diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4dffdc7..e6063e3e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,3 +39,15 @@ jobs: - name: Lint run: | yarn lint + + - name: YAML Lint + uses: ibiqlik/action-yamllint@v1.0.0 + with: + file_or_dir: translations/*.yaml + + - name: TSLint + run: | + cd gulp + yarn gulp translations.fullBuild + cd .. + yarn tslint diff --git a/.gitignore b/.gitignore index 3c599ecc..46dc1fd1 100644 --- a/.gitignore +++ b/.gitignore @@ -109,10 +109,6 @@ build tmp_standalone_files - -# Github Actions files -.github/workflows - # Local config config.local.js .DS_Store diff --git a/.travis.yml b/.travis.yml index 85abbc20..6b8b5e97 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,165 +3,164 @@ os: linux dist: xenial language: node_js node_js: - - "10" + - "12" cache: yarn # platform specific configuration jobs: + # jobs which have to succeed + include: + # OS: MAC + ## -> build darwin + # - name: "Standalone MacOS on MacOS" + # os: osx + # osx_image: xcode11.3 + # before_install: + # - HOMEBREW_NO_AUTO_UPDATE=1 brew install git-lfs + # - HOMEBREW_NO_AUTO_UPDATE=1 brew install ffmpeg + # script: + # - cd gulp + # - yarn gulp build.standalone-prod || travis_terminate 1 + # - yarn gulp standalone.prepare + # - yarn gulp standalone.package.prod.darwin64 + # - cd .. - # jobs which have to succeed - include: - # OS: MAC - ## -> build darwin - - name: "Standalone MacOS on MacOS" - os: osx - osx_image: xcode11.3 - before_install: - - HOMEBREW_NO_AUTO_UPDATE=1 brew install git-lfs - - HOMEBREW_NO_AUTO_UPDATE=1 brew install ffmpeg - script: - - cd gulp - - yarn gulp build.standalone-prod || travis_terminate 1 - - yarn gulp standalone.prepare - - yarn gulp standalone.package.prod.darwin64 - - cd .. + ## -> build win + # - name: "Standalone Windows on MacOS" + # os: osx + # osx_image: xcode11.3 + # before_install: + # - HOMEBREW_NO_AUTO_UPDATE=1 brew install git-lfs + # - HOMEBREW_NO_AUTO_UPDATE=1 brew install ffmpeg + # - HOMEBREW_NO_AUTO_UPDATE=1 brew cask install wine-stable + # # prevent Wine popup dialogs about installing additional packages + # - export WINEDLLOVERRIDES="mscoree,mshtml=" + # - export WINEDEBUG="-all" + # script: + # - cd gulp + # - yarn gulp build.standalone-prod || travis_terminate 1 + # - yarn gulp standalone.prepare + # - yarn gulp standalone.package.prod.win64 + # - yarn gulp standalone.package.prod.win32 + # - cd .. - ## -> build win - - name: "Standalone Windows on MacOS" - os: osx - osx_image: xcode11.3 - before_install: - - HOMEBREW_NO_AUTO_UPDATE=1 brew install git-lfs - - HOMEBREW_NO_AUTO_UPDATE=1 brew install ffmpeg - - HOMEBREW_NO_AUTO_UPDATE=1 brew cask install wine-stable - # prevent Wine popup dialogs about installing additional packages - - export WINEDLLOVERRIDES="mscoree,mshtml=" - - export WINEDEBUG="-all" - script: - - cd gulp - - yarn gulp build.standalone-prod || travis_terminate 1 - - yarn gulp standalone.prepare - - yarn gulp standalone.package.prod.win64 - - yarn gulp standalone.package.prod.win32 - - cd .. + ## -> build linux + # - name: "Standalone Linux on MacOS" + # os: osx + # osx_image: xcode11.3 + # before_install: + # - HOMEBREW_NO_AUTO_UPDATE=1 brew install git-lfs + # - HOMEBREW_NO_AUTO_UPDATE=1 brew install ffmpeg + # script: + # - cd gulp + # - yarn gulp build.standalone-prod || travis_terminate 1 + # - yarn gulp standalone.prepare + # - yarn gulp standalone.package.prod.linux64 + # - yarn gulp standalone.package.prod.linux32 + # - cd .. - ## -> build linux - - name: "Standalone Linux on MacOS" - os: osx - osx_image: xcode11.3 - before_install: - - HOMEBREW_NO_AUTO_UPDATE=1 brew install git-lfs - - HOMEBREW_NO_AUTO_UPDATE=1 brew install ffmpeg - script: - - cd gulp - - yarn gulp build.standalone-prod || travis_terminate 1 - - yarn gulp standalone.prepare - - yarn gulp standalone.package.prod.linux64 - - yarn gulp standalone.package.prod.linux32 - - cd .. + # OS: LINUX + ## -> build darwin + ## not possible - # OS: LINUX - ## -> build darwin - ## not possible + ## -> build win + # - name: "Standalone Windows on Linux" + # os: linux + # addons: + # apt: + # packages: + # - libavformat-dev + # - libavfilter-dev + # - libavdevice-dev + # - ffmpeg + # - wine + # script: + # - cd gulp + # - yarn gulp build.standalone-prod || travis_terminate 1 + # - yarn gulp standalone.prepare + # - yarn gulp standalone.package.prod.win64 + # - yarn gulp standalone.package.prod.win32 + # - cd .. - ## -> build win - - name: "Standalone Windows on Linux" - os: linux - addons: - apt: - packages: - - libavformat-dev - - libavfilter-dev - - libavdevice-dev - - ffmpeg - - wine - script: - - cd gulp - - yarn gulp build.standalone-prod || travis_terminate 1 - - yarn gulp standalone.prepare - - yarn gulp standalone.package.prod.win64 - - yarn gulp standalone.package.prod.win32 - - cd .. + ## -> build linux + # - name: "Standalone Linux on Linux" + # os: linux + # addons: + # apt: + # packages: + # - libavformat-dev + # - libavfilter-dev + # - libavdevice-dev + # - ffmpeg + # script: + # - cd gulp + # - yarn gulp build.standalone-prod || travis_terminate 1 + # - yarn gulp standalone.prepare + # - yarn gulp standalone.package.prod.linux64 + # - yarn gulp standalone.package.prod.linux32 + # - cd .. - ## -> build linux - - name: "Standalone Linux on Linux" - os: linux - addons: - apt: - packages: - - libavformat-dev - - libavfilter-dev - - libavdevice-dev - - ffmpeg - script: - - cd gulp - - yarn gulp build.standalone-prod || travis_terminate 1 - - yarn gulp standalone.prepare - - yarn gulp standalone.package.prod.linux64 - - yarn gulp standalone.package.prod.linux32 - - cd .. + # OS: WINDOWS + ## -> build darwin + ## not possible - # OS: WINDOWS - ## -> build darwin - ## not possible + ## -> build linux + # - name: "Standalone Linux on Windows" + # os: windows + # env: YARN_GPG=no + # before_install: + # - choco install git-lfs -y -f || echo "0" # choco fails but git-lfs is still installed + # - choco install ffmpeg --version=4.2.3 + # - export PATH=/C/ProgramData/chocolatey/lib/ffmpeg/tools/ffmpeg/bin:$PATH + # - wget https://github.com/moiamond/docker-ffmpeg-base-windowsservercore/raw/master/System32/avicap32.dll -P /C/Windows/System32/ + # - wget https://github.com/moiamond/docker-ffmpeg-base-windowsservercore/raw/master/System32/msvfw32.dll -P /C/Windows/System32/ + # script: + # - cd gulp + # - yarn gulp build.standalone-prod || travis_terminate 1 + # - yarn gulp standalone.prepare + # - yarn gulp standalone.package.prod.linux64 + # - yarn gulp standalone.package.prod.linux32 + # - cd .. - ## -> build linux - - name: "Standalone Linux on Windows" - os: windows - env: YARN_GPG=no - before_install: - - choco install git-lfs -y -f || echo "0" # choco fails but git-lfs is still installed - - choco install ffmpeg --version=4.2.3 - - export PATH=/C/ProgramData/chocolatey/lib/ffmpeg/tools/ffmpeg/bin:$PATH - - wget https://github.com/moiamond/docker-ffmpeg-base-windowsservercore/raw/master/System32/avicap32.dll -P /C/Windows/System32/ - - wget https://github.com/moiamond/docker-ffmpeg-base-windowsservercore/raw/master/System32/msvfw32.dll -P /C/Windows/System32/ - script: - - cd gulp - - yarn gulp build.standalone-prod || travis_terminate 1 - - yarn gulp standalone.prepare - - yarn gulp standalone.package.prod.linux64 - - yarn gulp standalone.package.prod.linux32 - - cd .. + ## -> build win + - name: "Standalone Windows on Windows" + os: windows + env: YARN_GPG=no + before_install: + - choco install git-lfs -y -f || echo "0" # choco fails but git-lfs is still installed + - choco install ffmpeg --version=4.2.3 + - choco install wget + - export PATH=/C/ProgramData/chocolatey/lib/ffmpeg/tools/ffmpeg/bin:$PATH + - wget https://github.com/moiamond/docker-ffmpeg-base-windowsservercore/raw/master/System32/avicap32.dll -P /C/Windows/System32/ + - wget https://github.com/moiamond/docker-ffmpeg-base-windowsservercore/raw/master/System32/msvfw32.dll -P /C/Windows/System32/ + script: + - cd gulp + - yarn gulp build.standalone-prod || travis_terminate 1 + - yarn gulp standalone.prepare + - yarn gulp standalone.package.prod.win64 + - yarn gulp standalone.package.prod.win32 + - cd .. - ## -> build win - - name: "Standalone Windows on Windows" - os: windows - env: YARN_GPG=no - before_install: - - choco install git-lfs -y -f || echo "0" # choco fails but git-lfs is still installed - - choco install ffmpeg --version=4.2.3 - - choco install wget - - export PATH=/C/ProgramData/chocolatey/lib/ffmpeg/tools/ffmpeg/bin:$PATH - - wget https://github.com/moiamond/docker-ffmpeg-base-windowsservercore/raw/master/System32/avicap32.dll -P /C/Windows/System32/ - - wget https://github.com/moiamond/docker-ffmpeg-base-windowsservercore/raw/master/System32/msvfw32.dll -P /C/Windows/System32/ - script: - - cd gulp - - yarn gulp build.standalone-prod || travis_terminate 1 - - yarn gulp standalone.prepare - - yarn gulp standalone.package.prod.win64 - - yarn gulp standalone.package.prod.win32 - - cd .. + # mark build as finished even if "allow_failures" are still running + fast_finish: true - # mark build as finished even if "allow_failures" are still running - fast_finish: true + # optional jobs which may fail + #allow_failures: + # - name: "" - # optional jobs which may fail - #allow_failures: - # - name: "" - # shared install: - - git lfs install - - git lfs pull + - git lfs install + - git lfs pull - - yarn - - # electron dependencies - - cd electron - - yarn - - cd .. + - yarn - # gulp dependendencies - - cd gulp - - yarn - - cd .. + # electron dependencies + - cd electron + - yarn + - cd .. + + # gulp dependendencies + - cd gulp + - yarn + - cd .. diff --git a/.yamllint b/.yamllint new file mode 100644 index 00000000..98e73204 --- /dev/null +++ b/.yamllint @@ -0,0 +1,6 @@ +extends: default + +rules: + line-length: + level: warning + max: 200 diff --git a/README.md b/README.md index 5a5847aa..32e09d59 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,15 @@ Your goal is to produce shapes by cutting, rotating, merging and painting parts - [Steam Page](https://steam.shapez.io) - [Official Discord](https://discord.com/invite/HN7EVzV) <- _Highly recommended to join!_ +## Reporting issues, suggestions, feedback, bugs + +1. Ask in `#bugs` / `#feedback` / `#questions` on the [Official Discord](https://discord.com/invite/HN7EVzV) if you are not entirely sure if it's a bug etc. +2. Check out the trello board: https://trello.com/b/ISQncpJP/shapezio +3. See if it's already there - If so, vote for it, done. I will see it. (You have to be signed in on trello) +4. If not, check if it's already reported here: https://github.com/tobspr/shapez.io/issues +5. If not, file a new issue here: https://github.com/tobspr/shapez.io/issues/new +6. I will then have a look (This can take days or weeks) and convert it to trello, and comment with the link. You can then vote there ;) + ## Building - Make sure git `git lfs` extension is on your path @@ -41,11 +50,48 @@ If you want to add a new feature or in generally contribute I recommend to get i ### Code -The game is based on a custom engine which itself is based on the YORG.io 3 game egine (Actually it shares almost the same core). +The game is based on a custom engine which itself is based on the YORG.io 3 game engine (Actually it shares almost the same core). The code within the engine is relatively clean with some code for the actual game on top being hacky. This project is based on ES5. Some ES2015 features are used but most of them are too slow, especially when polyfilled. For example, `Array.prototype.forEach` is only used within non-critical loops since its slower than a plain for loop. +#### Adding a new component + +1. Create the component file in `src/js/game/components/.js` +2. Create a component class (e.g. `MyFancyComponent`) which `extends Component` +3. Create a `static getId()` method which should return the `PascalCaseName` without component (e.g. `MyFancy`) +4. If any data needs to be persisted, create a `static getSchema()` which should return the properties to be saved (See other components) +5. Add a constructor. **The constructor must be called with optional parameters only!** `new MyFancyComponent({})` should always work. +6. Add any props you need in the constructor. +7. Add the component in `src/js/game/component_registry.js` +8. Add the componetn in `src/js/game/entity_components.js` +9. Done! You can use your component now + +#### Adding a new building + +(The easiest way is to copy an existing building) + +1. Create your building in `src/js/game/buildings/` +2. Create the building meta class, e.g. `MetaMyFancyBuilding extends MetaBuilding` +3. Override the methods from MetaBuilding you want to override. +4. Most important is `setupEntityComponents` +5. Add the building to `src/js/game/meta_building_registry.js`: You need to register it on the registry, and also call `registerBuildingVariant`. +6. Add the building to the right toolbar, e.g. `src/js/game/hud/parts/buildings_toolbar.js`:`supportedBuildings` +7. Add a keybinding for the building in `src/js/game/key_action_mapper.js` in `KEYMAPPINGS.buildings` +8. In `translations/base-en.yaml` add it to two sections: `buildings.[my_building].XXX` (See other buildings) and also `keybindings.mappings.[my_building]`. Be sure to do it the same way as other buildings do! +9. Create a icon (128x128, [prefab](https://github.com/tobspr/shapez.io-artwork/blob/master/ui/toolbar-icons.psd)) for your building and save it in `res/ui/buildings_icons` with the id of your building +10. Create a tutorial image (600x600) for your building and save it in `res/ui/building_tutorials` +11. In `src/css/icons.scss` add your building to `$buildings` as well as `$buildingAndVariants` +12. Done! Optional: Add a new reward for unlocking your building at some point. + +#### Adding a new game system + +1. Create the class in `src/js/game/systems/.js` +2. Derive it from `GameSystemWithFilter` if you want it to work on certain entities only which have the given components. Otherwise use `GameSystem` to do more generic stuff. +3. Implement the `update()` method. +4. Add the system in `src/js/game/game_system_manager.js` (To `this.systems` and also call `add` in the `internalInitSystems()` method) +5. If your system should draw stuff, this is a bit more complicated. Have a look at existing systems on how they do it. + ### Assets For most assets I use Adobe Photoshop, you can find them in `assets/`. diff --git a/buildutils.js b/buildutils.js deleted file mode 100644 index 5342650f..00000000 --- a/buildutils.js +++ /dev/null @@ -1,44 +0,0 @@ -const glob = require("glob"); -const execSync = require("child_process").execSync; -const trim = require("trim"); -const fs = require("fs"); -const path = require("path"); - -module.exports = { - getRevision: function (useLast = false) { - const commitHash = execSync("git rev-parse --short " + (useLast ? "HEAD^1" : "HEAD")).toString("ascii"); - return commitHash.replace(/^\s+|\s+$/g, ""); - }, - getAllResourceImages() { - return glob - .sync("res/**/*.@(png|svg|jpg)", { cwd: ".." }) - .map((f) => f.replace(/^res\//gi, "")) - .filter((f) => { - if (f.indexOf("ui") >= 0) { - // We drop all ui images except for the noinline ones - return f.indexOf("noinline") >= 0; - } - return true; - }); - }, - - getAllAtlasImages() { - return glob.sync("res_built/atlas/*.png", { cwd: ".." }).map((s) => s.replace("res_built/atlas/", "res/")); - }, - - getAllSounds() { - return glob.sync("res_built/sounds/**/*.mp3", { cwd: ".." }).map((s) => s.replace("res_built/sounds/", "res/sounds/")); - }, - - getVersion() { - return trim(fs.readFileSync(path.join(__dirname, "version")).toString()); - }, - - /** - * @param {string} url - * @param {string} commitHash - */ - cachebust(url, commitHash) { - return "/v/" + commitHash + "/" + url; - }, -}; diff --git a/gulp/buildutils.js b/gulp/buildutils.js index 1fb2a9a3..041c8b1d 100644 --- a/gulp/buildutils.js +++ b/gulp/buildutils.js @@ -11,6 +11,7 @@ module.exports = { ); return commitHash.replace(/^\s+|\s+$/g, ""); }, + getAllResourceImages() { return glob .sync("res/**/*.@(png|svg|jpg)", { cwd: ".." }) @@ -24,18 +25,6 @@ module.exports = { }); }, - getAllAtlasImages() { - return glob - .sync("res_built/atlas/*.png", { cwd: ".." }) - .map(s => s.replace("res_built/atlas/", "res/")); - }, - - getAllSounds() { - return glob - .sync("res_built/sounds/**/*.mp3", { cwd: ".." }) - .map(s => s.replace("res_built/sounds/", "res/sounds/")); - }, - getVersion() { return trim(fs.readFileSync(path.join(__dirname, "..", "version")).toString()); }, diff --git a/gulp/cordova.js b/gulp/cordova.js index dc968df0..22274dba 100644 --- a/gulp/cordova.js +++ b/gulp/cordova.js @@ -132,25 +132,6 @@ function gulptasksCordova($, gulp, buildFolder) { }) ); }); - - // gulp.task("pushToStagingRepo", (cb) => { - // var cmd = spawn('../push-pgb.sh', ['https://TOKEN@github.com/tobspr/shapezapp-cordova-buildslave.git'], - // { stdio: 'inherit', stdout: 'inherit', stderr: 'inherit', shell: true }); - // cmd.on('close', function (code) { - // console.log('push staging exited with code ' + code + " / " + cmd.stdout + " / " + cmd.stderr); - // cb(code); - // }); - - // }); - - // gulp.task("pushToProdRepo", (cb) => { - // var cmd = spawn('../push-pgb.sh', ['https://TOKEN@github.com/tobspr/shapezapp-cordova-buildslave-release.git'], - // { stdio: 'inherit', stdout: 'inherit', stderr: 'inherit', shell: true }); - // cmd.on('close', function (code) { - // console.log('push prod exited with code ' + code + " / " + cmd.stdout + " / " + cmd.stderr); - // cb(code); - // }); - // }); } module.exports = { diff --git a/gulp/css.js b/gulp/css.js index 729d0432..6734f1ae 100644 --- a/gulp/css.js +++ b/gulp/css.js @@ -77,7 +77,6 @@ function gulptasksCSS($, gulp, buildFolder, browserSync) { .pipe($.plumber()) .pipe($.sass.sync({ outputStyle: "compressed" }).on("error", $.sass.logError)) .pipe($.postcss(postcssPlugins(true, { cachebust: true }))) - // .pipe($.cssbeautify()) .pipe(gulp.dest(buildFolder)) ); }); @@ -90,7 +89,6 @@ function gulptasksCSS($, gulp, buildFolder, browserSync) { .pipe($.plumber()) .pipe($.sass.sync({ outputStyle: "compressed" }).on("error", $.sass.logError)) .pipe($.postcss(postcssPlugins(true, { cachebust: false }))) - // .pipe($.cssbeautify()) .pipe(gulp.dest(buildFolder)) ); }); diff --git a/gulp/html.js b/gulp/html.js index a21d66cb..b49fc1b2 100644 --- a/gulp/html.js +++ b/gulp/html.js @@ -9,7 +9,7 @@ function computeIntegrityHash(fullPath, algorithm = "sha256") { return algorithm + "-" + hash; } -function gulptasksHTML($, gulp, buildFolder, browserSync) { +function gulptasksHTML($, gulp, buildFolder) { const commitHash = buildUtils.getRevision(); async function buildHtml( apiUrl, @@ -27,9 +27,8 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { return gulp .src("../src/html/" + (standalone ? "index.standalone.html" : "index.html")) .pipe( - $.dom(function () { - // @ts-ignore - const document = /** @type {Document} */ (this); + $.dom(/** @this {Document} **/ function () { + const document = this; // Preconnect to api const prefetchLink = document.createElement("link"); @@ -38,21 +37,6 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { prefetchLink.setAttribute("crossorigin", "anonymous"); document.head.appendChild(prefetchLink); - // // Append css preload - // const cssPreload = document.createElement("link"); - // cssPreload.rel = "preload"; - // cssPreload.href = cachebust("main.css"); - // cssPreload.setAttribute("as", "style"); - // document.head.appendChild(cssPreload); - // document.head.appendChild(prefetchLink); - - // // Append js preload - // const jsPreload = document.createElement("link"); - // jsPreload.rel = "preload"; - // jsPreload.href = cachebust("bundle.js"); - // jsPreload.setAttribute("as", "script"); - // document.head.appendChild(jsPreload); - // Append css const css = document.createElement("link"); css.rel = "stylesheet"; @@ -68,17 +52,6 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { } document.head.appendChild(css); - if (analytics) { - // Logrocket - // const logrocketScript = document.createElement("script"); - // logrocketScript.src = "https://cdn.lr-ingest.io/LogRocket.min.js"; - // logrocketScript.setAttribute("crossorigin", "anonymous"); - // document.head.appendChild(logrocketScript); - // const logrocketInit = document.createElement("script"); - // logrocketInit.textContent = "window.LogRocket && window.LogRocket.init('TODO: GET LOGROCKET ID');"; - // document.head.appendChild(logrocketInit); - } - if (app) { // Append cordova link const cdv = document.createElement("script"); @@ -114,18 +87,9 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { // Do not need to preload in app or standalone if (!hasLocalFiles) { - // Preload images - const images = buildUtils.getAllResourceImages(); - // Preload essentials const preloads = ["fonts/GameFont.woff2"]; - // for (let i = 0; i < images.length; ++i) { - // if (preloads.indexOf(images[i]) < 0) { - // preloads.push(images[i]); - // } - // } - preloads.forEach(src => { const preloadLink = document.createElement("link"); preloadLink.rel = "preload"; @@ -138,23 +102,6 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { } document.head.appendChild(preloadLink); }); - - // Sound preloads - // const sounds = buildUtils.getAllSounds(); - // sounds.forEach((src) => { - - // if (src.indexOf("sounds/music/") >= 0) { - // // skip music - // return; - // } - - // const preloadLink = document.createElement("link"); - // preloadLink.rel = "preload"; - // preloadLink.href = cachebust(src); - // // preloadLink.setAttribute("crossorigin", "anonymous"); - // preloadLink.setAttribute("as", "fetch"); - // document.head.appendChild(preloadLink); - // }); } const loadingSvg = `background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46YXV0bztiYWNrZ3JvdW5kOjAgMCIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCIgZGlzcGxheT0iYmxvY2siPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzM5Mzc0NyIgc3Ryb2tlLXdpZHRoPSIzIiByPSI0MiIgc3Ryb2tlLWRhc2hhcnJheT0iMTk3LjkyMDMzNzE3NjE1Njk4IDY3Ljk3MzQ0NTcyNTM4NTY2IiB0cmFuc2Zvcm09InJvdGF0ZSg0OC4yNjUgNTAgNTApIj48YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIGR1cj0iNS41NTU1NTU1NTU1NTU1NTVzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIi8+PC9jaXJjbGU+PC9zdmc+")`; @@ -167,7 +114,7 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { font-display: swap; src: url('${cachebust("res/fonts/GameFont.woff2")}') format('woff2'); } - + #ll_fp { font-family: GameFont; font-size: 14px; @@ -177,7 +124,7 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { left: 0; opacity: 0.05; } - + #ll_p { display: flex; position: fixed; @@ -190,7 +137,7 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { center; align-items: center; } - + #ll_p > div { position: absolute; text-align: center; @@ -201,7 +148,7 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { font-family: 'GameFont', sans-serif; font-size: 20px; } - + #ll_p > span { width: 60px; height: 60px; diff --git a/gulp/js.js b/gulp/js.js index 6faccfca..28c037bd 100644 --- a/gulp/js.js +++ b/gulp/js.js @@ -6,12 +6,6 @@ function requireUncached(module) { } function gulptasksJS($, gulp, buildFolder, browserSync) { - gulp.task("js.prettify", () => { - return gulp - .src(path.join(buildFolder, "bundle.js")) - .pipe($.jsbeautifier(require("./jsbeautify.json"))) - .pipe(gulp.dest(buildFolder)); - }); //// DEV @@ -71,6 +65,7 @@ function gulptasksJS($, gulp, buildFolder, browserSync) { gulp.task("js.staging", gulp.parallel("js.staging.transpiled", "js.staging.latest")); //// PROD + gulp.task("js.prod.transpiled", () => { return gulp .src("../src/js/main.js") @@ -167,8 +162,6 @@ function gulptasksJS($, gulp, buildFolder, browserSync) { ) .pipe(gulp.dest(buildFolder)); }); - - // TODO: Tasks for te app } module.exports = { diff --git a/gulp/package.json b/gulp/package.json index 1fd39c40..9c3d0182 100644 --- a/gulp/package.json +++ b/gulp/package.json @@ -3,7 +3,6 @@ "version": "1.0.0", "description": "builder", "private": true, - "main": "main.js", "scripts": { "gulp": "gulp" }, @@ -20,7 +19,7 @@ "ajv": "^6.10.2", "audiosprite": "^0.7.2", "babel-loader": "^8.1.0", - "browser-sync": "^2.24.6", + "browser-sync": "^2.26.10", "circular-dependency-plugin": "^5.0.2", "circular-json": "^0.5.9", "clipboard-copy": "^3.1.0", @@ -41,21 +40,18 @@ "lz-string": "^1.4.4", "markdown-loader": "^5.1.0", "node-sri": "^1.1.1", - "obfuscator-loader": "^1.1.2", "phonegap-plugin-mobile-accessibility": "^1.0.5", "promise-polyfill": "^8.1.0", "query-string": "^6.8.1", "rusha": "^0.8.13", "serialize-error": "^3.0.0", - "sloc": "^0.2.1", "strictdom": "^1.0.1", "string-replace-webpack-plugin": "^0.1.3", "terser-webpack-plugin": "^1.1.0", "through2": "^3.0.1", "uglify-template-string-loader": "^1.1.0", "unused-files-webpack-plugin": "^3.4.0", - "webpack": "^4.31.0", - "webpack-bundle-analyzer": "^3.0.3", + "webpack": "^4.43.0", "webpack-cli": "^3.1.0", "webpack-deep-scope-plugin": "^1.6.0", "webpack-plugin-replace": "^1.1.1", @@ -77,8 +73,6 @@ "gulp-cache": "^1.1.3", "gulp-cached": "^1.1.1", "gulp-clean": "^0.4.0", - "gulp-cssbeautify": "^2.0.1", - "gulp-csslint": "^1.0.1", "gulp-dom": "^1.0.0", "gulp-flatten": "^0.4.0", "gulp-fluent-ffmpeg": "^2.0.0", @@ -86,8 +80,6 @@ "gulp-htmlmin": "^5.0.1", "gulp-if": "^3.0.0", "gulp-imagemin": "^7.1.0", - "gulp-javascript-obfuscator": "^1.1.5", - "gulp-jsbeautifier": "^3.0.0", "gulp-load-plugins": "^2.0.3", "gulp-phonegap-build": "^0.1.5", "gulp-plumber": "^1.2.1", @@ -105,16 +97,14 @@ "imagemin-pngquant": "^9.0.0", "jimp": "^0.6.1", "js-yaml": "^3.13.1", - "onesky-fetch": "^0.0.7", "postcss-assets": "^5.0.0", "postcss-preset-env": "^6.5.0", "postcss-round-subpixels": "^1.2.0", "postcss-unprefix": "^2.1.3", "sass-unused": "^0.3.0", - "speed-measure-webpack-plugin": "^1.3.1", "strip-json-comments": "^3.0.1", "trim": "^0.0.1", - "webpack-stream": "^5.1.0", + "webpack-stream": "^5.2.1", "yaml-loader": "^0.6.0" } } diff --git a/gulp/standalone.js b/gulp/standalone.js index c4f33417..3b0112d4 100644 --- a/gulp/standalone.js +++ b/gulp/standalone.js @@ -1,11 +1,11 @@ const packager = require("electron-packager"); const path = require("path"); -const buildutils = require("./buildutils"); +const { getVersion } = require("./buildutils"); const fs = require("fs"); const fse = require("fs-extra"); const execSync = require("child_process").execSync; -function gulptasksStandalone($, gulp, buildFolder) { +function gulptasksStandalone($, gulp) { const electronBaseDir = path.join(__dirname, "..", "electron"); const tempDestDir = path.join(__dirname, "..", "tmp_standalone_files"); @@ -47,49 +47,7 @@ function gulptasksStandalone($, gulp, buildFolder) { }); gulp.task("standalone.prepare.minifyCode", () => { - return ( - gulp - .src(path.join(electronBaseDir, "*.js")) - // .pipe( - // $.terser({ - // ecma: 6, - // parse: {}, - // module: false, - // toplevel: true, - // keep_classnames: false, - // keep_fnames: false, - // safari10: false, - // compress: { - // arguments: false, // breaks - // drop_console: false, - // // keep_fargs: false, - // keep_infinity: true, - // passes: 2, - // module: false, - // toplevel: true, - // unsafe_math: true, - // unsafe_arrows: false, - // warnings: true, - // }, - // mangle: { - // eval: true, - // keep_classnames: false, - // keep_fnames: false, - // module: false, - // toplevel: true, - // safari10: false, - // }, - // output: { - // comments: false, - // ascii_only: true, - // beautify: false, - // braces: false, - // ecma: 6, - // }, - // }) - // ) - .pipe(gulp.dest(tempDestBuildDir)) - ); + return gulp.src(path.join(electronBaseDir, "*.js")).pipe(gulp.dest(tempDestBuildDir)); }); gulp.task("standalone.prepare.copyGamefiles", () => { @@ -122,15 +80,14 @@ function gulptasksStandalone($, gulp, buildFolder) { * @param {'win32'|'linux'|'darwin'} platform * @param {'x64'|'ia32'} arch * @param {function():void} cb - * @param {boolean=} isRelease */ - function packageStandalone(platform, arch, cb, isRelease = false) { + function packageStandalone(platform, arch, cb) { const tomlFile = fs.readFileSync(path.join(__dirname, ".itch.toml")); packager({ dir: tempDestBuildDir, appCopyright: "Tobias Springer", - appVersion: buildutils.getVersion(), + appVersion: getVersion(), buildVersion: "1.0.0", arch, platform, @@ -164,19 +121,6 @@ function gulptasksStandalone($, gulp, buildFolder) { '#!/usr/bin/env bash\n./shapezio --no-sandbox "$@"\n' ); fs.chmodSync(path.join(appPath, "play.sh"), 0o775); - } else if (platform === "win32") { - // Optional: Create a playable copy. Shouldn't be required - // const playablePath = appPath + "_playable"; - // fse.copySync(appPath, playablePath); - // fs.writeFileSync(path.join(playablePath, "steam_appid.txt"), "1134480"); - // fs.writeFileSync( - // path.join(playablePath, "play.bat"), - // "start shapezio --dev --disable-direct-composition --in-process-gpu\r\n" - // ); - // fs.writeFileSync( - // path.join(playablePath, "play_local.bat"), - // "start shapezio --local --dev --disable-direct-composition --in-process-gpu\r\n" - // ); } if (platform === "darwin") { @@ -226,11 +170,11 @@ function gulptasksStandalone($, gulp, buildFolder) { ); } - gulp.task("standalone.package.prod.win64", cb => packageStandalone("win32", "x64", cb, true)); - gulp.task("standalone.package.prod.win32", cb => packageStandalone("win32", "ia32", cb, true)); - gulp.task("standalone.package.prod.linux64", cb => packageStandalone("linux", "x64", cb, true)); - gulp.task("standalone.package.prod.linux32", cb => packageStandalone("linux", "ia32", cb, true)); - gulp.task("standalone.package.prod.darwin64", cb => packageStandalone("darwin", "x64", cb, true)); + gulp.task("standalone.package.prod.win64", cb => packageStandalone("win32", "x64", cb)); + gulp.task("standalone.package.prod.win32", cb => packageStandalone("win32", "ia32", cb)); + gulp.task("standalone.package.prod.linux64", cb => packageStandalone("linux", "x64", cb)); + gulp.task("standalone.package.prod.linux32", cb => packageStandalone("linux", "ia32", cb)); + gulp.task("standalone.package.prod.darwin64", cb => packageStandalone("darwin", "x64", cb)); gulp.task( "standalone.package.prod", @@ -240,8 +184,6 @@ function gulptasksStandalone($, gulp, buildFolder) { "standalone.package.prod.win64", "standalone.package.prod.linux64", "standalone.package.prod.darwin64" - // "standalone.package.prod.win32", - // "standalone.package.prod.linux32", ) ) ); diff --git a/gulp/translations.js b/gulp/translations.js index 50404390..56054476 100644 --- a/gulp/translations.js +++ b/gulp/translations.js @@ -5,7 +5,7 @@ const yaml = require("gulp-yaml"); const translationsSourceDir = path.join(__dirname, "..", "translations"); const translationsJsonDir = path.join(__dirname, "..", "src", "js", "built-temp"); -function gulptasksTranslations($, gulp, buildFolder) { +function gulptasksTranslations($, gulp) { gulp.task("translations.convertToJson", () => { return gulp .src(path.join(translationsSourceDir, "*.yaml")) diff --git a/gulp/webpack.config.js b/gulp/webpack.config.js index 26923796..6e1d7388 100644 --- a/gulp/webpack.config.js +++ b/gulp/webpack.config.js @@ -2,9 +2,8 @@ const path = require("path"); const webpack = require("webpack"); -const utils = require("./buildutils"); +const { getRevision, getVersion, getAllResourceImages } = require("./buildutils"); const lzString = require("lz-string"); -// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const CircularDependencyPlugin = require("circular-dependency-plugin"); module.exports = ({ watch = false, standalone = false }) => { @@ -41,9 +40,9 @@ module.exports = ({ watch = false, standalone = false }) => { G_IS_BROWSER: "true", G_IS_STANDALONE: standalone ? "true" : "false", G_BUILD_TIME: "" + new Date().getTime(), - G_BUILD_COMMIT_HASH: JSON.stringify(utils.getRevision()), - G_BUILD_VERSION: JSON.stringify(utils.getVersion()), - G_ALL_UI_IMAGES: JSON.stringify(utils.getAllResourceImages()), + G_BUILD_COMMIT_HASH: JSON.stringify(getRevision()), + G_BUILD_VERSION: JSON.stringify(getVersion()), + G_ALL_UI_IMAGES: JSON.stringify(getAllResourceImages()), }), new CircularDependencyPlugin({ @@ -60,7 +59,6 @@ module.exports = ({ watch = false, standalone = false }) => { // set the current working directory for displaying module paths cwd: path.join(__dirname, "..", "src", "js"), }), - // new BundleAnalyzerPlugin() ], module: { rules: [ diff --git a/gulp/webpack.production.config.js b/gulp/webpack.production.config.js index 1b89283f..c26bca68 100644 --- a/gulp/webpack.production.config.js +++ b/gulp/webpack.production.config.js @@ -2,14 +2,12 @@ const path = require("path"); const webpack = require("webpack"); -const utils = require("./buildutils"); +const { getRevision, getVersion, getAllResourceImages } = require("./buildutils"); const lzString = require("lz-string"); const TerserPlugin = require("terser-webpack-plugin"); const StringReplacePlugin = require("string-replace-webpack-plugin"); -// const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin; const UnusedFilesPlugin = require("unused-files-webpack-plugin").UnusedFilesWebpackPlugin; -// const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); module.exports = ({ enableAssert = false, @@ -34,9 +32,9 @@ module.exports = ({ G_APP_ENVIRONMENT: JSON.stringify(environment), G_HAVE_ASSERT: enableAssert ? "true" : "false", G_BUILD_TIME: "" + new Date().getTime(), - G_BUILD_COMMIT_HASH: JSON.stringify(utils.getRevision()), - G_BUILD_VERSION: JSON.stringify(utils.getVersion()), - G_ALL_UI_IMAGES: JSON.stringify(utils.getAllResourceImages()), + G_BUILD_COMMIT_HASH: JSON.stringify(getRevision()), + G_BUILD_VERSION: JSON.stringify(getVersion()), + G_ALL_UI_IMAGES: JSON.stringify(getAllResourceImages()), }; const minifyNames = environment === "prod"; @@ -143,9 +141,9 @@ module.exports = ({ ecma: es6 ? 6 : 5, preamble: "/* shapez.io Codebase - Copyright 2020 Tobias Springer - " + - utils.getVersion() + + getVersion() + " @ " + - utils.getRevision() + + getRevision() + " */", }, }, @@ -164,15 +162,6 @@ module.exports = ({ cwd: path.join(__dirname, "..", "src", "js"), patterns: ["../src/js/**/*.js"], }), - - // new webpack.SourceMapDevToolPlugin({ - // filename: "[name].map", - // publicPath: "/v/" + utils.getRevision() + "/", - // }), - // new ReplaceCompressBlocks() - // new webpack.optimize.ModuleConcatenationPlugin() - // new WebpackDeepScopeAnalysisPlugin() - // new BundleAnalyzerPlugin() ], module: { rules: [ diff --git a/gulp/yarn.lock b/gulp/yarn.lock index a0a8d4f2..d0628aa3 100644 --- a/gulp/yarn.lock +++ b/gulp/yarn.lock @@ -718,21 +718,6 @@ js-levenshtein "^1.1.3" semver "^5.5.0" -"@babel/runtime@7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0-beta.42.tgz#352e40c92e0460d3e82f49bd7e79f6cda76f919f" - integrity sha512-iOGRzUoONLOtmCvjUsZv3mZzgCT6ljHQY5fr1qG1QIiJQwtM7zbPWGGpa3QWETq+UqwWyJnoi5XZDZRwZDFciQ== - dependencies: - core-js "^2.5.3" - regenerator-runtime "^0.11.1" - -"@babel/runtime@7.0.0-rc.1": - version "7.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0-rc.1.tgz#42f36fc5817911c89ea75da2b874054922967616" - integrity sha512-Nifv2kwP/nwR39cAOasNxzjYfpeuf/ZbZNtQz5eYxWTC9yHARU9wItFnAwz1GTZ62MU+AtSjzZPMbLK5Q9hmbg== - dependencies: - regenerator-runtime "^0.12.0" - "@babel/runtime@^7.5.5": version "7.9.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" @@ -1163,150 +1148,149 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== -"@webassemblyjs/ast@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" - integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ== +"@webassemblyjs/ast@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== dependencies: - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" -"@webassemblyjs/floating-point-hex-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721" - integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ== +"@webassemblyjs/floating-point-hex-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== -"@webassemblyjs/helper-api-error@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7" - integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA== +"@webassemblyjs/helper-api-error@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== -"@webassemblyjs/helper-buffer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204" - integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q== +"@webassemblyjs/helper-buffer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== -"@webassemblyjs/helper-code-frame@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e" - integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ== +"@webassemblyjs/helper-code-frame@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== dependencies: - "@webassemblyjs/wast-printer" "1.8.5" + "@webassemblyjs/wast-printer" "1.9.0" -"@webassemblyjs/helper-fsm@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452" - integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow== +"@webassemblyjs/helper-fsm@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== -"@webassemblyjs/helper-module-context@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245" - integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g== +"@webassemblyjs/helper-module-context@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== dependencies: - "@webassemblyjs/ast" "1.8.5" - mamacro "^0.0.3" + "@webassemblyjs/ast" "1.9.0" -"@webassemblyjs/helper-wasm-bytecode@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61" - integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ== +"@webassemblyjs/helper-wasm-bytecode@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== -"@webassemblyjs/helper-wasm-section@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf" - integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA== +"@webassemblyjs/helper-wasm-section@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" -"@webassemblyjs/ieee754@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e" - integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g== +"@webassemblyjs/ieee754@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" + integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10" - integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A== +"@webassemblyjs/leb128@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" + integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc" - integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw== +"@webassemblyjs/utf8@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== -"@webassemblyjs/wasm-edit@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a" - integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q== +"@webassemblyjs/wasm-edit@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/helper-wasm-section" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-opt" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - "@webassemblyjs/wast-printer" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/helper-wasm-section" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-opt" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + "@webassemblyjs/wast-printer" "1.9.0" -"@webassemblyjs/wasm-gen@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc" - integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg== +"@webassemblyjs/wasm-gen@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" -"@webassemblyjs/wasm-opt@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264" - integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q== +"@webassemblyjs/wasm-opt@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" -"@webassemblyjs/wasm-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d" - integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw== +"@webassemblyjs/wasm-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" -"@webassemblyjs/wast-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c" - integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg== +"@webassemblyjs/wast-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/floating-point-hex-parser" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-code-frame" "1.8.5" - "@webassemblyjs/helper-fsm" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/floating-point-hex-parser" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-code-frame" "1.9.0" + "@webassemblyjs/helper-fsm" "1.9.0" "@xtuc/long" "4.2.2" -"@webassemblyjs/wast-printer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc" - integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg== +"@webassemblyjs/wast-printer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" + integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": @@ -1329,7 +1313,7 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -accepts@~1.3.4, accepts@~1.3.7: +accepts@~1.3.4: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== @@ -1352,19 +1336,12 @@ acorn-jsx@^3.0.0: dependencies: acorn "^3.0.4" -acorn-jsx@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-4.1.1.tgz#e8e41e48ea2fe0c896740610ab6a4ffd8add225e" - integrity sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw== - dependencies: - acorn "^5.0.3" - acorn-jsx@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f" integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw== -acorn-walk@^6.0.1, acorn-walk@^6.1.1: +acorn-walk@^6.0.1: version "6.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== @@ -1374,16 +1351,21 @@ acorn@^3.0.4: resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= -acorn@^5.0.3, acorn@^5.5.0, acorn@^5.6.0: +acorn@^5.5.0: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== -acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.7, acorn@^6.2.1: +acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.7: version "6.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== +acorn@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" + integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== + after@0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" @@ -1449,7 +1431,7 @@ ansi-colors@^1.0.1: dependencies: ansi-wrap "^0.1.0" -ansi-colors@^4.1.0, ansi-colors@^4.1.1: +ansi-colors@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== @@ -1505,6 +1487,11 @@ ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + ansi-styles@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" @@ -1522,7 +1509,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== @@ -1548,6 +1535,14 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + append-buffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" @@ -1668,11 +1663,6 @@ array-find-index@^1.0.1: resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - array-initial@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795" @@ -1707,19 +1697,12 @@ array-sort@^1.0.0: get-value "^2.0.6" kind-of "^5.0.2" -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array-uniq@^1.0.1, array-uniq@^1.0.2: +array-uniq@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= @@ -1739,11 +1722,6 @@ arraybuffer.slice@~0.0.7: resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - asar@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/asar/-/asar-2.0.1.tgz#8518a1c62c238109c15a5f742213e83a09b9fd38" @@ -1887,13 +1865,6 @@ async@~1.0.0: resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" integrity sha1-+PwEyjoTeErenhZBr5hXjPvWR6k= -async@~2.1.4: - version "2.1.5" - resolved "https://registry.yarnpkg.com/async/-/async-2.1.5.tgz#e587c68580994ac67fc56ff86d3ac56bdbe810bc" - integrity sha1-5YfGhYCZSsZ/xW/4bTrFa9voELw= - dependencies: - lodash "^4.14.0" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1985,23 +1956,6 @@ babel-plugin-dynamic-import-node@^2.3.0: dependencies: object.assign "^4.1.0" -babel-polyfill@6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" - integrity sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0= - dependencies: - babel-runtime "^6.22.0" - core-js "^2.4.0" - regenerator-runtime "^0.10.0" - -babel-runtime@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - babel-runtime@^7.0.0-beta.3: version "7.0.0-beta.3" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-7.0.0-beta.3.tgz#7c750de5514452c27612172506b49085a4a630f2" @@ -2087,16 +2041,6 @@ better-assert@~1.0.0: dependencies: callsite "1.0.0" -bfj@^6.1.1: - version "6.1.2" - resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.2.tgz#325c861a822bcb358a41c78a33b8e6e2086dde7f" - integrity sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw== - dependencies: - bluebird "^3.5.5" - check-types "^8.0.3" - hoopy "^0.1.4" - tryer "^1.0.1" - big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" @@ -2160,6 +2104,11 @@ binary-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== +binary-extensions@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" + integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== + bl@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/bl/-/bl-0.7.0.tgz#3fb0670602ac2878eb770dc2039f1836be62ae5b" @@ -2209,22 +2158,6 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" - body-parser@~1.8.0: version "1.8.4" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.8.4.tgz#d497e04bc13b3f9a8bd8c70bb0cdc16f2e028898" @@ -2268,7 +2201,7 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.1: +braces@^3.0.1, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -2285,20 +2218,20 @@ browser-process-hrtime@^0.1.2: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw== -browser-sync-client@^2.26.6: - version "2.26.6" - resolved "https://registry.yarnpkg.com/browser-sync-client/-/browser-sync-client-2.26.6.tgz#e5201d3ace8aee88af17656b7b0c0620b6f8e4ab" - integrity sha512-mGrkZdNzttKdf/16I+y+2dTQxoMCIpKbVIMJ/uP8ZpnKu9f9qa/2CYVtLtbjZG8nsM14EwiCrjuFTGBEnT3Gjw== +browser-sync-client@^2.26.10: + version "2.26.10" + resolved "https://registry.yarnpkg.com/browser-sync-client/-/browser-sync-client-2.26.10.tgz#ca9309ba19f9695e7945b95062da8a7ef3156711" + integrity sha512-8pYitKwpVva7hzXJI8lTljNDbA9fjMEobHSxWqegIUon/GjJAG3UgHB/+lBWnOLzTY8rGX66MvGqL1Aknyrj7g== dependencies: etag "1.8.1" fresh "0.5.2" mitt "^1.1.3" rxjs "^5.5.6" -browser-sync-ui@^2.26.4: - version "2.26.4" - resolved "https://registry.yarnpkg.com/browser-sync-ui/-/browser-sync-ui-2.26.4.tgz#3772f13c6b93f2d7d333f4be0ca1ec02aae97dba" - integrity sha512-u20P3EsZoM8Pt+puoi3BU3KlbQAH1lAcV+/O4saF26qokrBqIDotmGonfWwoRbUmdxZkM9MBmA0K39ZTG1h4sA== +browser-sync-ui@^2.26.10: + version "2.26.10" + resolved "https://registry.yarnpkg.com/browser-sync-ui/-/browser-sync-ui-2.26.10.tgz#7b4b378de204b3913d4b8a6f93b16b1ba769d4bc" + integrity sha512-UfNSBItlXcmEvJ9RE4JooNtIsiIfHowp+7/52Jz4VFfQD4v78QK5/NV9DVrG41oMM3zLyhW4f/RliOb4ysStZg== dependencies: async-each-series "0.1.1" connect-history-api-fallback "^1" @@ -2307,16 +2240,16 @@ browser-sync-ui@^2.26.4: socket.io-client "^2.0.4" stream-throttle "^0.1.3" -browser-sync@^2.24.6: - version "2.26.7" - resolved "https://registry.yarnpkg.com/browser-sync/-/browser-sync-2.26.7.tgz#120287716eb405651a76cc74fe851c31350557f9" - integrity sha512-lY3emme0OyvA2ujEMpRmyRy9LY6gHLuTr2/ABxhIm3lADOiRXzP4dgekvnDrQqZ/Ec2Fz19lEjm6kglSG5766w== +browser-sync@^2.26.10: + version "2.26.10" + resolved "https://registry.yarnpkg.com/browser-sync/-/browser-sync-2.26.10.tgz#f03c043f615cf53c9294ccb2a5a5e25cfe11a230" + integrity sha512-JeVQP3CARvNA1DELj+ZGWj+/0pzE8+Omvq1WNgzaTXVdP3lNEbGxZbkjvLK7hHpQywjQ1sDJWlJQZT6V59XDTg== dependencies: - browser-sync-client "^2.26.6" - browser-sync-ui "^2.26.4" + browser-sync-client "^2.26.10" + browser-sync-ui "^2.26.10" bs-recipes "1.3.4" bs-snippet-injector "^2.0.1" - chokidar "^2.0.4" + chokidar "^3.4.1" connect "3.6.6" connect-history-api-fallback "^1" dev-ip "^1.0.1" @@ -2325,10 +2258,10 @@ browser-sync@^2.24.6: etag "^1.8.1" fresh "^0.5.2" fs-extra "3.0.1" - http-proxy "1.15.2" + http-proxy "^1.18.1" immutable "^3" - localtunnel "1.9.2" - micromatch "^3.1.10" + localtunnel "^2.0.0" + micromatch "^4.0.2" opn "5.3.0" portscanner "2.1.1" qs "6.2.3" @@ -2340,8 +2273,8 @@ browser-sync@^2.24.6: serve-static "1.13.2" server-destroy "1.0.1" socket.io "2.1.1" - ua-parser-js "0.7.17" - yargs "6.4.0" + ua-parser-js "^0.7.18" + yargs "^15.4.1" browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" @@ -2719,36 +2652,7 @@ caw@^2.0.0, caw@^2.0.1: tunnel-agent "^0.6.0" url-to-options "^1.0.1" -chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" - integrity sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2768,6 +2672,17 @@ chalk@^0.5.0: strip-ansi "^0.3.0" supports-color "^0.2.0" +chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + chalk@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" @@ -2776,37 +2691,12 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chance@1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/chance/-/chance-1.0.13.tgz#666bec2db42b3084456a3e4f4c28a82db5ccb7e6" - integrity sha512-9cpcgmAIQiXC0eMgQuMZgXuHR2Y+gKUyGQnalqSAg5LlUJyJFsZeKyuHVSGhj+bx18ppH+Jo3VOayNeXR/7p9Q== - -chance@1.0.16: - version "1.0.16" - resolved "https://registry.yarnpkg.com/chance/-/chance-1.0.16.tgz#bd61912716b0010c3dca8e3948a960efcaa7bb1b" - integrity sha512-2bgDHH5bVfAXH05SPtjqrsASzZ7h90yCuYT2z4mkYpxxYvJXiIydBFzVieVHZx7wLH1Ag2Azaaej2/zA1XUrNQ== - -chardet@^0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" - integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= - chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -charenc@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= - -check-types@^8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552" - integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ== - -chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.4: +chokidar@^2.0.0, chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== @@ -2825,6 +2715,21 @@ chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.4: optionalDependencies: fsevents "^1.2.7" +chokidar@^3.4.0, chokidar@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.1.tgz#e905bdecf10eaa0a0b1db0c664481cc4cbc22ba1" + integrity sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.4.0" + optionalDependencies: + fsevents "~2.1.2" + chownr@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" @@ -2875,21 +2780,6 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -class-validator@0.8.5: - version "0.8.5" - resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.8.5.tgz#484785acda98f68549c3a84dc1bb2f77b736dc58" - integrity sha512-84yezRo44aP4oGhvPmqj6obAFQF1NzUyfR0+f8jubzdAspO5pmjpHhBBlPf335epUskzXAFe5uo4Qf+c7SI+DA== - dependencies: - validator "9.2.0" - -class-validator@0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.9.1.tgz#d60e58c5d14abca0a41bce38cf792ad4c46d1531" - integrity sha512-3wApflrd3ywVZyx4jaasGoFt8pmo4aGLPPAEKCKCsTRWVGPilahD88q3jQjRQwja50rl9a7rsP5LAxJYwGK8/Q== - dependencies: - google-libphonenumber "^3.1.6" - validator "10.4.0" - clean-css@4.2.x: version "4.2.1" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" @@ -2911,13 +2801,6 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" -cli-table@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" - integrity sha1-9TsFJmqLGguTSz0IIebi3FkUriM= - dependencies: - colors "1.0.3" - cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" @@ -2946,6 +2829,15 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + clone-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" @@ -2978,7 +2870,7 @@ clone@^1.0.0, clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= -clone@^2.1.1, clone@~2.1.0: +clone@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= @@ -3073,7 +2965,7 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" -colors@1.0.3, colors@1.0.x: +colors@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= @@ -3090,17 +2982,12 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== - -commander@2.17.1, commander@2.17.x: +commander@2.17.x: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== -commander@^2.18.0, commander@^2.19.0, commander@^2.2.0, commander@^2.20.0, commander@^2.8.1: +commander@^2.19.0, commander@^2.2.0, commander@^2.20.0, commander@^2.8.1: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== @@ -3117,13 +3004,6 @@ commander@~2.8.1: dependencies: graceful-readlink ">= 1.0.0" -commander@~2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q= - dependencies: - graceful-readlink ">= 1.0.0" - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -3248,18 +3128,13 @@ constants-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= -content-disposition@0.5.3, content-disposition@^0.5.2: +content-disposition@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== dependencies: safe-buffer "5.1.2" -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - convert-source-map@^1.5.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" @@ -3267,21 +3142,11 @@ convert-source-map@^1.5.0, convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -3320,7 +3185,7 @@ core-js@3: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.2.1.tgz#cd41f38534da6cc59f7db050fe67307de9868b09" integrity sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw== -core-js@^2.4.0, core-js@^2.5.3, core-js@^2.5.7: +core-js@^2.4.0, core-js@^2.5.7: version "2.6.9" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== @@ -3330,7 +3195,7 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cosmiconfig@^5.0.0, cosmiconfig@^5.2.1: +cosmiconfig@^5.0.0: version "5.2.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== @@ -3423,11 +3288,6 @@ cross-zip@^2.1.5: dependencies: rimraf "^3.0.0" -crypt@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= - crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -3543,11 +3403,6 @@ css-what@^2.1.2: resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== -cssbeautify@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cssbeautify/-/cssbeautify-0.3.1.tgz#12dd1f734035c2e6faca67dcbdcef74e42811397" - integrity sha1-Et0fc0A1wub6ymfcvc73TkKBE5c= - cssdb@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" @@ -3558,14 +3413,6 @@ cssesc@^2.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== -csslint@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/csslint/-/csslint-1.0.5.tgz#19cc3eda322160fd3f7232af1cb2a360e898a2e9" - integrity sha1-Gcw+2jIhYP0/cjKvHLKjYOiYouk= - dependencies: - clone "~2.1.0" - parserlib "~1.1.1" - cssnano-preset-advanced@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-4.0.7.tgz#d981527b77712e2f3f3f09c73313e9b71b278b88" @@ -4099,11 +3946,6 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= -duplexer@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= - duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -4174,11 +4016,6 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -ejs@^2.6.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.1.tgz#5b5ab57f718b79d4aca9254457afecd36fa80228" - integrity sha512-kS/gEPzZs3Y1rRsbGX4UOSjtP/CeJP0CxSNZHYxGfVM/VgLcv0ZqM7C45YyTj2DI2g7+P9Dd24C+IMIg6D0nYQ== - electron-notarize@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/electron-notarize/-/electron-notarize-0.1.1.tgz#c3563d70c5e7b3315f44e8495b30050a8c408b91" @@ -4250,6 +4087,11 @@ emoji-regex@^7.0.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -4265,13 +4107,6 @@ encodeurl@~1.0.1, encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= - dependencies: - iconv-lite "~0.4.13" - end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" @@ -4504,30 +4339,6 @@ escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen-wallaby@1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/escodegen-wallaby/-/escodegen-wallaby-1.6.18.tgz#95a41e2fdc88687466e43550c7bf136386fd4363" - integrity sha512-3UvR14JRNh8VfKJixTDHWmhPNKAJiVZS807KUjECBk6f05WMe8ZeWL1gbrswNYhDiAUeDBQccyTWR91fayx3og== - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" - -escodegen-wallaby@1.6.19: - version "1.6.19" - resolved "https://registry.yarnpkg.com/escodegen-wallaby/-/escodegen-wallaby-1.6.19.tgz#acd6bbd73f9270763e18570cdc13c0d694759a23" - integrity sha512-q+JGvR5+NR+EJBLnGAevCk5PIiIhPkUFCvcm6w9MWYtm8sv4FdGUsgzWsY6At/YHkgMyA366sjphA/JTNC8CeQ== - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" - escodegen@^1.11.0: version "1.12.0" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541" @@ -4651,7 +4462,7 @@ eslint@^5.9.0: table "^5.2.3" text-table "^0.2.0" -espree@3.5.4, espree@^3.1.6: +espree@^3.1.6: version "3.5.4" resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== @@ -4659,14 +4470,6 @@ espree@3.5.4, espree@^3.1.6: acorn "^5.5.0" acorn-jsx "^3.0.0" -espree@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-4.0.0.tgz#253998f20a0f82db5d866385799d912a83a36634" - integrity sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg== - dependencies: - acorn "^5.6.0" - acorn-jsx "^4.1.1" - espree@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" @@ -4676,11 +4479,6 @@ espree@^5.0.1: acorn-jsx "^5.0.0" eslint-visitor-keys "^1.0.0" -esprima@^2.7.1: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= - esprima@^3.1.3, esprima@~3.1.0: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" @@ -4705,16 +4503,6 @@ esrecurse@^4.1.0, esrecurse@^4.2.1: dependencies: estraverse "^4.1.0" -estraverse@4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= - -estraverse@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= - estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" @@ -4738,10 +4526,10 @@ event-emitter@~0.3.5: d "1" es5-ext "~0.10.14" -eventemitter3@1.x.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" - integrity sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg= +eventemitter3@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" + integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== events@^3.0.0: version "3.0.0" @@ -4858,42 +4646,6 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" -express@^4.16.3: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - ext-list@^2.0.0: version "2.2.2" resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37" @@ -4936,15 +4688,6 @@ extend@^3.0.0, extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" - integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== - dependencies: - chardet "^0.4.0" - iconv-lite "^0.4.17" - tmp "^0.0.33" - external-editor@^3.0.3: version "3.1.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" @@ -5159,11 +4902,6 @@ filenamify@^2.0.0: strip-outer "^1.0.0" trim-repeated "^1.0.0" -filesize@^3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" - integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -5194,7 +4932,7 @@ finalhandler@1.1.0: statuses "~1.3.1" unpipe "~1.0.0" -finalhandler@1.1.2, finalhandler@~1.1.2: +finalhandler@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== @@ -5243,6 +4981,14 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + find-versions@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.1.0.tgz#10161f29cf3eb4350dec10a29bdde75bff0df32d" @@ -5362,6 +5108,11 @@ follow-redirects@1.5.10: dependencies: debug "=3.1.0" +follow-redirects@^1.0.0: + version "1.12.1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.12.1.tgz#de54a6205311b93d60398ebc01cf7015682312b6" + integrity sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg== + for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -5400,11 +5151,6 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -5511,6 +5257,11 @@ fsevents@^1.2.7: nan "^2.12.1" node-pre-gyp "^0.12.0" +fsevents@~2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + fstream@^1.0.0, fstream@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" @@ -5684,7 +5435,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.1.0: +glob-parent@^5.1.0, glob-parent@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== @@ -5914,11 +5665,6 @@ gonzales-pe@^4.2.3: dependencies: minimist "1.1.x" -google-libphonenumber@^3.1.6: - version "3.2.5" - resolved "https://registry.yarnpkg.com/google-libphonenumber/-/google-libphonenumber-3.2.5.tgz#2ebe6437fd3dbbffd65f4339ad1ba93b3dc56836" - integrity sha512-Y0r7MFCI11UDLn0KaMPBEInhROyIOkWkQIyvWMFVF2I+h+sHE3vbl5a7FVe39td6u/w+nlKDdUMP9dMOZyv+2Q== - got@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" @@ -6071,27 +5817,6 @@ gulp-cli@^2.2.0: v8flags "^3.2.0" yargs "^7.1.0" -gulp-cssbeautify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/gulp-cssbeautify/-/gulp-cssbeautify-2.0.1.tgz#39903a8fa0b4f384f20d4eb4bc6591d83c4e47ac" - integrity sha512-IOFGr2KQuO9koeQ5i0aWFhyUU4DBXmIHHblE5xfVxQEzPy5YXdKb54maP1sXTIDDhihilL+y3RhcCcxStem4Ig== - dependencies: - cssbeautify "^0.3.1" - plugin-error "^1.0.1" - through2 "^3.0.1" - -gulp-csslint@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gulp-csslint/-/gulp-csslint-1.0.1.tgz#112a908f7aef98efc27b7bd00801f13a77becb93" - integrity sha512-Rec56+RpCGg7feK3d/S45oqgxyLV3end0ed+UjWFv6YziQae2Bp4DNSDobwEvJdfCAsOhOSExEEB+jcfMx430w== - dependencies: - csslint "^1.0.2" - fancy-log "^1.3.2" - plugin-error "^1.0.1" - rcloader "^0.2.1" - through2 "^2.0.1" - vinyl "^2.1.0" - gulp-dom@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/gulp-dom/-/gulp-dom-1.0.0.tgz#f834d5299c09b85e11c32505044a2ebe86ae1375" @@ -6164,29 +5889,6 @@ gulp-imagemin@^7.1.0: imagemin-optipng "^7.0.0" imagemin-svgo "^7.0.0" -gulp-javascript-obfuscator@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/gulp-javascript-obfuscator/-/gulp-javascript-obfuscator-1.1.6.tgz#4615ce5adb6a0f846246aacea8e1402d8fe04e06" - integrity sha512-oiROhi7Zlu/0fM2h20jBFPaDOZicilT6kN+97Si82yieeFqr6l70o2R3gZ2Ah0u8v5IqGa+Pt8c2q3UnkMuk2A== - dependencies: - javascript-obfuscator latest - plugin-error "^1.0.1" - through2 "^2.0.0" - vinyl "^2.2.0" - -gulp-jsbeautifier@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/gulp-jsbeautifier/-/gulp-jsbeautifier-3.0.1.tgz#4b26991e0adf063130452c5d74910239fadbf254" - integrity sha512-zSXsXQy0/s6qjhhtTun+/ZfC/q8cz/fZpZmxoGPKpmxjuP7/F+oGpV/LHqtOAaWNo+WjcxLVey0cFoNrPZiHWg== - dependencies: - ansi-colors "^4.1.1" - cosmiconfig "^5.2.1" - fancy-log "^1.3.3" - js-beautify "^1.10.1" - lodash.mergewith "^4.6.2" - plugin-error "^1.0.1" - through2 "^3.0.1" - gulp-load-plugins@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/gulp-load-plugins/-/gulp-load-plugins-2.0.3.tgz#5f275c0b7f1925d8a1ce57cbd5c346d6af6b64fb" @@ -6407,14 +6109,6 @@ gulplog@^1.0.0: dependencies: glogg "^1.0.0" -gzip-size@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" - integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== - dependencies: - duplexer "^0.1.1" - pify "^4.0.1" - har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -6578,11 +6272,6 @@ homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" -hoopy@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" - integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== - hosted-git-info@^2.1.4: version "2.8.4" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546" @@ -6649,17 +6338,6 @@ http-cache-semantics@^4.0.0: resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#495704773277eeef6e43f9ab2c2c7d259dda25c5" integrity sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew== -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - http-errors@1.7.3, http-errors@~1.7.2: version "1.7.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" @@ -6686,13 +6364,14 @@ http-errors@~1.6.2: resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= -http-proxy@1.15.2: - version "1.15.2" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.15.2.tgz#642fdcaffe52d3448d2bda3b0079e9409064da31" - integrity sha1-ZC/cr/5S00SNK9o7AHnpQJBk2jE= +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== dependencies: - eventemitter3 "1.x.x" - requires-port "1.x.x" + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" http-signature@~1.2.0: version "1.2.0" @@ -6713,7 +6392,7 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== -iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -6943,25 +6622,6 @@ ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== -inquirer@3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" - integrity sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c= - dependencies: - ansi-escapes "^1.1.0" - chalk "^1.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.1" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx "^4.1.0" - string-width "^2.0.0" - strip-ansi "^3.0.0" - through "^2.3.6" - inquirer@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" @@ -7030,16 +6690,6 @@ invariant@^2.2.2: dependencies: loose-envify "^1.0.0" -inversify@4.11.1: - version "4.11.1" - resolved "https://registry.yarnpkg.com/inversify/-/inversify-4.11.1.tgz#9a10635d1fd347da11da96475b3608babd5945a6" - integrity sha512-9bs/36crPdTSOCcoomHMb96s+B8W0+2c9dHFP/Srv9ZQaPnUvsMgzmMHfgVECqfHVUIW+M5S7SYOjoig8khWuQ== - -inversify@4.13.0: - version "4.13.0" - resolved "https://registry.yarnpkg.com/inversify/-/inversify-4.13.0.tgz#0ab40570bfa4474b04d5b919bbab3a4f682a72f5" - integrity sha512-O5d8y7gKtyRwrvTLZzYET3kdFjqUy58sGpBYMARF13mzqDobpfBXVOPLH7HmnD2VR6Q+1HzZtslGvsdQfeb0SA== - invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" @@ -7050,11 +6700,6 @@ invert-kv@^2.0.0: resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== -ipaddr.js@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" - integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== - irregular-plurals@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-2.0.0.tgz#39d40f05b00f656d0b7fa471230dd3b714af2872" @@ -7104,7 +6749,14 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" -is-buffer@^1.1.5, is-buffer@~1.1.1: +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -7209,6 +6861,11 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + is-function@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" @@ -7228,7 +6885,7 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0, is-glob@^4.0.1: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== @@ -7351,7 +7008,7 @@ is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== -is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: +is-stream@^1.0.0, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= @@ -7464,55 +7121,6 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" -javascript-obfuscator@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/javascript-obfuscator/-/javascript-obfuscator-0.15.0.tgz#e2b348c3a6895ef9195e3088f05747cff7a914f1" - integrity sha512-d4mzMLkwZarZE9ZDFXQapNba4iHEj6ARveU4qCz7j/T/TlrHJVbyhVRcZigIuiQqgotTWGub5vMCa2/ep+hA+w== - dependencies: - "@babel/runtime" "7.0.0-beta.42" - chalk "2.3.2" - chance "1.0.13" - class-validator "0.8.5" - commander "2.15.1" - escodegen-wallaby "1.6.18" - espree "3.5.4" - estraverse "4.2.0" - inversify "4.11.1" - js-string-escape "1.0.1" - md5 "2.2.1" - mkdirp "0.5.1" - multimatch "2.1.0" - opencollective "1.0.3" - pjson "1.0.9" - reflect-metadata "0.1.12" - source-map-support "0.5.4" - string-template "1.0.0" - tslib "1.9.0" - -javascript-obfuscator@latest: - version "0.18.1" - resolved "https://registry.yarnpkg.com/javascript-obfuscator/-/javascript-obfuscator-0.18.1.tgz#ed536645bd64998c8d284c1ab87957d6d8d8294c" - integrity sha512-pQ2DyRV4j0neaWdII1S7iJftCyks9H7afVkQRSE4gslkqpeqyM1DE0eapsZKHR0BnYvw3tPU+Ky+j4yhzcxRZA== - dependencies: - "@babel/runtime" "7.0.0-rc.1" - chalk "2.4.1" - chance "1.0.16" - class-validator "0.9.1" - commander "2.17.1" - escodegen-wallaby "1.6.19" - espree "4.0.0" - estraverse "4.2.0" - inversify "4.13.0" - js-string-escape "1.0.1" - md5 "2.2.1" - mkdirp "0.5.1" - multimatch "2.1.0" - opencollective "1.0.3" - reflect-metadata "0.1.12" - source-map-support "0.5.8" - string-template "1.0.0" - tslib "1.9.3" - jimp@^0.6.1: version "0.6.8" resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.6.8.tgz#63074984337cc469cd4030946e503e7c02a18b5c" @@ -7543,7 +7151,7 @@ js-base64@^2.1.8, js-base64@^2.1.9: resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw== -js-beautify@^1.10.1, js-beautify@^1.5.10: +js-beautify@^1.5.10: version "1.10.2" resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.2.tgz#88c9099cd6559402b124cfab18754936f8a7b178" integrity sha512-ZtBYyNUYJIsBWERnQP0rPN9KjkrDfJcMjuVGcvXOUJrD1zmOGwhRwQ4msG+HJ+Ni/FA7+sRQEMYVzdTQDvnzvQ== @@ -7559,11 +7167,6 @@ js-levenshtein@^1.1.3: resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== -js-string-escape@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -7900,7 +7503,7 @@ loader-runner@^2.4.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== -loader-utils@1.2.3, loader-utils@^1.0.0, loader-utils@^1.1.0, loader-utils@^1.2.3: +loader-utils@1.2.3, loader-utils@^1.1.0, loader-utils@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== @@ -7919,7 +7522,7 @@ loader-utils@^0.2.5, loader-utils@~0.2.2, loader-utils@~0.2.3, loader-utils@~0.2 json5 "^0.5.0" object-assign "^4.0.1" -loader-utils@^1.4.0: +loader-utils@^1.0.0, loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== @@ -7928,15 +7531,15 @@ loader-utils@^1.4.0: emojis-list "^3.0.0" json5 "^1.0.1" -localtunnel@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/localtunnel/-/localtunnel-1.9.2.tgz#0012fcabc29cf964c130a01858768aa2bb65b5af" - integrity sha512-NEKF7bDJE9U3xzJu3kbayF0WTvng6Pww7tzqNb/XtEARYwqw7CKEX7BvOMg98FtE9es2CRizl61gkV3hS8dqYg== +localtunnel@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/localtunnel/-/localtunnel-2.0.0.tgz#2ea71174fa80e34cce91b2a7ce416e6a57d9ff7c" + integrity sha512-g6E0aLgYYDvQDxIjIXkgJo2+pHj3sGg4Wz/XP3h2KtZnRsWPbOQY+hw1H8Z91jep998fkcVE9l+kghO+97vllg== dependencies: axios "0.19.0" debug "4.1.1" openurl "1.1.1" - yargs "6.6.0" + yargs "13.3.0" locate-path@^2.0.0: version "2.0.0" @@ -7954,6 +7557,13 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + lodash._basecopy@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" @@ -8046,11 +7656,6 @@ lodash._shimkeys@~2.4.1: dependencies: lodash._objecttypes "~2.4.1" -lodash.assign@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= - lodash.capitalize@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz#f826c9b4e2a8511d84e3aca29db05e1a4f3b72a9" @@ -8115,11 +7720,6 @@ lodash.isfinite@^3.3.2: resolved "https://registry.yarnpkg.com/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz#fb89b65a9a80281833f0b7478b3a5104f898ebb3" integrity sha1-+4m2WpqAKBgz8LdHizpRBPiY67M= -lodash.isobject@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-3.0.2.tgz#3c8fb8d5b5bf4bf90ae06e14f2a530a4ed935e1d" - integrity sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0= - lodash.isobject@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz#5a2e47fe69953f1ee631a7eba1fe64d2d06558f5" @@ -8155,16 +7755,6 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= -lodash.merge@^4.6.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.mergewith@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" - integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== - lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" @@ -8256,7 +7846,7 @@ lodash@^3.0.1: resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y= -lodash@^4.0.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.3.0, lodash@~4.17.10: +lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.3.0, lodash@~4.17.10: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -8383,11 +7973,6 @@ make-iterator@^1.0.0: dependencies: kind-of "^6.0.2" -mamacro@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" - integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA== - map-age-cleaner@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" @@ -8444,15 +8029,6 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -md5@2.2.1, md5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" - integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk= - dependencies: - charenc "~0.0.1" - crypt "~0.0.1" - is-buffer "~1.1.1" - mdn-data@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" @@ -8501,11 +8077,6 @@ meow@^3.3.0, meow@^3.7.0: redent "^1.0.0" trim-newlines "^1.0.0" -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -8526,11 +8097,6 @@ merge@^1.2.0: resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -8650,7 +8216,7 @@ minimatch@0.3: lru-cache "2" sigmund "~1.0.0" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: +"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -8682,11 +8248,6 @@ minimist@1.1.x: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag= -minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - minimist@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de" @@ -8697,6 +8258,11 @@ minimist@^0.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.2.0.tgz#4dffe525dae2b864c66c2e23c6271d7afdecefce" integrity sha1-Tf/lJdriuGTGbC4jxicdev3s784= +minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -8801,16 +8367,6 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -multimatch@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - multipipe@^0.1.0, multipipe@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" @@ -8906,22 +8462,6 @@ no-case@^2.2.0: dependencies: lower-case "^1.1.1" -node-fetch@1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" - integrity sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ= - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -node-fetch@^1.6.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - node-gyp@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" @@ -9060,7 +8600,7 @@ normalize-path@^2.1.1: dependencies: remove-trailing-separator "^1.0.1" -normalize-path@^3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -9168,15 +8708,6 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -obfuscator-loader@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obfuscator-loader/-/obfuscator-loader-1.1.2.tgz#6e8460066296fc642a68c945e64906e3c964cb0f" - integrity sha512-5PKsa4Vzq8uLJG0GT9BvC9ZxCr44wyV0c9wi782RYWh44GdFMSqlnUldgqSV+HQkFH3MWNc34AlSVSEhg7I26w== - dependencies: - esprima "^4.0.0" - javascript-obfuscator "^0.15.0" - loader-utils "^1.1.0" - object-assign@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" @@ -9327,14 +8858,6 @@ once@~1.3.0: dependencies: wrappy "1" -onesky-fetch@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/onesky-fetch/-/onesky-fetch-0.0.7.tgz#96fce1a258a80683d6a37840958bae2f6fdb2809" - integrity sha1-lvzholioBoPWo3hAlYuuL2/bKAk= - dependencies: - md5 "^2.2.1" - node-fetch "^1.6.3" - onetime@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" @@ -9359,36 +8882,11 @@ open@^0.0.5: resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc" integrity sha1-QsPhjslUZra/DcQvOilFw/DK2Pw= -opencollective@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/opencollective/-/opencollective-1.0.3.tgz#aee6372bc28144583690c3ca8daecfc120dd0ef1" - integrity sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE= - dependencies: - babel-polyfill "6.23.0" - chalk "1.1.3" - inquirer "3.0.6" - minimist "1.2.0" - node-fetch "1.6.3" - opn "4.0.2" - -opener@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" - integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== - openurl@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/openurl/-/openurl-1.1.1.tgz#3875b4b0ef7a52c156f0db41d4609dbb0f94b387" integrity sha1-OHW0sO96UsFW8NtB1GCduw+Us4c= -opn@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/opn/-/opn-4.0.2.tgz#7abc22e644dff63b0a96d5ab7f2790c0f01abc95" - integrity sha1-erwi5kTf9jsKltWrfyeQwPAavJU= - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - opn@5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" @@ -9562,6 +9060,13 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -9576,6 +9081,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-map-series@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca" @@ -9743,11 +9255,6 @@ parseqs@0.0.5: dependencies: better-assert "~1.0.0" -parserlib@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/parserlib/-/parserlib-1.1.1.tgz#a64cfa724062434fdfc351c9a4ec2d92b94c06f4" - integrity sha1-pkz6ckBiQ0/fw1HJpOwtkrlMBvQ= - parseuri@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" @@ -9787,6 +9294,11 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -9834,11 +9346,6 @@ path-starts-with@^2.0.0: resolved "https://registry.yarnpkg.com/path-starts-with/-/path-starts-with-2.0.0.tgz#ffd6d51926cd497022b44d392196033d5451892f" integrity sha512-3UHTHbJz5+NLkPafFR+2ycJOjoc4WV2e9qCZCnm71zHiWaFrm1XniLVTkZXvaRgxr1xFh9JsTdicpH2yM03nLA== -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -9891,7 +9398,7 @@ phonegap-plugin-mobile-accessibility@^1.0.5: resolved "https://registry.yarnpkg.com/phonegap-plugin-mobile-accessibility/-/phonegap-plugin-mobile-accessibility-1.0.5.tgz#95a8754d127508bc6e1ae259a53ce765836eac03" integrity sha1-lah1TRJ1CLxuGuJZpTznZYNurAM= -picomatch@^2.0.5, picomatch@^2.2.1: +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== @@ -9930,11 +9437,6 @@ pixelmatch@^4.0.2: dependencies: pngjs "^3.0.0" -pjson@1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/pjson/-/pjson-1.0.9.tgz#8a9520ce76a4739f8fee91679dad6b065b1c7938" - integrity sha512-4hRJH3YzkUpOlShRzhyxAmThSNnAaIlWZCAb27hd0pVUAXNUAHAO7XZbsPPvsCYwBFEScTmCCL6DGE8NyZ8BdQ== - pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" @@ -10772,14 +10274,6 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= -proxy-addr@~2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" - integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ== - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.9.0" - proxy-middleware@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/proxy-middleware/-/proxy-middleware-0.5.1.tgz#da24d5d58c1ddf13dad237c7eca503849eaea903" @@ -10877,11 +10371,6 @@ qs@6.2.3: resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" integrity sha1-HPyyXBCpsrSDBT/zn138kjOQjP4= -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - qs@~2.2.3: version "2.2.5" resolved "https://registry.yarnpkg.com/qs/-/qs-2.2.5.tgz#1088abaf9dcc0ae5ae45b709e6c6b5888b23923c" @@ -10920,7 +10409,7 @@ querystring@0.2.0: resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== @@ -10948,16 +10437,6 @@ raw-body@1.3.0: bytes "1" iconv-lite "0.4.4" -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - raw-body@^2.3.2: version "2.4.1" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" @@ -10998,16 +10477,6 @@ rcloader@^0.1.4: lodash "^3.0.1" rcfinder "^0.1.6" -rcloader@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/rcloader/-/rcloader-0.2.2.tgz#58d2298b462d0b9bfd2133d2a1ec74fbd705c717" - integrity sha1-WNIpi0YtC5v9ITPSoex0+9cFxxc= - dependencies: - lodash.assign "^4.2.0" - lodash.isobject "^3.0.2" - lodash.merge "^4.6.0" - rcfinder "^0.1.6" - read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -11100,7 +10569,7 @@ readable-stream@^3.0.2, readable-stream@^3.1.1: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readdirp@^2.1.0, readdirp@^2.2.1: +readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== @@ -11109,6 +10578,13 @@ readdirp@^2.1.0, readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" +readdirp@~3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" + integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== + dependencies: + picomatch "^2.2.1" + readline2@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" @@ -11143,11 +10619,6 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" -reflect-metadata@0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.12.tgz#311bf0c6b63cd782f228a81abe146a2bfa9c56f2" - integrity sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A== - regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" @@ -11160,21 +10631,11 @@ regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@^0.10.0: - version "0.10.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= - -regenerator-runtime@^0.11.0, regenerator-runtime@^0.11.1: +regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.12.0: - version "0.12.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" - integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== - regenerator-runtime@^0.13.3: version "0.13.3" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" @@ -11362,7 +10823,7 @@ require-uncached@^1.0.2: caller-path "^0.1.0" resolve-from "^1.0.0" -requires-port@1.x.x: +requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= @@ -11539,7 +11000,7 @@ rx-lite@^3.1.2: resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI= -rx@4.1.0, rx@^4.1.0: +rx@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= @@ -11769,6 +11230,13 @@ serialize-javascript@^1.7.0: resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb" integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A== +serialize-javascript@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.1.0.tgz#8bf3a9170712664ef2561b44b691eafe399214ea" + integrity sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg== + dependencies: + randombytes "^2.1.0" + serve-index@1.9.1, serve-index@^1.1.4: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" @@ -11792,7 +11260,7 @@ serve-static@1.13.2: parseurl "~1.3.2" send "0.16.2" -serve-static@1.14.1, serve-static@^1.3.0: +serve-static@^1.3.0: version "1.14.1" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== @@ -11910,16 +11378,6 @@ slice-ansi@^2.1.0: astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" -sloc@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/sloc/-/sloc-0.2.1.tgz#42ad891e76838c1a22bbd8483468e9d74c7f531e" - integrity sha512-8XJnwCFR4DatLz1s0nGFe6IJPJ+5pjRFhoBuBKq8SLgFI40eD7ak6jOXpzeG0tmIpyOc1zCs9bjKAxMFm1451A== - dependencies: - async "~2.1.4" - cli-table "^0.3.1" - commander "~2.9.0" - readdirp "^2.1.0" - snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -12062,21 +11520,6 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.4.tgz#54456efa89caa9270af7cd624cc2f123e51fbae8" - integrity sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg== - dependencies: - source-map "^0.6.0" - -source-map-support@0.5.8: - version "0.5.8" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.8.tgz#04f5581713a8a65612d0175fbf3a01f80a162613" - integrity sha512-WqAEWPdb78u25RfKzOF0swBpY0dKrNdjc4GvLwm7ScX/o9bj8Eh/YL8mcMhBHYDGl87UkkSXDOFnW4G7GhWhGg== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-support@~0.5.12: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -12114,13 +11557,6 @@ source-map@~0.1.38: dependencies: amdefine ">=0.0.4" -source-map@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= - dependencies: - amdefine ">=0.0.4" - sparkles@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" @@ -12152,13 +11588,6 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== -speed-measure-webpack-plugin@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.1.tgz#69840a5cdc08b4638697dac7db037f595d7f36a0" - integrity sha512-qVIkJvbtS9j/UeZumbdfz0vg+QfG/zxonAjzefZrqzkr7xOncLVXkeGbTpzd1gjCBM4PmVNkWlkeTVhgskAGSQ== - dependencies: - chalk "^2.0.1" - split-on-first@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" @@ -12350,11 +11779,6 @@ string-replace-webpack-plugin@^0.1.3: file-loader "^0.8.1" style-loader "^0.8.3" -string-template@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96" - integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y= - string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -12381,6 +11805,15 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + string.prototype.trim@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.0.tgz#75a729b10cfc1be439543dae442129459ce61e3d" @@ -12453,6 +11886,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + strip-bom@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-1.0.0.tgz#85b8862f3844b5a6d5ec8467a93598173a36f794" @@ -12712,7 +12152,7 @@ ternary-stream@^3.0.0: merge-stream "^2.0.0" through2 "^3.0.1" -terser-webpack-plugin@^1.1.0, terser-webpack-plugin@^1.4.1: +terser-webpack-plugin@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz#61b18e40eaee5be97e771cdbb10ed1280888c2b4" integrity sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg== @@ -12727,6 +12167,21 @@ terser-webpack-plugin@^1.1.0, terser-webpack-plugin@^1.4.1: webpack-sources "^1.4.0" worker-farm "^1.7.0" +terser-webpack-plugin@^1.4.3: + version "1.4.4" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz#2c63544347324baafa9a56baaddf1634c8abfc2f" + integrity sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA== + dependencies: + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" + schema-utils "^1.0.0" + serialize-javascript "^3.1.0" + source-map "^0.6.1" + terser "^4.1.2" + webpack-sources "^1.4.0" + worker-farm "^1.7.0" + terser@^4.0.0, terser@^4.1.2: version "4.3.1" resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.1.tgz#09820bcb3398299c4b48d9a86aefc65127d0ed65" @@ -13032,21 +12487,6 @@ truncate-utf8-bytes@^1.0.0: dependencies: utf8-byte-length "^1.0.1" -tryer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" - integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== - -tslib@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" - integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ== - -tslib@1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== - tslib@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" @@ -13089,14 +12529,6 @@ type-is@~1.5.1: media-typer "0.3.0" mime-types "~2.0.9" -type-is@~1.6.17, type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - type@^1.0.1: version "1.2.0" resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" @@ -13107,10 +12539,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -ua-parser-js@0.7.17: - version "0.7.17" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" - integrity sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g== +ua-parser-js@^0.7.18: + version "0.7.21" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777" + integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ== uglify-js@3.4.x: version "3.4.10" @@ -13421,26 +12853,11 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validator@10.4.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-10.4.0.tgz#ee99a44afb3bb5ed350a159f056ca72a204cfc3c" - integrity sha512-Q/wBy3LB1uOyssgNlXSRmaf22NxjvDNZM2MtIQ4jaEOAB61xsh1TQxsq1CgzUMBV1lDrVMogIh8GjG1DYW0zLg== - -validator@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-9.2.0.tgz#ad216eed5f37cac31a6fe00ceab1f6b88bded03e" - integrity sha512-6Ij4Eo0KM4LkR0d0IegOwluG5453uqT5QyF5SV5Ezvm8/zmkKI/L4eoraafZGlZPC9guLkwKzgypcw8VGWWnGA== - value-or-function@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - vendors@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.3.tgz#a6467781abd366217c050f8202e7e50cc9eef8c0" @@ -13588,39 +13005,29 @@ watch@^0.11.0: resolved "https://registry.yarnpkg.com/watch/-/watch-0.11.0.tgz#e8dba091b7456799a3af57978b986e77e1320406" integrity sha1-6NugkbdFZ5mjr1eXi5hud+EyBAY= -watchpack@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" - integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== +watchpack-chokidar2@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" + integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== + dependencies: + chokidar "^2.1.8" + +watchpack@^1.6.1: + version "1.7.2" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.2.tgz#c02e4d4d49913c3e7e122c3325365af9d331e9aa" + integrity sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g== dependencies: - chokidar "^2.0.2" graceful-fs "^4.1.2" neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.0" + watchpack-chokidar2 "^2.0.0" webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webpack-bundle-analyzer@^3.0.3: - version "3.5.1" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.5.1.tgz#84aabb1547178d842ebb4ccc7324084b6c3b0ea9" - integrity sha512-CDdaT3TTu4F9X3tcDq6PNJOiNGgREOM0WdN2vVAoUUn+M6NLB5kJ543HImCWbrDwOpbpGARSwU8r+u0Pl367kA== - dependencies: - acorn "^6.0.7" - acorn-walk "^6.1.1" - bfj "^6.1.1" - chalk "^2.4.1" - commander "^2.18.0" - ejs "^2.6.1" - express "^4.16.3" - filesize "^3.6.1" - gzip-size "^5.0.0" - lodash "^4.17.15" - mkdirp "^0.5.1" - opener "^1.5.1" - ws "^6.0.0" - webpack-cli@^3.1.0: version "3.3.9" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.9.tgz#79c27e71f94b7fe324d594ab64a8e396b9daa91a" @@ -13658,7 +13065,7 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1: source-list-map "^2.0.0" source-map "~0.6.1" -webpack-stream@^5.1.0: +webpack-stream@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/webpack-stream/-/webpack-stream-5.2.1.tgz#35c992161399fe8cad9c10d4a5c258f022629b39" integrity sha512-WvyVU0K1/VB1NZ7JfsaemVdG0PXAQUqbjUNW4A58th4pULvKMQxG+y33HXTL02JvD56ko2Cub+E2NyPwrLBT/A== @@ -13680,16 +13087,16 @@ webpack-strip-block@^0.2.0: dependencies: loader-utils "^1.1.0" -webpack@^4.26.1, webpack@^4.31.0: - version "4.40.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.40.2.tgz#d21433d250f900bf0facbabe8f50d585b2dc30a7" - integrity sha512-5nIvteTDCUws2DVvP9Qe+JPla7kWPPIDFZv55To7IycHWZ+Z5qBdaBYPyuXWdhggTufZkQwfIK+5rKQTVovm2A== +webpack@^4.26.1, webpack@^4.43.0: + version "4.43.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.43.0.tgz#c48547b11d563224c561dad1172c8aa0b8a678e6" + integrity sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/wasm-edit" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - acorn "^6.2.1" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + acorn "^6.4.1" ajv "^6.10.2" ajv-keywords "^3.4.1" chrome-trace-event "^1.0.2" @@ -13700,13 +13107,13 @@ webpack@^4.26.1, webpack@^4.31.0: loader-utils "^1.2.3" memory-fs "^0.4.1" micromatch "^3.1.10" - mkdirp "^0.5.1" + mkdirp "^0.5.3" neo-async "^2.6.1" node-libs-browser "^2.2.1" schema-utils "^1.0.0" tapable "^1.1.3" - terser-webpack-plugin "^1.4.1" - watchpack "^1.6.0" + terser-webpack-plugin "^1.4.3" + watchpack "^1.6.1" webpack-sources "^1.4.1" websocket-driver@>=0.3.6: @@ -13780,11 +13187,6 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2" -window-size@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= - winston@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/winston/-/winston-1.0.2.tgz#351c58e2323f8a4ca29a45195aa9aa3b4c35d76f" @@ -13840,6 +13242,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -13859,7 +13270,7 @@ write@^0.2.1: dependencies: mkdirp "^0.5.1" -ws@^6.0.0, ws@^6.1.0: +ws@^6.1.0: version "6.2.1" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== @@ -14002,12 +13413,21 @@ yargs-parser@^13.0.0, yargs-parser@^13.1.0: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^4.1.0, yargs-parser@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" - integrity sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw= +yargs-parser@^13.1.1: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: - camelcase "^3.0.0" + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" yargs-parser@^5.0.0: version "5.0.0" @@ -14033,44 +13453,38 @@ yargs@13.2.4: y18n "^4.0.0" yargs-parser "^13.1.0" -yargs@6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.4.0.tgz#816e1a866d5598ccf34e5596ddce22d92da490d4" - integrity sha1-gW4ahm1VmMzzTlWW3c4i2S2kkNQ= +yargs@13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" require-directory "^2.1.1" - require-main-filename "^1.0.1" + require-main-filename "^2.0.0" set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - window-size "^0.2.0" - y18n "^3.2.1" - yargs-parser "^4.1.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" -yargs@6.6.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" - integrity sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg= +yargs@^15.4.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" require-directory "^2.1.1" - require-main-filename "^1.0.1" + require-main-filename "^2.0.0" set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^4.2.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" yargs@^7.0.0: version "7.1.0" diff --git a/package.json b/package.json index af94e173..bdc0eb53 100644 --- a/package.json +++ b/package.json @@ -1,103 +1,100 @@ -{ - "name": "shapez.io", - "version": "1.0.0", - "main": "index.js", - "repository": "https://github.com/tobspr/shapez.io", - "author": "Tobias Springer ", - "license": "MIT", - "private": true, - "scripts": { - "dev": "cd gulp && yarn gulp main.serveDev", - "tslint": "cd src/js && tsc", - "lint": "npx eslint src/js", - "prettier-all": "prettier --write src/**/*.* && prettier --write gulp/**/*.*", - "publishOnItchWindows": "butler push tmp_standalone_files/shapez.io-standalone-win32-x64 tobspr/shapezio:windows --userversion-file version", - "publishOnItchLinux": "butler push tmp_standalone_files/shapez.io-standalone-linux-x64 tobspr/shapezio:linux --userversion-file version", - "publishOnItch": "yarn publishOnItchWindows && yarn publishOnItchLinux", - "publishOnSteam": "cd gulp/steampipe && ./upload.bat", - "publishStandalone": "yarn publishOnItch && yarn publishOnSteam", - "publishWeb": "cd gulp && yarn main.deploy.prod", - "publish": "yarn publishStandalone && yarn publishWeb", - "syncTranslations": "node sync-translations.js" - }, - "dependencies": { - "@babel/core": "^7.5.4", - "@babel/plugin-transform-block-scoping": "^7.4.4", - "@babel/plugin-transform-classes": "^7.5.5", - "@babel/preset-env": "^7.5.4", - "@types/cordova": "^0.0.34", - "@types/filesystem": "^0.0.29", - "ajv": "^6.10.2", - "babel-loader": "^8.0.4", - "browser-sync": "^2.24.6", - "circular-dependency-plugin": "^5.0.2", - "circular-json": "^0.5.9", - "clipboard-copy": "^3.1.0", - "colors": "^1.3.3", - "core-js": "3", - "cssnano-preset-advanced": "^4.0.7", - "email-validator": "^2.0.4", - "eslint": "7.1.0", - "fastdom": "^1.0.8", - "flatted": "^2.0.1", - "howler": "^2.1.2", - "html-loader": "^0.5.5", - "ignore-loader": "^0.1.2", - "logrocket": "^1.0.7", - "lz-string": "^1.4.4", - "markdown-loader": "^4.0.0", - "match-all": "^1.2.5", - "obfuscator-loader": "^1.1.2", - "phonegap-plugin-mobile-accessibility": "^1.0.5", - "promise-polyfill": "^8.1.0", - "query-string": "^6.8.1", - "rusha": "^0.8.13", - "serialize-error": "^3.0.0", - "sloc": "^0.2.1", - "strictdom": "^1.0.1", - "string-replace-webpack-plugin": "^0.1.3", - "terser-webpack-plugin": "^1.1.0", - "typescript": "3.9.3", - "uglify-template-string-loader": "^1.1.0", - "unused-files-webpack-plugin": "^3.4.0", - "webpack": "^4.31.0", - "webpack-bundle-analyzer": "^3.0.3", - "webpack-cli": "^3.1.0", - "webpack-deep-scope-plugin": "^1.6.0", - "webpack-plugin-replace": "^1.1.1", - "webpack-strip-block": "^0.2.0", - "whatwg-fetch": "^3.0.0", - "worker-loader": "^2.0.0", - "yaml": "^1.10.0", - "yawn-yaml": "^1.5.0" - }, - "devDependencies": { - "@typescript-eslint/eslint-plugin": "3.0.1", - "@typescript-eslint/parser": "3.0.1", - "autoprefixer": "^9.4.3", - "babel-plugin-closure-elimination": "^1.3.0", - "babel-plugin-console-source": "^2.0.2", - "babel-plugin-danger-remove-unused-import": "^1.1.2", - "css-mqpacker": "^7.0.0", - "cssnano": "^4.1.10", - "eslint-config-prettier": "6.11.0", - "eslint-plugin-prettier": "3.1.3", - "faster.js": "^1.1.0", - "glob": "^7.1.3", - "imagemin-mozjpeg": "^8.0.0", - "imagemin-pngquant": "^8.0.0", - "jimp": "^0.6.1", - "js-yaml": "^3.13.1", - "onesky-fetch": "^0.0.7", - "postcss-assets": "^5.0.0", - "postcss-preset-env": "^6.5.0", - "postcss-round-subpixels": "^1.2.0", - "postcss-unprefix": "^2.1.3", - "prettier": "^2.0.4", - "sass-unused": "^0.3.0", - "speed-measure-webpack-plugin": "^1.3.1", - "strip-json-comments": "^3.0.1", - "trim": "^0.0.1", - "webpack-stream": "^5.1.0" - } -} +{ + "name": "shapez.io", + "version": "1.0.0", + "main": "index.js", + "repository": "https://github.com/tobspr/shapez.io", + "author": "Tobias Springer ", + "license": "MIT", + "private": true, + "scripts": { + "dev": "cd gulp && yarn gulp main.serveDev", + "tslint": "cd src/js && tsc", + "lint": "eslint src/js", + "prettier-all": "prettier --write src/**/*.* && prettier --write gulp/**/*.*", + "publishOnItchWindows": "butler push tmp_standalone_files/shapez.io-standalone-win32-x64 tobspr/shapezio:windows --userversion-file version", + "publishOnItchLinux": "butler push tmp_standalone_files/shapez.io-standalone-linux-x64 tobspr/shapezio:linux --userversion-file version", + "publishOnItch": "yarn publishOnItchWindows && yarn publishOnItchLinux", + "publishOnSteam": "cd gulp/steampipe && ./upload.bat", + "publishStandalone": "yarn publishOnItch && yarn publishOnSteam", + "publishWeb": "cd gulp && yarn main.deploy.prod", + "publish": "yarn publishStandalone && yarn publishWeb", + "syncTranslations": "node sync-translations.js" + }, + "dependencies": { + "@babel/core": "^7.5.4", + "@babel/plugin-transform-block-scoping": "^7.4.4", + "@babel/plugin-transform-classes": "^7.5.5", + "@babel/preset-env": "^7.5.4", + "@types/cordova": "^0.0.34", + "@types/filesystem": "^0.0.29", + "ajv": "^6.10.2", + "babel-loader": "^8.0.4", + "circular-dependency-plugin": "^5.0.2", + "circular-json": "^0.5.9", + "clipboard-copy": "^3.1.0", + "colors": "^1.3.3", + "core-js": "3", + "crc": "^3.8.0", + "cssnano-preset-advanced": "^4.0.7", + "debounce-promise": "^3.1.2", + "email-validator": "^2.0.4", + "eslint": "7.1.0", + "fastdom": "^1.0.8", + "flatted": "^2.0.1", + "howler": "^2.1.2", + "html-loader": "^0.5.5", + "ignore-loader": "^0.1.2", + "logrocket": "^1.0.7", + "lz-string": "^1.4.4", + "markdown-loader": "^4.0.0", + "match-all": "^1.2.5", + "phonegap-plugin-mobile-accessibility": "^1.0.5", + "promise-polyfill": "^8.1.0", + "query-string": "^6.8.1", + "rusha": "^0.8.13", + "serialize-error": "^3.0.0", + "strictdom": "^1.0.1", + "string-replace-webpack-plugin": "^0.1.3", + "terser-webpack-plugin": "^1.1.0", + "typescript": "3.9.3", + "uglify-template-string-loader": "^1.1.0", + "unused-files-webpack-plugin": "^3.4.0", + "webpack": "^4.43.0", + "webpack-bundle-analyzer": "^3.0.3", + "webpack-cli": "^3.1.0", + "webpack-deep-scope-plugin": "^1.6.0", + "webpack-plugin-replace": "^1.1.1", + "webpack-strip-block": "^0.2.0", + "whatwg-fetch": "^3.0.0", + "worker-loader": "^2.0.0", + "yaml": "^1.10.0", + "yawn-yaml": "^1.5.0" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "3.0.1", + "@typescript-eslint/parser": "3.0.1", + "autoprefixer": "^9.4.3", + "babel-plugin-closure-elimination": "^1.3.0", + "babel-plugin-console-source": "^2.0.2", + "babel-plugin-danger-remove-unused-import": "^1.1.2", + "css-mqpacker": "^7.0.0", + "cssnano": "^4.1.10", + "eslint-config-prettier": "6.11.0", + "eslint-plugin-prettier": "3.1.3", + "faster.js": "^1.1.0", + "glob": "^7.1.3", + "imagemin-mozjpeg": "^8.0.0", + "imagemin-pngquant": "^8.0.0", + "jimp": "^0.6.1", + "js-yaml": "^3.13.1", + "postcss-assets": "^5.0.0", + "postcss-preset-env": "^6.5.0", + "postcss-round-subpixels": "^1.2.0", + "postcss-unprefix": "^2.1.3", + "prettier": "^2.0.4", + "sass-unused": "^0.3.0", + "strip-json-comments": "^3.0.1", + "trim": "^0.0.1", + "yarn": "^1.22.4" + } +} diff --git a/res/ui/building_icons/advanced_processor.png b/res/ui/building_icons/advanced_processor.png deleted file mode 100644 index c1423b09..00000000 Binary files a/res/ui/building_icons/advanced_processor.png and /dev/null differ diff --git a/res/ui/building_icons/belt.png b/res/ui/building_icons/belt.png index f9ed2542..628480fb 100644 Binary files a/res/ui/building_icons/belt.png and b/res/ui/building_icons/belt.png differ diff --git a/res/ui/building_icons/constant_signal.png b/res/ui/building_icons/constant_signal.png new file mode 100644 index 00000000..b438fa29 Binary files /dev/null and b/res/ui/building_icons/constant_signal.png differ diff --git a/res/ui/building_icons/cutter.png b/res/ui/building_icons/cutter.png index ab69cfbd..6d0fc4d1 100644 Binary files a/res/ui/building_icons/cutter.png and b/res/ui/building_icons/cutter.png differ diff --git a/res/ui/building_icons/display.png b/res/ui/building_icons/display.png new file mode 100644 index 00000000..14c48d7e Binary files /dev/null and b/res/ui/building_icons/display.png differ diff --git a/res/ui/building_icons/energy_generator.png b/res/ui/building_icons/energy_generator.png deleted file mode 100644 index ab724a7b..00000000 Binary files a/res/ui/building_icons/energy_generator.png and /dev/null differ diff --git a/res/ui/building_icons/filter.png b/res/ui/building_icons/filter.png new file mode 100644 index 00000000..2e87af28 Binary files /dev/null and b/res/ui/building_icons/filter.png differ diff --git a/res/ui/building_icons/lever.png b/res/ui/building_icons/lever.png new file mode 100644 index 00000000..77eea9f3 Binary files /dev/null and b/res/ui/building_icons/lever.png differ diff --git a/res/ui/building_icons/logic_gate.png b/res/ui/building_icons/logic_gate.png new file mode 100644 index 00000000..81a0bdd6 Binary files /dev/null and b/res/ui/building_icons/logic_gate.png differ diff --git a/res/ui/building_icons/miner.png b/res/ui/building_icons/miner.png index 6bf727ec..fc7050ea 100644 Binary files a/res/ui/building_icons/miner.png and b/res/ui/building_icons/miner.png differ diff --git a/res/ui/building_icons/mixer.png b/res/ui/building_icons/mixer.png index 62e15780..87409438 100644 Binary files a/res/ui/building_icons/mixer.png and b/res/ui/building_icons/mixer.png differ diff --git a/res/ui/building_icons/painter.png b/res/ui/building_icons/painter.png index 60a1c784..4aa888b6 100644 Binary files a/res/ui/building_icons/painter.png and b/res/ui/building_icons/painter.png differ diff --git a/res/ui/building_icons/reader.png b/res/ui/building_icons/reader.png new file mode 100644 index 00000000..890a6ad7 Binary files /dev/null and b/res/ui/building_icons/reader.png differ diff --git a/res/ui/building_icons/rotater.png b/res/ui/building_icons/rotater.png index fe0b2186..3fb355d6 100644 Binary files a/res/ui/building_icons/rotater.png and b/res/ui/building_icons/rotater.png differ diff --git a/res/ui/building_icons/splitter.png b/res/ui/building_icons/splitter.png index 29ea7123..fb889bab 100644 Binary files a/res/ui/building_icons/splitter.png and b/res/ui/building_icons/splitter.png differ diff --git a/res/ui/building_icons/stacker.png b/res/ui/building_icons/stacker.png index 3098ae3e..5a4dda42 100644 Binary files a/res/ui/building_icons/stacker.png and b/res/ui/building_icons/stacker.png differ diff --git a/res/ui/building_icons/trash.png b/res/ui/building_icons/trash.png index 8f094f2e..b6a34ae6 100644 Binary files a/res/ui/building_icons/trash.png and b/res/ui/building_icons/trash.png differ diff --git a/res/ui/building_icons/underground_belt.png b/res/ui/building_icons/underground_belt.png index 240e08a6..b52f4d8e 100644 Binary files a/res/ui/building_icons/underground_belt.png and b/res/ui/building_icons/underground_belt.png differ diff --git a/res/ui/building_icons/virtual_processor.png b/res/ui/building_icons/virtual_processor.png new file mode 100644 index 00000000..f5471999 Binary files /dev/null and b/res/ui/building_icons/virtual_processor.png differ diff --git a/res/ui/building_icons/wire.png b/res/ui/building_icons/wire.png index e6ccb3a6..6bae2537 100644 Binary files a/res/ui/building_icons/wire.png and b/res/ui/building_icons/wire.png differ diff --git a/res/ui/building_icons/wire_crossings.png b/res/ui/building_icons/wire_crossings.png deleted file mode 100644 index 29ea7123..00000000 Binary files a/res/ui/building_icons/wire_crossings.png and /dev/null differ diff --git a/res/ui/building_icons/wire_tunnel.png b/res/ui/building_icons/wire_tunnel.png new file mode 100644 index 00000000..d0e185f9 Binary files /dev/null and b/res/ui/building_icons/wire_tunnel.png differ diff --git a/res/ui/building_tutorials/rotater-fl.png b/res/ui/building_tutorials/rotater-fl.png new file mode 100644 index 00000000..cb6cee0d Binary files /dev/null and b/res/ui/building_tutorials/rotater-fl.png differ diff --git a/res/ui/icons/display_sorted.png b/res/ui/icons/display_sorted.png new file mode 100644 index 00000000..2e3c2bad Binary files /dev/null and b/res/ui/icons/display_sorted.png differ diff --git a/res/ui/icons/download.png b/res/ui/icons/download.png index bb28bf81..68ed3fb4 100644 Binary files a/res/ui/icons/download.png and b/res/ui/icons/download.png differ diff --git a/res/ui/icons/link.png b/res/ui/icons/link.png new file mode 100644 index 00000000..f51ca38b Binary files /dev/null and b/res/ui/icons/link.png differ diff --git a/res_built/atlas/atlas0_10.json b/res_built/atlas/atlas0_10.json deleted file mode 100644 index e20ae7b7..00000000 --- a/res_built/atlas/atlas0_10.json +++ /dev/null @@ -1,1388 +0,0 @@ -{"frames": { - -"sprites/belt/forward_0.png": -{ - "frame": {"x":294,"y":26,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_1.png": -{ - "frame": {"x":311,"y":26,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_2.png": -{ - "frame": {"x":487,"y":43,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_3.png": -{ - "frame": {"x":521,"y":40,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_4.png": -{ - "frame": {"x":522,"y":23,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_5.png": -{ - "frame": {"x":527,"y":3,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_6.png": -{ - "frame": {"x":504,"y":94,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_7.png": -{ - "frame": {"x":516,"y":77,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_8.png": -{ - "frame": {"x":504,"y":111,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_9.png": -{ - "frame": {"x":523,"y":57,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_10.png": -{ - "frame": {"x":328,"y":26,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_11.png": -{ - "frame": {"x":345,"y":26,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_12.png": -{ - "frame": {"x":362,"y":26,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_13.png": -{ - "frame": {"x":379,"y":26,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_14.png": -{ - "frame": {"x":396,"y":26,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_15.png": -{ - "frame": {"x":413,"y":49,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_16.png": -{ - "frame": {"x":430,"y":49,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_17.png": -{ - "frame": {"x":436,"y":111,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_18.png": -{ - "frame": {"x":453,"y":111,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_19.png": -{ - "frame": {"x":447,"y":49,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_20.png": -{ - "frame": {"x":470,"y":105,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_21.png": -{ - "frame": {"x":482,"y":84,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_22.png": -{ - "frame": {"x":489,"y":60,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_23.png": -{ - "frame": {"x":504,"y":43,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_24.png": -{ - "frame": {"x":505,"y":23,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_25.png": -{ - "frame": {"x":487,"y":101,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_26.png": -{ - "frame": {"x":499,"y":77,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_27.png": -{ - "frame": {"x":506,"y":60,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_0.png": -{ - "frame": {"x":538,"y":40,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_1.png": -{ - "frame": {"x":539,"y":20,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_2.png": -{ - "frame": {"x":557,"y":54,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_3.png": -{ - "frame": {"x":590,"y":20,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_4.png": -{ - "frame": {"x":595,"y":3,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_5.png": -{ - "frame": {"x":555,"y":108,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_6.png": -{ - "frame": {"x":572,"y":88,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_7.png": -{ - "frame": {"x":584,"y":71,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_8.png": -{ - "frame": {"x":591,"y":54,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_9.png": -{ - "frame": {"x":606,"y":37,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_10.png": -{ - "frame": {"x":544,"y":3,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_11.png": -{ - "frame": {"x":521,"y":94,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_12.png": -{ - "frame": {"x":521,"y":111,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_13.png": -{ - "frame": {"x":533,"y":74,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_14.png": -{ - "frame": {"x":540,"y":57,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_15.png": -{ - "frame": {"x":555,"y":37,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_16.png": -{ - "frame": {"x":556,"y":20,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_17.png": -{ - "frame": {"x":561,"y":3,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_18.png": -{ - "frame": {"x":538,"y":91,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_19.png": -{ - "frame": {"x":550,"y":74,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_20.png": -{ - "frame": {"x":572,"y":37,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_21.png": -{ - "frame": {"x":573,"y":20,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_22.png": -{ - "frame": {"x":578,"y":3,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_23.png": -{ - "frame": {"x":538,"y":108,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_24.png": -{ - "frame": {"x":555,"y":91,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_25.png": -{ - "frame": {"x":567,"y":71,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_26.png": -{ - "frame": {"x":574,"y":54,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_27.png": -{ - "frame": {"x":589,"y":37,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_0.png": -{ - "frame": {"x":607,"y":20,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_1.png": -{ - "frame": {"x":612,"y":3,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_2.png": -{ - "frame": {"x":625,"y":54,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_3.png": -{ - "frame": {"x":623,"y":88,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_4.png": -{ - "frame": {"x":635,"y":71,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_5.png": -{ - "frame": {"x":642,"y":54,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_6.png": -{ - "frame": {"x":623,"y":105,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_7.png": -{ - "frame": {"x":659,"y":54,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_8.png": -{ - "frame": {"x":652,"y":71,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_9.png": -{ - "frame": {"x":669,"y":71,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_10.png": -{ - "frame": {"x":572,"y":105,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_11.png": -{ - "frame": {"x":589,"y":88,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_12.png": -{ - "frame": {"x":601,"y":71,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_13.png": -{ - "frame": {"x":608,"y":54,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_14.png": -{ - "frame": {"x":623,"y":37,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_15.png": -{ - "frame": {"x":624,"y":20,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_16.png": -{ - "frame": {"x":629,"y":3,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_17.png": -{ - "frame": {"x":589,"y":105,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_18.png": -{ - "frame": {"x":606,"y":88,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_19.png": -{ - "frame": {"x":618,"y":71,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_20.png": -{ - "frame": {"x":640,"y":37,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_21.png": -{ - "frame": {"x":641,"y":20,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_22.png": -{ - "frame": {"x":646,"y":3,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_23.png": -{ - "frame": {"x":606,"y":105,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_24.png": -{ - "frame": {"x":663,"y":3,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_25.png": -{ - "frame": {"x":658,"y":20,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_26.png": -{ - "frame": {"x":657,"y":37,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_27.png": -{ - "frame": {"x":674,"y":37,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/blueprints/advanced_processor.png": -{ - "frame": {"x":3,"y":83,"w":38,"h":38}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":38}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/blueprints/belt_left.png": -{ - "frame": {"x":640,"y":88,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/blueprints/belt_right.png": -{ - "frame": {"x":640,"y":105,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/blueprints/belt_top.png": -{ - "frame": {"x":657,"y":88,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/blueprints/cutter-quad.png": -{ - "frame": {"x":165,"y":81,"w":76,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":76,"h":19}, - "sourceSize": {"w":77,"h":19} -}, -"sprites/blueprints/cutter.png": -{ - "frame": {"x":327,"y":43,"w":36,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/blueprints/energy_generator.png": -{ - "frame": {"x":166,"y":3,"w":37,"h":37}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":37,"h":37}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/blueprints/miner-chainable.png": -{ - "frame": {"x":328,"y":66,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/miner.png": -{ - "frame": {"x":351,"y":66,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/mixer.png": -{ - "frame": {"x":286,"y":44,"w":37,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/blueprints/painter-double.png": -{ - "frame": {"x":45,"y":83,"w":38,"h":38}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":38}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/blueprints/painter-mirrored.png": -{ - "frame": {"x":244,"y":44,"w":38,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/blueprints/painter-quad.png": -{ - "frame": {"x":82,"y":45,"w":77,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":77,"h":19}, - "sourceSize": {"w":77,"h":19} -}, -"sprites/blueprints/painter.png": -{ - "frame": {"x":248,"y":3,"w":38,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/blueprints/rotater-ccw.png": -{ - "frame": {"x":367,"y":43,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/rotater.png": -{ - "frame": {"x":367,"y":89,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/splitter-compact-inverse.png": -{ - "frame": {"x":374,"y":66,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/splitter-compact.png": -{ - "frame": {"x":390,"y":43,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/splitter.png": -{ - "frame": {"x":332,"y":3,"w":36,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/blueprints/stacker.png": -{ - "frame": {"x":245,"y":101,"w":37,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/blueprints/trash-storage.png": -{ - "frame": {"x":87,"y":82,"w":35,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":35,"h":38}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/blueprints/trash.png": -{ - "frame": {"x":412,"y":3,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/underground_belt_entry-tier2.png": -{ - "frame": {"x":458,"y":3,"w":19,"h":18}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":19,"h":18}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/underground_belt_entry.png": -{ - "frame": {"x":443,"y":66,"w":19,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":3,"w":19,"h":16}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/underground_belt_exit-tier2.png": -{ - "frame": {"x":459,"y":25,"w":19,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/underground_belt_exit.png": -{ - "frame": {"x":464,"y":45,"w":19,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/wire_crossings-merger.png": -{ - "frame": {"x":459,"y":86,"w":19,"h":15}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":15}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/wire_crossings.png": -{ - "frame": {"x":248,"y":26,"w":19,"h":14}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":5,"w":19,"h":14}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/wire_left.png": -{ - "frame": {"x":154,"y":68,"w":10,"h":9}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":10,"h":9}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/blueprints/wire_right.png": -{ - "frame": {"x":168,"y":68,"w":9,"h":9}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":9,"h":9}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/blueprints/wire_top.png": -{ - "frame": {"x":680,"y":3,"w":6,"h":13}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":6,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/buildings/advanced_processor.png": -{ - "frame": {"x":82,"y":3,"w":38,"h":38}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":38}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":674,"y":88,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":657,"y":105,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/buildings/belt_top.png": -{ - "frame": {"x":294,"y":26,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/buildings/cutter-quad.png": -{ - "frame": {"x":165,"y":104,"w":76,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":76,"h":19}, - "sourceSize": {"w":77,"h":19} -}, -"sprites/buildings/cutter.png": -{ - "frame": {"x":372,"y":3,"w":36,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/buildings/energy_generator.png": -{ - "frame": {"x":207,"y":3,"w":37,"h":37}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":37,"h":37}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/buildings/hub.png": -{ - "frame": {"x":3,"y":3,"w":75,"h":76}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":75,"h":76}, - "sourceSize": {"w":77,"h":77} -}, -"sprites/buildings/miner-chainable.png": -{ - "frame": {"x":390,"y":89,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/miner.png": -{ - "frame": {"x":397,"y":66,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/mixer.png": -{ - "frame": {"x":286,"y":101,"w":37,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/buildings/painter-double.png": -{ - "frame": {"x":124,"y":3,"w":38,"h":38}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":38}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/buildings/painter-mirrored.png": -{ - "frame": {"x":290,"y":3,"w":38,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/buildings/painter-quad.png": -{ - "frame": {"x":163,"y":45,"w":77,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":77,"h":19}, - "sourceSize": {"w":77,"h":19} -}, -"sprites/buildings/painter.png": -{ - "frame": {"x":245,"y":78,"w":38,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/buildings/rotater-ccw.png": -{ - "frame": {"x":413,"y":89,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/rotater.png": -{ - "frame": {"x":413,"y":26,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/splitter-compact-inverse.png": -{ - "frame": {"x":435,"y":3,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/splitter-compact.png": -{ - "frame": {"x":420,"y":66,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/splitter.png": -{ - "frame": {"x":327,"y":90,"w":36,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/buildings/stacker.png": -{ - "frame": {"x":287,"y":67,"w":37,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/buildings/trash-storage.png": -{ - "frame": {"x":126,"y":81,"w":35,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":35,"h":38}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/buildings/trash.png": -{ - "frame": {"x":436,"y":26,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/underground_belt_entry-tier2.png": -{ - "frame": {"x":436,"y":89,"w":19,"h":18}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":19,"h":18}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/underground_belt_entry.png": -{ - "frame": {"x":481,"y":3,"w":19,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":3,"w":19,"h":16}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/underground_belt_exit-tier2.png": -{ - "frame": {"x":482,"y":23,"w":19,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/underground_belt_exit.png": -{ - "frame": {"x":504,"y":3,"w":19,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/wire_crossings-merger.png": -{ - "frame": {"x":466,"y":65,"w":19,"h":15}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":15}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/wire_crossings.png": -{ - "frame": {"x":271,"y":26,"w":19,"h":14}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":5,"w":19,"h":14}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/wire_left.png": -{ - "frame": {"x":181,"y":68,"w":9,"h":9}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":9,"h":9}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/buildings/wire_right.png": -{ - "frame": {"x":194,"y":68,"w":9,"h":9}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":9,"h":9}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/buildings/wire_top.png": -{ - "frame": {"x":675,"y":20,"w":5,"h":13}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":5,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/debug/acceptor_slot.png": -{ - "frame": {"x":207,"y":68,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/debug/ejector_slot.png": -{ - "frame": {"x":217,"y":68,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/map_overview/belt_forward.png": -{ - "frame": {"x":306,"y":90,"w":3,"h":3}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, - "sourceSize": {"w":3,"h":3} -}, -"sprites/map_overview/belt_left.png": -{ - "frame": {"x":313,"y":90,"w":3,"h":3}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, - "sourceSize": {"w":3,"h":3} -}, -"sprites/map_overview/belt_right.png": -{ - "frame": {"x":320,"y":90,"w":3,"h":3}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, - "sourceSize": {"w":3,"h":3} -}, -"sprites/misc/deletion_marker.png": -{ - "frame": {"x":82,"y":68,"w":10,"h":10}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":10,"h":10}, - "sourceSize": {"w":10,"h":10} -}, -"sprites/misc/energy_generator_overlay.png": -{ - "frame": {"x":110,"y":68,"w":18,"h":9}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":27,"w":18,"h":9}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/misc/hub_direction_indicator.png": -{ - "frame": {"x":327,"y":113,"w":3,"h":3}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, - "sourceSize": {"w":3,"h":3} -}, -"sprites/misc/lock_direction_indicator.png": -{ - "frame": {"x":297,"y":90,"w":5,"h":5}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":5,"h":5}, - "sourceSize": {"w":5,"h":5} -}, -"sprites/misc/slot_bad_arrow.png": -{ - "frame": {"x":82,"y":68,"w":10,"h":10}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":10,"h":10}, - "sourceSize": {"w":10,"h":10} -}, -"sprites/misc/slot_good_arrow.png": -{ - "frame": {"x":96,"y":68,"w":10,"h":10}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":10,"h":10}, - "sourceSize": {"w":10,"h":10} -}, -"sprites/misc/storage_overlay.png": -{ - "frame": {"x":132,"y":68,"w":18,"h":9}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":18,"h":9}, - "sourceSize": {"w":18,"h":9} -}, -"sprites/misc/waypoint.png": -{ - "frame": {"x":327,"y":120,"w":3,"h":3}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, - "sourceSize": {"w":3,"h":3} -}, -"sprites/misc/wires_overlay_tile.png": -{ - "frame": {"x":674,"y":105,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/wires/battery_empty.png": -{ - "frame": {"x":227,"y":68,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/wires/battery_full.png": -{ - "frame": {"x":237,"y":68,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/wires/battery_low.png": -{ - "frame": {"x":247,"y":67,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/wires/battery_medium.png": -{ - "frame": {"x":257,"y":67,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/wires/negative_energy.png": -{ - "frame": {"x":267,"y":67,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/wires/pin_negative_accept.png": -{ - "frame": {"x":367,"y":112,"w":11,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":11,"h":12}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/wires/pin_negative_eject.png": -{ - "frame": {"x":397,"y":112,"w":9,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":9,"h":12}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/wires/pin_positive_accept.png": -{ - "frame": {"x":410,"y":112,"w":9,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":9,"h":12}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/wires/pin_positive_eject.png": -{ - "frame": {"x":382,"y":112,"w":11,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":11,"h":12}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/wires/positive_energy.png": -{ - "frame": {"x":277,"y":67,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/wires/waste_piled.png": -{ - "frame": {"x":287,"y":90,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}}, -"meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "atlas0_10.png", - "format": "RGBA8888", - "size": {"w":690,"h":127}, - "scale": "0.1", - "smartupdate": "$TexturePacker:SmartUpdate:4e5fb3bd7f1e5423e4fcea2215debe11:0c5d091d0b928944c68553dcc592c801:f159918d23e5952766c6d23ab52278c6$" -} -} diff --git a/res_built/atlas/atlas0_10.png b/res_built/atlas/atlas0_10.png deleted file mode 100644 index b75b013b..00000000 Binary files a/res_built/atlas/atlas0_10.png and /dev/null differ diff --git a/res_built/atlas/atlas0_100.json b/res_built/atlas/atlas0_100.json deleted file mode 100644 index 974d23ec..00000000 --- a/res_built/atlas/atlas0_100.json +++ /dev/null @@ -1,1388 +0,0 @@ -{"frames": { - -"sprites/belt/forward_0.png": -{ - "frame": {"x":1115,"y":1688,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_1.png": -{ - "frame": {"x":1115,"y":1818,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_2.png": -{ - "frame": {"x":1353,"y":2194,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_3.png": -{ - "frame": {"x":1470,"y":2445,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_4.png": -{ - "frame": {"x":1871,"y":199,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_5.png": -{ - "frame": {"x":1263,"y":1163,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_6.png": -{ - "frame": {"x":1484,"y":1222,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_7.png": -{ - "frame": {"x":1372,"y":1347,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_8.png": -{ - "frame": {"x":1476,"y":1352,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_9.png": -{ - "frame": {"x":1531,"y":1748,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_10.png": -{ - "frame": {"x":1100,"y":2065,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_11.png": -{ - "frame": {"x":1219,"y":1687,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_12.png": -{ - "frame": {"x":1219,"y":1817,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_13.png": -{ - "frame": {"x":1225,"y":1947,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_14.png": -{ - "frame": {"x":1132,"y":2277,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_15.png": -{ - "frame": {"x":1132,"y":2407,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_16.png": -{ - "frame": {"x":1123,"y":2537,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_17.png": -{ - "frame": {"x":1323,"y":1687,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_18.png": -{ - "frame": {"x":1323,"y":1817,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_19.png": -{ - "frame": {"x":1329,"y":1947,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_20.png": -{ - "frame": {"x":1353,"y":2324,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_21.png": -{ - "frame": {"x":1260,"y":1301,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_22.png": -{ - "frame": {"x":1268,"y":1431,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_23.png": -{ - "frame": {"x":1427,"y":1678,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_24.png": -{ - "frame": {"x":1427,"y":1808,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_25.png": -{ - "frame": {"x":1433,"y":1938,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_26.png": -{ - "frame": {"x":1457,"y":2185,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_27.png": -{ - "frame": {"x":1457,"y":2315,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_0.png": -{ - "frame": {"x":1108,"y":1948,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_1.png": -{ - "frame": {"x":1217,"y":1570,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_2.png": -{ - "frame": {"x":1461,"y":2575,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_3.png": -{ - "frame": {"x":1580,"y":1397,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_4.png": -{ - "frame": {"x":1697,"y":1409,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_5.png": -{ - "frame": {"x":1814,"y":1409,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_6.png": -{ - "frame": {"x":1451,"y":1482,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_7.png": -{ - "frame": {"x":1568,"y":1514,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_8.png": -{ - "frame": {"x":1685,"y":1526,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_9.png": -{ - "frame": {"x":1802,"y":1526,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_10.png": -{ - "frame": {"x":1204,"y":2077,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_11.png": -{ - "frame": {"x":1321,"y":2077,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_12.png": -{ - "frame": {"x":1236,"y":2194,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_13.png": -{ - "frame": {"x":1236,"y":2311,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_14.png": -{ - "frame": {"x":1236,"y":2428,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_15.png": -{ - "frame": {"x":1227,"y":2545,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_16.png": -{ - "frame": {"x":1353,"y":2454,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_17.png": -{ - "frame": {"x":1344,"y":2571,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_18.png": -{ - "frame": {"x":1334,"y":1561,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_19.png": -{ - "frame": {"x":1438,"y":2068,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_20.png": -{ - "frame": {"x":1367,"y":1113,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_21.png": -{ - "frame": {"x":1367,"y":1230,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_22.png": -{ - "frame": {"x":1588,"y":1163,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_23.png": -{ - "frame": {"x":1588,"y":1280,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_24.png": -{ - "frame": {"x":1705,"y":1175,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_25.png": -{ - "frame": {"x":1822,"y":1175,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_26.png": -{ - "frame": {"x":1705,"y":1292,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_27.png": -{ - "frame": {"x":1822,"y":1292,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_0.png": -{ - "frame": {"x":1531,"y":1631,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_1.png": -{ - "frame": {"x":1648,"y":1643,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_2.png": -{ - "frame": {"x":1555,"y":1995,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_3.png": -{ - "frame": {"x":1795,"y":2228,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_4.png": -{ - "frame": {"x":1912,"y":2111,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_5.png": -{ - "frame": {"x":1912,"y":2228,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_6.png": -{ - "frame": {"x":1574,"y":2346,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_7.png": -{ - "frame": {"x":1691,"y":2345,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_8.png": -{ - "frame": {"x":1808,"y":2345,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_9.png": -{ - "frame": {"x":1925,"y":2345,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_10.png": -{ - "frame": {"x":1765,"y":1643,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_11.png": -{ - "frame": {"x":1635,"y":1760,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_12.png": -{ - "frame": {"x":1752,"y":1760,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_13.png": -{ - "frame": {"x":1537,"y":1878,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_14.png": -{ - "frame": {"x":1654,"y":1877,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_15.png": -{ - "frame": {"x":1771,"y":1877,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_16.png": -{ - "frame": {"x":1882,"y":1643,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_17.png": -{ - "frame": {"x":1869,"y":1760,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_18.png": -{ - "frame": {"x":1888,"y":1877,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_19.png": -{ - "frame": {"x":1919,"y":1526,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_20.png": -{ - "frame": {"x":1672,"y":1994,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_21.png": -{ - "frame": {"x":1789,"y":1994,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_22.png": -{ - "frame": {"x":1906,"y":1994,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_23.png": -{ - "frame": {"x":1561,"y":2112,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_24.png": -{ - "frame": {"x":1561,"y":2229,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_25.png": -{ - "frame": {"x":1678,"y":2111,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_26.png": -{ - "frame": {"x":1678,"y":2228,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_27.png": -{ - "frame": {"x":1795,"y":2111,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/blueprints/advanced_processor.png": -{ - "frame": {"x":3,"y":1702,"w":374,"h":358}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":10,"y":12,"w":374,"h":358}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/blueprints/belt_left.png": -{ - "frame": {"x":1150,"y":1452,"w":114,"h":114}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":12,"w":114,"h":114}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/blueprints/belt_right.png": -{ - "frame": {"x":1099,"y":1570,"w":114,"h":114}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":12,"y":12,"w":114,"h":114}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/blueprints/belt_top.png": -{ - "frame": {"x":1260,"y":957,"w":102,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":12,"y":0,"w":102,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/blueprints/cutter-quad.png": -{ - "frame": {"x":735,"y":395,"w":730,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":730,"h":191}, - "sourceSize": {"w":768,"h":192} -}, -"sprites/blueprints/cutter.png": -{ - "frame": {"x":381,"y":1707,"w":341,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":341,"h":191}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/blueprints/energy_generator.png": -{ - "frame": {"x":735,"y":590,"w":348,"h":364}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":20,"w":348,"h":364}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/blueprints/miner-chainable.png": -{ - "frame": {"x":763,"y":2290,"w":182,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":182,"h":190}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/miner.png": -{ - "frame": {"x":914,"y":2096,"w":182,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":182,"h":190}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/mixer.png": -{ - "frame": {"x":3,"y":2424,"w":347,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":18,"y":0,"w":347,"h":191}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/blueprints/painter-double.png": -{ - "frame": {"x":3,"y":931,"w":384,"h":382}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":384,"h":382}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/blueprints/painter-mirrored.png": -{ - "frame": {"x":1485,"y":3,"w":384,"h":192}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":384,"h":192}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/blueprints/painter-quad.png": -{ - "frame": {"x":735,"y":3,"w":746,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":746,"h":192}, - "sourceSize": {"w":768,"h":192} -}, -"sprites/blueprints/painter.png": -{ - "frame": {"x":1483,"y":199,"w":384,"h":192}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":384,"h":192}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/blueprints/rotater-ccw.png": -{ - "frame": {"x":922,"y":1694,"w":189,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":189,"h":191}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/rotater.png": -{ - "frame": {"x":550,"y":2460,"w":189,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":189,"h":191}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/splitter-compact-inverse.png": -{ - "frame": {"x":743,"y":2484,"w":188,"h":182}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":188,"h":182}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/splitter-compact.png": -{ - "frame": {"x":1753,"y":989,"w":185,"h":182}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":4,"w":185,"h":182}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/splitter.png": -{ - "frame": {"x":724,"y":1347,"w":340,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":340,"h":191}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/blueprints/stacker.png": -{ - "frame": {"x":726,"y":958,"w":347,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":18,"y":0,"w":347,"h":191}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/blueprints/trash-storage.png": -{ - "frame": {"x":391,"y":931,"w":331,"h":384}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":29,"y":0,"w":331,"h":384}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/blueprints/trash.png": -{ - "frame": {"x":726,"y":1694,"w":192,"h":192}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/underground_belt_entry-tier2.png": -{ - "frame": {"x":576,"y":2290,"w":183,"h":166}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":26,"w":183,"h":166}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/underground_belt_entry.png": -{ - "frame": {"x":913,"y":1542,"w":182,"h":148}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":44,"w":182,"h":148}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/underground_belt_exit-tier2.png": -{ - "frame": {"x":724,"y":1542,"w":185,"h":148}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":185,"h":148}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/underground_belt_exit.png": -{ - "frame": {"x":922,"y":1889,"w":182,"h":148}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":182,"h":148}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/wire_crossings-merger.png": -{ - "frame": {"x":380,"y":2290,"w":192,"h":136}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":136}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/wire_crossings.png": -{ - "frame": {"x":1786,"y":854,"w":192,"h":131}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":61,"w":192,"h":131}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/wire_left.png": -{ - "frame": {"x":436,"y":2625,"w":79,"h":79}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":47,"w":79,"h":79}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/blueprints/wire_right.png": -{ - "frame": {"x":353,"y":2625,"w":79,"h":80}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":47,"y":46,"w":79,"h":80}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/blueprints/wire_top.png": -{ - "frame": {"x":1982,"y":854,"w":32,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":47,"y":0,"w":32,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/buildings/advanced_processor.png": -{ - "frame": {"x":3,"y":2064,"w":373,"h":356}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":13,"w":373,"h":356}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":1578,"y":2572,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":1718,"y":2462,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/buildings/belt_top.png": -{ - "frame": {"x":1115,"y":1688,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/buildings/cutter-quad.png": -{ - "frame": {"x":3,"y":737,"w":728,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":24,"y":0,"w":728,"h":190}, - "sourceSize": {"w":768,"h":192} -}, -"sprites/buildings/cutter.png": -{ - "frame": {"x":381,"y":1902,"w":339,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":24,"y":0,"w":339,"h":190}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/buildings/energy_generator.png": -{ - "frame": {"x":1087,"y":590,"w":346,"h":363}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":21,"y":21,"w":346,"h":363}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/buildings/hub.png": -{ - "frame": {"x":3,"y":3,"w":728,"h":730}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":22,"w":728,"h":730}, - "sourceSize": {"w":768,"h":768} -}, -"sprites/buildings/miner-chainable.png": -{ - "frame": {"x":1077,"y":958,"w":179,"h":188}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":1,"w":179,"h":188}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/miner.png": -{ - "frame": {"x":949,"y":2290,"w":179,"h":189}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":179,"h":189}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/mixer.png": -{ - "frame": {"x":1437,"y":785,"w":345,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":19,"y":0,"w":345,"h":190}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/buildings/painter-double.png": -{ - "frame": {"x":3,"y":1317,"w":384,"h":381}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":384,"h":381}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/buildings/painter-mirrored.png": -{ - "frame": {"x":1469,"y":395,"w":384,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":384,"h":191}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/buildings/painter-quad.png": -{ - "frame": {"x":735,"y":199,"w":744,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":744,"h":192}, - "sourceSize": {"w":768,"h":192} -}, -"sprites/buildings/painter.png": -{ - "frame": {"x":1437,"y":590,"w":384,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":384,"h":191}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/buildings/rotater-ccw.png": -{ - "frame": {"x":723,"y":2096,"w":187,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":187,"h":190}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/rotater.png": -{ - "frame": {"x":724,"y":1902,"w":187,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":187,"h":190}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/splitter-compact-inverse.png": -{ - "frame": {"x":1562,"y":979,"w":187,"h":180}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":5,"w":187,"h":180}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/splitter-compact.png": -{ - "frame": {"x":935,"y":2484,"w":184,"h":180}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":5,"w":184,"h":180}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/splitter.png": -{ - "frame": {"x":380,"y":2096,"w":339,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":24,"y":0,"w":339,"h":190}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/buildings/stacker.png": -{ - "frame": {"x":726,"y":1153,"w":345,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":19,"y":0,"w":345,"h":190}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/buildings/trash-storage.png": -{ - "frame": {"x":391,"y":1319,"w":329,"h":384}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":30,"y":0,"w":329,"h":384}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/buildings/trash.png": -{ - "frame": {"x":354,"y":2430,"w":192,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":192,"h":191}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/underground_belt_entry-tier2.png": -{ - "frame": {"x":1857,"y":395,"w":181,"h":165}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":27,"w":181,"h":165}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/underground_belt_entry.png": -{ - "frame": {"x":1857,"y":564,"w":181,"h":147}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":45,"w":181,"h":147}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/underground_belt_exit-tier2.png": -{ - "frame": {"x":1077,"y":1150,"w":182,"h":147}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":182,"h":147}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/underground_belt_exit.png": -{ - "frame": {"x":1075,"y":1301,"w":181,"h":147}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":181,"h":147}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/wire_crossings-merger.png": -{ - "frame": {"x":1825,"y":715,"w":192,"h":135}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":135}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/wire_crossings.png": -{ - "frame": {"x":1366,"y":979,"w":192,"h":130}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":62,"w":192,"h":130}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/wire_left.png": -{ - "frame": {"x":1068,"y":1452,"w":78,"h":78}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":48,"w":78,"h":78}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/buildings/wire_right.png": -{ - "frame": {"x":1100,"y":2195,"w":78,"h":78}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":48,"y":48,"w":78,"h":78}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/buildings/wire_top.png": -{ - "frame": {"x":1942,"y":989,"w":30,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":48,"y":0,"w":30,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/debug/acceptor_slot.png": -{ - "frame": {"x":1182,"y":2195,"w":50,"h":64}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":50,"h":64}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/debug/ejector_slot.png": -{ - "frame": {"x":1372,"y":1477,"w":50,"h":64}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":50,"h":64}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/map_overview/belt_forward.png": -{ - "frame": {"x":1503,"y":1641,"w":24,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":24,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/map_overview/belt_left.png": -{ - "frame": {"x":1825,"y":590,"w":28,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":28,"h":28}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/map_overview/belt_right.png": -{ - "frame": {"x":1825,"y":622,"w":28,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":28,"h":28}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/misc/deletion_marker.png": -{ - "frame": {"x":267,"y":2619,"w":82,"h":82}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":7,"w":82,"h":82}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/misc/energy_generator_overlay.png": -{ - "frame": {"x":1873,"y":135,"w":153,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":183,"y":290,"w":153,"h":57}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/misc/hub_direction_indicator.png": -{ - "frame": {"x":1099,"y":1534,"w":32,"h":32}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/misc/lock_direction_indicator.png": -{ - "frame": {"x":1451,"y":1641,"w":48,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":48,"h":30}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/misc/slot_bad_arrow.png": -{ - "frame": {"x":267,"y":2619,"w":82,"h":82}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":7,"w":82,"h":82}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/misc/slot_good_arrow.png": -{ - "frame": {"x":183,"y":2619,"w":80,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":80,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/misc/storage_overlay.png": -{ - "frame": {"x":3,"y":2619,"w":176,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":4,"w":176,"h":86}, - "sourceSize": {"w":180,"h":90} -}, -"sprites/misc/waypoint.png": -{ - "frame": {"x":1786,"y":785,"w":24,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":24,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/misc/wires_overlay_tile.png": -{ - "frame": {"x":1873,"y":3,"w":128,"h":128}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, - "sourceSize": {"w":128,"h":128} -}, -"sprites/wires/battery_empty.png": -{ - "frame": {"x":519,"y":2655,"w":38,"h":60}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":2,"w":38,"h":60}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/battery_full.png": -{ - "frame": {"x":1871,"y":329,"w":58,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":14,"w":58,"h":38}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/battery_low.png": -{ - "frame": {"x":1451,"y":1599,"w":58,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":14,"w":58,"h":38}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/battery_medium.png": -{ - "frame": {"x":1835,"y":2462,"w":58,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":14,"w":58,"h":38}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/negative_energy.png": -{ - "frame": {"x":561,"y":2655,"w":42,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":11,"w":42,"h":42}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/pin_negative_accept.png": -{ - "frame": {"x":1484,"y":1113,"w":73,"h":105}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":27,"y":0,"w":73,"h":105}, - "sourceSize": {"w":128,"h":128} -}, -"sprites/wires/pin_negative_eject.png": -{ - "frame": {"x":1975,"y":196,"w":63,"h":100}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":32,"y":0,"w":63,"h":100}, - "sourceSize": {"w":128,"h":128} -}, -"sprites/wires/pin_positive_accept.png": -{ - "frame": {"x":1651,"y":2463,"w":63,"h":100}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":32,"y":0,"w":63,"h":100}, - "sourceSize": {"w":128,"h":128} -}, -"sprites/wires/pin_positive_eject.png": -{ - "frame": {"x":1574,"y":2463,"w":73,"h":105}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":27,"y":0,"w":73,"h":105}, - "sourceSize": {"w":128,"h":128} -}, -"sprites/wires/positive_energy.png": -{ - "frame": {"x":1835,"y":2504,"w":42,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":11,"w":42,"h":42}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/waste_piled.png": -{ - "frame": {"x":1260,"y":1087,"w":58,"h":55}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":4,"w":58,"h":55}, - "sourceSize": {"w":64,"h":64} -}}, -"meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "atlas0_100.png", - "format": "RGBA8888", - "size": {"w":2041,"h":2718}, - "scale": "1", - "smartupdate": "$TexturePacker:SmartUpdate:4e5fb3bd7f1e5423e4fcea2215debe11:0c5d091d0b928944c68553dcc592c801:f159918d23e5952766c6d23ab52278c6$" -} -} diff --git a/res_built/atlas/atlas0_100.png b/res_built/atlas/atlas0_100.png deleted file mode 100644 index a40f84d0..00000000 Binary files a/res_built/atlas/atlas0_100.png and /dev/null differ diff --git a/res_built/atlas/atlas0_25.json b/res_built/atlas/atlas0_25.json deleted file mode 100644 index dd58adcc..00000000 --- a/res_built/atlas/atlas0_25.json +++ /dev/null @@ -1,1388 +0,0 @@ -{"frames": { - -"sprites/belt/forward_0.png": -{ - "frame": {"x":195,"y":433,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_1.png": -{ - "frame": {"x":741,"y":197,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_2.png": -{ - "frame": {"x":627,"y":252,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_3.png": -{ - "frame": {"x":564,"y":289,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_4.png": -{ - "frame": {"x":596,"y":288,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_5.png": -{ - "frame": {"x":628,"y":288,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_6.png": -{ - "frame": {"x":660,"y":288,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_7.png": -{ - "frame": {"x":692,"y":283,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_8.png": -{ - "frame": {"x":422,"y":331,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_9.png": -{ - "frame": {"x":422,"y":367,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_10.png": -{ - "frame": {"x":227,"y":433,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_11.png": -{ - "frame": {"x":435,"y":253,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_12.png": -{ - "frame": {"x":467,"y":253,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_13.png": -{ - "frame": {"x":499,"y":253,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_14.png": -{ - "frame": {"x":531,"y":253,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_15.png": -{ - "frame": {"x":390,"y":295,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_16.png": -{ - "frame": {"x":390,"y":331,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_17.png": -{ - "frame": {"x":390,"y":367,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_18.png": -{ - "frame": {"x":563,"y":253,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_19.png": -{ - "frame": {"x":595,"y":252,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_20.png": -{ - "frame": {"x":659,"y":252,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_21.png": -{ - "frame": {"x":773,"y":197,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_22.png": -{ - "frame": {"x":792,"y":159,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_23.png": -{ - "frame": {"x":725,"y":249,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_24.png": -{ - "frame": {"x":436,"y":289,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_25.png": -{ - "frame": {"x":468,"y":289,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_26.png": -{ - "frame": {"x":500,"y":289,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_27.png": -{ - "frame": {"x":532,"y":289,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_0.png": -{ - "frame": {"x":691,"y":249,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_1.png": -{ - "frame": {"x":761,"y":233,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_2.png": -{ - "frame": {"x":758,"y":301,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_3.png": -{ - "frame": {"x":465,"y":393,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_4.png": -{ - "frame": {"x":499,"y":393,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_5.png": -{ - "frame": {"x":533,"y":393,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_6.png": -{ - "frame": {"x":567,"y":393,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_7.png": -{ - "frame": {"x":795,"y":233,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_8.png": -{ - "frame": {"x":792,"y":267,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_9.png": -{ - "frame": {"x":792,"y":301,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_10.png": -{ - "frame": {"x":724,"y":285,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_11.png": -{ - "frame": {"x":454,"y":325,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_12.png": -{ - "frame": {"x":454,"y":359,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_13.png": -{ - "frame": {"x":488,"y":325,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_14.png": -{ - "frame": {"x":488,"y":359,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_15.png": -{ - "frame": {"x":522,"y":325,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_16.png": -{ - "frame": {"x":522,"y":359,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_17.png": -{ - "frame": {"x":556,"y":325,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_18.png": -{ - "frame": {"x":556,"y":359,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_19.png": -{ - "frame": {"x":758,"y":267,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_20.png": -{ - "frame": {"x":295,"y":407,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_21.png": -{ - "frame": {"x":329,"y":407,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_22.png": -{ - "frame": {"x":363,"y":407,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_23.png": -{ - "frame": {"x":397,"y":403,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_24.png": -{ - "frame": {"x":291,"y":441,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_25.png": -{ - "frame": {"x":325,"y":441,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_26.png": -{ - "frame": {"x":359,"y":441,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_27.png": -{ - "frame": {"x":431,"y":403,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_0.png": -{ - "frame": {"x":465,"y":427,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_1.png": -{ - "frame": {"x":499,"y":427,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_2.png": -{ - "frame": {"x":601,"y":393,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_3.png": -{ - "frame": {"x":703,"y":387,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_4.png": -{ - "frame": {"x":703,"y":421,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_5.png": -{ - "frame": {"x":737,"y":384,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_6.png": -{ - "frame": {"x":737,"y":418,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_7.png": -{ - "frame": {"x":771,"y":369,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_8.png": -{ - "frame": {"x":771,"y":403,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_9.png": -{ - "frame": {"x":771,"y":437,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_10.png": -{ - "frame": {"x":533,"y":427,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_11.png": -{ - "frame": {"x":567,"y":427,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_12.png": -{ - "frame": {"x":590,"y":325,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_13.png": -{ - "frame": {"x":590,"y":359,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_14.png": -{ - "frame": {"x":624,"y":324,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_15.png": -{ - "frame": {"x":658,"y":324,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_16.png": -{ - "frame": {"x":692,"y":319,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_17.png": -{ - "frame": {"x":624,"y":358,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_18.png": -{ - "frame": {"x":658,"y":358,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_19.png": -{ - "frame": {"x":692,"y":353,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_20.png": -{ - "frame": {"x":601,"y":427,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_21.png": -{ - "frame": {"x":635,"y":392,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_22.png": -{ - "frame": {"x":635,"y":426,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_23.png": -{ - "frame": {"x":669,"y":392,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_24.png": -{ - "frame": {"x":669,"y":426,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_25.png": -{ - "frame": {"x":726,"y":350,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_26.png": -{ - "frame": {"x":760,"y":335,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_27.png": -{ - "frame": {"x":794,"y":335,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/blueprints/advanced_processor.png": -{ - "frame": {"x":3,"y":344,"w":95,"h":92}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":2,"w":95,"h":92}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/belt_left.png": -{ - "frame": {"x":737,"y":452,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/blueprints/belt_right.png": -{ - "frame": {"x":703,"y":455,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/blueprints/belt_top.png": -{ - "frame": {"x":259,"y":432,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/blueprints/cutter-quad.png": -{ - "frame": {"x":3,"y":192,"w":184,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, - "sourceSize": {"w":192,"h":48} -}, -"sprites/blueprints/cutter.png": -{ - "frame": {"x":675,"y":55,"w":87,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/energy_generator.png": -{ - "frame": {"x":102,"y":344,"w":89,"h":92}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":89,"h":92}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/miner-chainable.png": -{ - "frame": {"x":383,"y":205,"w":47,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/miner.png": -{ - "frame": {"x":434,"y":201,"w":47,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/mixer.png": -{ - "frame": {"x":671,"y":3,"w":89,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/painter-double.png": -{ - "frame": {"x":191,"y":107,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/painter-mirrored.png": -{ - "frame": {"x":383,"y":55,"w":96,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/painter-quad.png": -{ - "frame": {"x":191,"y":3,"w":188,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, - "sourceSize": {"w":192,"h":48} -}, -"sprites/blueprints/painter.png": -{ - "frame": {"x":571,"y":3,"w":96,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/rotater-ccw.png": -{ - "frame": {"x":764,"y":3,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/rotater.png": -{ - "frame": {"x":766,"y":55,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/splitter-compact-inverse.png": -{ - "frame": {"x":756,"y":107,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/splitter-compact.png": -{ - "frame": {"x":639,"y":201,"w":47,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/splitter.png": -{ - "frame": {"x":665,"y":107,"w":87,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/stacker.png": -{ - "frame": {"x":480,"y":107,"w":89,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/trash-storage.png": -{ - "frame": {"x":291,"y":107,"w":85,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/trash.png": -{ - "frame": {"x":286,"y":303,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/underground_belt_entry-tier2.png": -{ - "frame": {"x":3,"y":440,"w":48,"h":43}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":5,"w":48,"h":43}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/underground_belt_entry.png": -{ - "frame": {"x":55,"y":440,"w":48,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":10,"w":48,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/underground_belt_exit-tier2.png": -{ - "frame": {"x":431,"y":159,"w":48,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/underground_belt_exit.png": -{ - "frame": {"x":483,"y":159,"w":48,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/wire_crossings-merger.png": -{ - "frame": {"x":107,"y":440,"w":48,"h":35}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":35}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/wire_crossings.png": -{ - "frame": {"x":740,"y":159,"w":48,"h":34}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":48,"h":34}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/wire_left.png": -{ - "frame": {"x":808,"y":107,"w":21,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":11,"w":21,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/blueprints/wire_right.png": -{ - "frame": {"x":808,"y":132,"w":21,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":11,"w":21,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/blueprints/wire_top.png": -{ - "frame": {"x":816,"y":3,"w":10,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":10,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/buildings/advanced_processor.png": -{ - "frame": {"x":192,"y":207,"w":94,"h":91}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":94,"h":91}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":397,"y":437,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":431,"y":437,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/buildings/belt_top.png": -{ - "frame": {"x":195,"y":433,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/buildings/cutter-quad.png": -{ - "frame": {"x":383,"y":3,"w":184,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, - "sourceSize": {"w":192,"h":48} -}, -"sprites/buildings/cutter.png": -{ - "frame": {"x":195,"y":302,"w":87,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/energy_generator.png": -{ - "frame": {"x":290,"y":207,"w":89,"h":92}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":89,"h":92}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/hub.png": -{ - "frame": {"x":3,"y":3,"w":184,"h":185}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":184,"h":185}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/miner-chainable.png": -{ - "frame": {"x":485,"y":201,"w":47,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/miner.png": -{ - "frame": {"x":536,"y":201,"w":47,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/mixer.png": -{ - "frame": {"x":583,"y":55,"w":88,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/painter-double.png": -{ - "frame": {"x":3,"y":244,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/painter-mirrored.png": -{ - "frame": {"x":380,"y":107,"w":96,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/painter-quad.png": -{ - "frame": {"x":191,"y":55,"w":188,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, - "sourceSize": {"w":192,"h":48} -}, -"sprites/buildings/painter.png": -{ - "frame": {"x":483,"y":55,"w":96,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/rotater-ccw.png": -{ - "frame": {"x":286,"y":355,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/rotater.png": -{ - "frame": {"x":338,"y":303,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/splitter-compact-inverse.png": -{ - "frame": {"x":587,"y":201,"w":48,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":47}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/splitter-compact.png": -{ - "frame": {"x":690,"y":198,"w":47,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/splitter.png": -{ - "frame": {"x":195,"y":354,"w":87,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/stacker.png": -{ - "frame": {"x":573,"y":107,"w":88,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/trash-storage.png": -{ - "frame": {"x":103,"y":244,"w":85,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/trash.png": -{ - "frame": {"x":338,"y":355,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/underground_belt_entry-tier2.png": -{ - "frame": {"x":380,"y":159,"w":47,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":6,"w":47,"h":42}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/underground_belt_entry.png": -{ - "frame": {"x":535,"y":159,"w":47,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":10,"w":47,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/underground_belt_exit-tier2.png": -{ - "frame": {"x":586,"y":159,"w":47,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/underground_belt_exit.png": -{ - "frame": {"x":637,"y":159,"w":47,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/wire_crossings-merger.png": -{ - "frame": {"x":688,"y":159,"w":48,"h":35}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":35}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/wire_crossings.png": -{ - "frame": {"x":383,"y":257,"w":48,"h":34}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":14,"w":48,"h":34}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/wire_left.png": -{ - "frame": {"x":270,"y":407,"w":21,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":11,"w":21,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/buildings/wire_right.png": -{ - "frame": {"x":805,"y":457,"w":21,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":11,"w":21,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/buildings/wire_top.png": -{ - "frame": {"x":422,"y":295,"w":10,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":10,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/debug/acceptor_slot.png": -{ - "frame": {"x":259,"y":468,"w":14,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/debug/ejector_slot.png": -{ - "frame": {"x":485,"y":461,"w":14,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/map_overview/belt_forward.png": -{ - "frame": {"x":277,"y":468,"w":8,"h":8}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, - "sourceSize": {"w":8,"h":8} -}, -"sprites/map_overview/belt_left.png": -{ - "frame": {"x":791,"y":471,"w":8,"h":8}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, - "sourceSize": {"w":8,"h":8} -}, -"sprites/map_overview/belt_right.png": -{ - "frame": {"x":175,"y":476,"w":8,"h":8}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, - "sourceSize": {"w":8,"h":8} -}, -"sprites/misc/deletion_marker.png": -{ - "frame": {"x":244,"y":406,"w":22,"h":22}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":22,"h":22}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/energy_generator_overlay.png": -{ - "frame": {"x":195,"y":469,"w":40,"h":17}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":45,"y":71,"w":40,"h":17}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/misc/hub_direction_indicator.png": -{ - "frame": {"x":818,"y":55,"w":8,"h":8}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, - "sourceSize": {"w":8,"h":8} -}, -"sprites/misc/lock_direction_indicator.png": -{ - "frame": {"x":159,"y":476,"w":12,"h":10}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":12,"h":10}, - "sourceSize": {"w":12,"h":12} -}, -"sprites/misc/slot_bad_arrow.png": -{ - "frame": {"x":244,"y":406,"w":22,"h":22}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":22,"h":22}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/slot_good_arrow.png": -{ - "frame": {"x":805,"y":429,"w":22,"h":24}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":22,"h":24}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/storage_overlay.png": -{ - "frame": {"x":195,"y":406,"w":45,"h":23}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":45,"h":23}, - "sourceSize": {"w":45,"h":23} -}, -"sprites/misc/waypoint.png": -{ - "frame": {"x":535,"y":461,"w":8,"h":8}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, - "sourceSize": {"w":8,"h":8} -}, -"sprites/misc/wires_overlay_tile.png": -{ - "frame": {"x":159,"y":440,"w":32,"h":32}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/battery_empty.png": -{ - "frame": {"x":503,"y":461,"w":12,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":12,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/battery_full.png": -{ - "frame": {"x":741,"y":233,"w":16,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":16,"h":12}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/battery_low.png": -{ - "frame": {"x":771,"y":471,"w":16,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":16,"h":12}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/battery_medium.png": -{ - "frame": {"x":465,"y":461,"w":16,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":16,"h":12}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/negative_energy.png": -{ - "frame": {"x":816,"y":39,"w":12,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":12,"h":12}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/pin_negative_accept.png": -{ - "frame": {"x":805,"y":195,"w":20,"h":27}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":20,"h":27}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/pin_negative_eject.png": -{ - "frame": {"x":805,"y":369,"w":18,"h":26}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":18,"h":26}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/pin_positive_accept.png": -{ - "frame": {"x":805,"y":399,"w":18,"h":26}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":18,"h":26}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/pin_positive_eject.png": -{ - "frame": {"x":726,"y":319,"w":20,"h":27}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":20,"h":27}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/positive_energy.png": -{ - "frame": {"x":519,"y":461,"w":12,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":12,"h":12}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/waste_piled.png": -{ - "frame": {"x":239,"y":469,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}}, -"meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "atlas0_25.png", - "format": "RGBA8888", - "size": {"w":832,"h":489}, - "scale": "0.25", - "smartupdate": "$TexturePacker:SmartUpdate:4e5fb3bd7f1e5423e4fcea2215debe11:0c5d091d0b928944c68553dcc592c801:f159918d23e5952766c6d23ab52278c6$" -} -} diff --git a/res_built/atlas/atlas0_25.png b/res_built/atlas/atlas0_25.png deleted file mode 100644 index f4b2409b..00000000 Binary files a/res_built/atlas/atlas0_25.png and /dev/null differ diff --git a/res_built/atlas/atlas0_50.json b/res_built/atlas/atlas0_50.json deleted file mode 100644 index 4e89c4a1..00000000 --- a/res_built/atlas/atlas0_50.json +++ /dev/null @@ -1,1388 +0,0 @@ -{"frames": { - -"sprites/belt/forward_0.png": -{ - "frame": {"x":962,"y":484,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_1.png": -{ - "frame": {"x":740,"y":481,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_2.png": -{ - "frame": {"x":881,"y":735,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_3.png": -{ - "frame": {"x":991,"y":868,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_4.png": -{ - "frame": {"x":1046,"y":868,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_5.png": -{ - "frame": {"x":1017,"y":535,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_6.png": -{ - "frame": {"x":1015,"y":602,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_7.png": -{ - "frame": {"x":1047,"y":669,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_8.png": -{ - "frame": {"x":1102,"y":664,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_9.png": -{ - "frame": {"x":1157,"y":664,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_10.png": -{ - "frame": {"x":765,"y":591,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_11.png": -{ - "frame": {"x":766,"y":658,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_12.png": -{ - "frame": {"x":766,"y":725,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_13.png": -{ - "frame": {"x":763,"y":853,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_14.png": -{ - "frame": {"x":821,"y":638,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_15.png": -{ - "frame": {"x":821,"y":705,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_16.png": -{ - "frame": {"x":876,"y":668,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_17.png": -{ - "frame": {"x":826,"y":772,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_18.png": -{ - "frame": {"x":992,"y":673,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_19.png": -{ - "frame": {"x":763,"y":920,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_20.png": -{ - "frame": {"x":936,"y":734,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_21.png": -{ - "frame": {"x":881,"y":802,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_22.png": -{ - "frame": {"x":936,"y":801,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_23.png": -{ - "frame": {"x":991,"y":801,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_24.png": -{ - "frame": {"x":826,"y":839,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_25.png": -{ - "frame": {"x":818,"y":906,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_26.png": -{ - "frame": {"x":881,"y":869,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_27.png": -{ - "frame": {"x":936,"y":868,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_0.png": -{ - "frame": {"x":1074,"y":481,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_1.png": -{ - "frame": {"x":1135,"y":481,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_2.png": -{ - "frame": {"x":931,"y":673,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_3.png": -{ - "frame": {"x":1131,"y":603,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_4.png": -{ - "frame": {"x":1192,"y":603,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_5.png": -{ - "frame": {"x":1253,"y":603,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_6.png": -{ - "frame": {"x":1314,"y":603,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_7.png": -{ - "frame": {"x":1212,"y":664,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_8.png": -{ - "frame": {"x":1273,"y":664,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_9.png": -{ - "frame": {"x":1052,"y":736,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_10.png": -{ - "frame": {"x":1196,"y":481,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_11.png": -{ - "frame": {"x":1257,"y":481,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_12.png": -{ - "frame": {"x":1318,"y":481,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_13.png": -{ - "frame": {"x":832,"y":516,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_14.png": -{ - "frame": {"x":893,"y":546,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_15.png": -{ - "frame": {"x":954,"y":551,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_16.png": -{ - "frame": {"x":832,"y":577,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_17.png": -{ - "frame": {"x":893,"y":607,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_18.png": -{ - "frame": {"x":954,"y":612,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_19.png": -{ - "frame": {"x":765,"y":792,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_20.png": -{ - "frame": {"x":991,"y":740,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_21.png": -{ - "frame": {"x":873,"y":936,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_22.png": -{ - "frame": {"x":1072,"y":542,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_23.png": -{ - "frame": {"x":1133,"y":542,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_24.png": -{ - "frame": {"x":1194,"y":542,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_25.png": -{ - "frame": {"x":1255,"y":542,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_26.png": -{ - "frame": {"x":1316,"y":542,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_27.png": -{ - "frame": {"x":1070,"y":603,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_0.png": -{ - "frame": {"x":1113,"y":731,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_1.png": -{ - "frame": {"x":1067,"y":797,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_2.png": -{ - "frame": {"x":1375,"y":603,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_3.png": -{ - "frame": {"x":1162,"y":914,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_4.png": -{ - "frame": {"x":1223,"y":914,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_5.png": -{ - "frame": {"x":1284,"y":908,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_6.png": -{ - "frame": {"x":1345,"y":908,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_7.png": -{ - "frame": {"x":573,"y":947,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_8.png": -{ - "frame": {"x":634,"y":947,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_9.png": -{ - "frame": {"x":695,"y":946,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_10.png": -{ - "frame": {"x":1334,"y":664,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_11.png": -{ - "frame": {"x":1128,"y":792,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_12.png": -{ - "frame": {"x":1174,"y":731,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_13.png": -{ - "frame": {"x":1235,"y":725,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_14.png": -{ - "frame": {"x":1296,"y":725,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_15.png": -{ - "frame": {"x":1189,"y":792,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_16.png": -{ - "frame": {"x":1250,"y":786,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_17.png": -{ - "frame": {"x":1311,"y":786,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_18.png": -{ - "frame": {"x":1357,"y":725,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_19.png": -{ - "frame": {"x":1372,"y":786,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_20.png": -{ - "frame": {"x":1377,"y":542,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_21.png": -{ - "frame": {"x":1379,"y":481,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_22.png": -{ - "frame": {"x":1101,"y":858,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_23.png": -{ - "frame": {"x":1162,"y":853,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_24.png": -{ - "frame": {"x":1223,"y":853,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_25.png": -{ - "frame": {"x":1284,"y":847,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_26.png": -{ - "frame": {"x":1345,"y":847,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_27.png": -{ - "frame": {"x":1101,"y":919,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/blueprints/advanced_processor.png": -{ - "frame": {"x":3,"y":669,"w":188,"h":181}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":5,"w":188,"h":181}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/belt_left.png": -{ - "frame": {"x":838,"y":454,"w":58,"h":58}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":5,"w":58,"h":58}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/blueprints/belt_right.png": -{ - "frame": {"x":900,"y":484,"w":58,"h":58}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":58,"h":58}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/blueprints/belt_top.png": -{ - "frame": {"x":1017,"y":468,"w":53,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":53,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/blueprints/cutter-quad.png": -{ - "frame": {"x":3,"y":374,"w":366,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, - "sourceSize": {"w":384,"h":96} -}, -"sprites/blueprints/cutter.png": -{ - "frame": {"x":373,"y":399,"w":172,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":172,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/energy_generator.png": -{ - "frame": {"x":195,"y":670,"w":175,"h":183}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":175,"h":183}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/miner-chainable.png": -{ - "frame": {"x":473,"y":669,"w":92,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/miner.png": -{ - "frame": {"x":477,"y":856,"w":92,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/mixer.png": -{ - "frame": {"x":3,"y":854,"w":175,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/painter-double.png": -{ - "frame": {"x":373,"y":203,"w":192,"h":192}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/painter-mirrored.png": -{ - "frame": {"x":751,"y":103,"w":192,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/painter-quad.png": -{ - "frame": {"x":373,"y":3,"w":374,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, - "sourceSize": {"w":384,"h":96} -}, -"sprites/blueprints/painter.png": -{ - "frame": {"x":1121,"y":3,"w":192,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/rotater-ccw.png": -{ - "frame": {"x":1317,"y":3,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/rotater.png": -{ - "frame": {"x":1322,"y":103,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/splitter-compact-inverse.png": -{ - "frame": {"x":569,"y":599,"w":95,"h":93}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":95,"h":93}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/splitter-compact.png": -{ - "frame": {"x":668,"y":599,"w":93,"h":93}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":1,"w":93,"h":93}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/splitter.png": -{ - "frame": {"x":549,"y":399,"w":171,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/stacker.png": -{ - "frame": {"x":1143,"y":103,"w":175,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/trash-storage.png": -{ - "frame": {"x":569,"y":203,"w":167,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":167,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/trash.png": -{ - "frame": {"x":1287,"y":203,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/underground_belt_entry-tier2.png": -{ - "frame": {"x":374,"y":769,"w":93,"h":84}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":12,"w":93,"h":84}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/underground_belt_entry.png": -{ - "frame": {"x":669,"y":696,"w":93,"h":75}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":21,"w":93,"h":75}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/underground_belt_exit-tier2.png": -{ - "frame": {"x":567,"y":769,"w":94,"h":75}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":94,"h":75}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/underground_belt_exit.png": -{ - "frame": {"x":1003,"y":389,"w":93,"h":75}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":93,"h":75}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/wire_crossings-merger.png": -{ - "frame": {"x":569,"y":696,"w":96,"h":69}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":69}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/wire_crossings.png": -{ - "frame": {"x":369,"y":599,"w":96,"h":66}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":30,"w":96,"h":66}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/wire_left.png": -{ - "frame": {"x":268,"y":957,"w":40,"h":40}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":23,"w":40,"h":40}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/blueprints/wire_right.png": -{ - "frame": {"x":224,"y":957,"w":40,"h":41}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":22,"w":40,"h":41}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/blueprints/wire_top.png": -{ - "frame": {"x":719,"y":499,"w":17,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":17,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/buildings/advanced_processor.png": -{ - "frame": {"x":740,"y":203,"w":187,"h":179}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":6,"w":187,"h":179}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":934,"y":936,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":995,"y":935,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/buildings/belt_top.png": -{ - "frame": {"x":962,"y":484,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/buildings/cutter-quad.png": -{ - "frame": {"x":751,"y":3,"w":366,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, - "sourceSize": {"w":384,"h":96} -}, -"sprites/buildings/cutter.png": -{ - "frame": {"x":369,"y":499,"w":171,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/energy_generator.png": -{ - "frame": {"x":931,"y":203,"w":174,"h":182}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":10,"y":10,"w":174,"h":182}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/hub.png": -{ - "frame": {"x":3,"y":3,"w":366,"h":367}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":10,"w":366,"h":367}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/buildings/miner-chainable.png": -{ - "frame": {"x":573,"y":848,"w":91,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/miner.png": -{ - "frame": {"x":668,"y":847,"w":91,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/mixer.png": -{ - "frame": {"x":1109,"y":203,"w":174,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/painter-double.png": -{ - "frame": {"x":3,"y":474,"w":192,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":191}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/painter-mirrored.png": -{ - "frame": {"x":947,"y":103,"w":192,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/painter-quad.png": -{ - "frame": {"x":373,"y":103,"w":374,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, - "sourceSize": {"w":384,"h":96} -}, -"sprites/buildings/painter.png": -{ - "frame": {"x":182,"y":857,"w":192,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/rotater-ccw.png": -{ - "frame": {"x":374,"y":669,"w":95,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/rotater.png": -{ - "frame": {"x":378,"y":857,"w":95,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/splitter-compact-inverse.png": -{ - "frame": {"x":740,"y":386,"w":94,"h":91}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":94,"h":91}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/splitter-compact.png": -{ - "frame": {"x":906,"y":389,"w":93,"h":91}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":2,"w":93,"h":91}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/splitter.png": -{ - "frame": {"x":544,"y":499,"w":171,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/stacker.png": -{ - "frame": {"x":1109,"y":303,"w":174,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/trash-storage.png": -{ - "frame": {"x":199,"y":474,"w":166,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":166,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/trash.png": -{ - "frame": {"x":1287,"y":303,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/underground_belt_entry-tier2.png": -{ - "frame": {"x":471,"y":769,"w":92,"h":83}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":13,"w":92,"h":83}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/underground_belt_entry.png": -{ - "frame": {"x":1100,"y":403,"w":92,"h":74}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":22,"w":92,"h":74}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/underground_belt_exit-tier2.png": -{ - "frame": {"x":1196,"y":403,"w":92,"h":74}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/underground_belt_exit.png": -{ - "frame": {"x":1292,"y":403,"w":92,"h":74}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/wire_crossings-merger.png": -{ - "frame": {"x":665,"y":775,"w":96,"h":68}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":68}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/wire_crossings.png": -{ - "frame": {"x":469,"y":599,"w":96,"h":66}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":30,"w":96,"h":66}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/wire_left.png": -{ - "frame": {"x":312,"y":957,"w":40,"h":40}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":23,"w":40,"h":40}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/buildings/wire_right.png": -{ - "frame": {"x":356,"y":957,"w":40,"h":40}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":23,"w":40,"h":40}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/buildings/wire_top.png": -{ - "frame": {"x":1046,"y":801,"w":17,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":17,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/debug/acceptor_slot.png": -{ - "frame": {"x":1395,"y":664,"w":26,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":26,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/debug/ejector_slot.png": -{ - "frame": {"x":400,"y":957,"w":26,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":26,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/map_overview/belt_forward.png": -{ - "frame": {"x":1417,"y":39,"w":14,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/map_overview/belt_left.png": -{ - "frame": {"x":1082,"y":935,"w":15,"h":15}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":15,"h":15}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/map_overview/belt_right.png": -{ - "frame": {"x":1082,"y":954,"w":15,"h":15}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":15,"h":15}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/misc/deletion_marker.png": -{ - "frame": {"x":178,"y":957,"w":42,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":3,"w":42,"h":42}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/misc/energy_generator_overlay.png": -{ - "frame": {"x":96,"y":954,"w":78,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":91,"y":144,"w":78,"h":30}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/misc/hub_direction_indicator.png": -{ - "frame": {"x":1421,"y":369,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/misc/lock_direction_indicator.png": -{ - "frame": {"x":1406,"y":873,"w":24,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":24,"h":16}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/slot_bad_arrow.png": -{ - "frame": {"x":178,"y":957,"w":42,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":3,"w":42,"h":42}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/misc/slot_good_arrow.png": -{ - "frame": {"x":1387,"y":317,"w":42,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":42,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/misc/storage_overlay.png": -{ - "frame": {"x":3,"y":954,"w":89,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":89,"h":44}, - "sourceSize": {"w":90,"h":45} -}, -"sprites/misc/waypoint.png": -{ - "frame": {"x":1406,"y":893,"w":14,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/misc/wires_overlay_tile.png": -{ - "frame": {"x":838,"y":386,"w":64,"h":64}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/battery_empty.png": -{ - "frame": {"x":1417,"y":3,"w":20,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":20,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/battery_full.png": -{ - "frame": {"x":1395,"y":700,"w":30,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":6,"w":30,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/battery_low.png": -{ - "frame": {"x":1387,"y":369,"w":30,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":6,"w":30,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/battery_medium.png": -{ - "frame": {"x":430,"y":957,"w":30,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":6,"w":30,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/negative_energy.png": -{ - "frame": {"x":1406,"y":847,"w":22,"h":22}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":22,"h":22}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/pin_negative_accept.png": -{ - "frame": {"x":1387,"y":203,"w":38,"h":53}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":38,"h":53}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/pin_negative_eject.png": -{ - "frame": {"x":795,"y":481,"w":33,"h":51}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":15,"y":0,"w":33,"h":51}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/pin_positive_accept.png": -{ - "frame": {"x":795,"y":536,"w":33,"h":51}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":15,"y":0,"w":33,"h":51}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/pin_positive_eject.png": -{ - "frame": {"x":1387,"y":260,"w":38,"h":53}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":38,"h":53}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/positive_energy.png": -{ - "frame": {"x":1056,"y":935,"w":22,"h":22}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":22,"h":22}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/waste_piled.png": -{ - "frame": {"x":719,"y":566,"w":30,"h":29}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":30,"h":29}, - "sourceSize": {"w":32,"h":32} -}}, -"meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "atlas0_50.png", - "format": "RGBA8888", - "size": {"w":1440,"h":1007}, - "scale": "0.5", - "smartupdate": "$TexturePacker:SmartUpdate:4e5fb3bd7f1e5423e4fcea2215debe11:0c5d091d0b928944c68553dcc592c801:f159918d23e5952766c6d23ab52278c6$" -} -} diff --git a/res_built/atlas/atlas0_50.png b/res_built/atlas/atlas0_50.png deleted file mode 100644 index dac64c2a..00000000 Binary files a/res_built/atlas/atlas0_50.png and /dev/null differ diff --git a/res_built/atlas/atlas0_75.json b/res_built/atlas/atlas0_75.json deleted file mode 100644 index b9dac39c..00000000 --- a/res_built/atlas/atlas0_75.json +++ /dev/null @@ -1,1388 +0,0 @@ -{"frames": { - -"sprites/belt/forward_0.png": -{ - "frame": {"x":1907,"y":299,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_1.png": -{ - "frame": {"x":1024,"y":887,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_2.png": -{ - "frame": {"x":1287,"y":1076,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_3.png": -{ - "frame": {"x":1374,"y":1167,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_4.png": -{ - "frame": {"x":1392,"y":1266,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_5.png": -{ - "frame": {"x":1423,"y":1455,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_6.png": -{ - "frame": {"x":1449,"y":1032,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_7.png": -{ - "frame": {"x":1455,"y":1131,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_8.png": -{ - "frame": {"x":1473,"y":1230,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_9.png": -{ - "frame": {"x":1484,"y":1329,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_10.png": -{ - "frame": {"x":1105,"y":880,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_11.png": -{ - "frame": {"x":1122,"y":979,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_12.png": -{ - "frame": {"x":1125,"y":1078,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_13.png": -{ - "frame": {"x":1215,"y":878,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_14.png": -{ - "frame": {"x":1131,"y":1177,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_15.png": -{ - "frame": {"x":1203,"y":979,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_16.png": -{ - "frame": {"x":1206,"y":1078,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_17.png": -{ - "frame": {"x":1212,"y":1177,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_18.png": -{ - "frame": {"x":1932,"y":594,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_19.png": -{ - "frame": {"x":1284,"y":977,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_20.png": -{ - "frame": {"x":1293,"y":1175,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_21.png": -{ - "frame": {"x":1311,"y":1274,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_22.png": -{ - "frame": {"x":1099,"y":1463,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_23.png": -{ - "frame": {"x":1180,"y":1463,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_24.png": -{ - "frame": {"x":1261,"y":1463,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_25.png": -{ - "frame": {"x":1342,"y":1463,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_26.png": -{ - "frame": {"x":1942,"y":398,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_27.png": -{ - "frame": {"x":1368,"y":1068,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_0.png": -{ - "frame": {"x":786,"y":887,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_1.png": -{ - "frame": {"x":1107,"y":691,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_2.png": -{ - "frame": {"x":1124,"y":1366,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_3.png": -{ - "frame": {"x":1893,"y":824,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_4.png": -{ - "frame": {"x":1803,"y":914,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_5.png": -{ - "frame": {"x":1893,"y":914,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_6.png": -{ - "frame": {"x":1365,"y":824,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_7.png": -{ - "frame": {"x":1365,"y":914,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_8.png": -{ - "frame": {"x":1394,"y":1365,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_9.png": -{ - "frame": {"x":1519,"y":912,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_10.png": -{ - "frame": {"x":1197,"y":698,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_11.png": -{ - "frame": {"x":1189,"y":788,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_12.png": -{ - "frame": {"x":1353,"y":734,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_13.png": -{ - "frame": {"x":1443,"y":734,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_14.png": -{ - "frame": {"x":1533,"y":732,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_15.png": -{ - "frame": {"x":1623,"y":736,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_16.png": -{ - "frame": {"x":1713,"y":736,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_17.png": -{ - "frame": {"x":1803,"y":734,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_18.png": -{ - "frame": {"x":1893,"y":734,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_19.png": -{ - "frame": {"x":1131,"y":1276,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_20.png": -{ - "frame": {"x":1221,"y":1276,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_21.png": -{ - "frame": {"x":1214,"y":1366,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_22.png": -{ - "frame": {"x":1304,"y":1373,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_23.png": -{ - "frame": {"x":1942,"y":497,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_24.png": -{ - "frame": {"x":1533,"y":822,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_25.png": -{ - "frame": {"x":1623,"y":826,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_26.png": -{ - "frame": {"x":1713,"y":826,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_27.png": -{ - "frame": {"x":1803,"y":824,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_0.png": -{ - "frame": {"x":1609,"y":916,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_1.png": -{ - "frame": {"x":1699,"y":916,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_2.png": -{ - "frame": {"x":1655,"y":1276,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_3.png": -{ - "frame": {"x":1824,"y":1184,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_4.png": -{ - "frame": {"x":1896,"y":1094,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_5.png": -{ - "frame": {"x":1835,"y":1274,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_6.png": -{ - "frame": {"x":1774,"y":1364,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_7.png": -{ - "frame": {"x":1774,"y":1454,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_8.png": -{ - "frame": {"x":1914,"y":1184,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_9.png": -{ - "frame": {"x":1925,"y":1274,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_10.png": -{ - "frame": {"x":1504,"y":1428,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_11.png": -{ - "frame": {"x":1789,"y":1004,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_12.png": -{ - "frame": {"x":1879,"y":1004,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_13.png": -{ - "frame": {"x":1530,"y":1006,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_14.png": -{ - "frame": {"x":1620,"y":1006,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_15.png": -{ - "frame": {"x":1536,"y":1096,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_16.png": -{ - "frame": {"x":1626,"y":1096,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_17.png": -{ - "frame": {"x":1554,"y":1186,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_18.png": -{ - "frame": {"x":1644,"y":1186,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_19.png": -{ - "frame": {"x":1565,"y":1276,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_20.png": -{ - "frame": {"x":1594,"y":1366,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_21.png": -{ - "frame": {"x":1594,"y":1456,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_22.png": -{ - "frame": {"x":1684,"y":1366,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_23.png": -{ - "frame": {"x":1684,"y":1456,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_24.png": -{ - "frame": {"x":1716,"y":1094,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_25.png": -{ - "frame": {"x":1806,"y":1094,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_26.png": -{ - "frame": {"x":1734,"y":1184,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_27.png": -{ - "frame": {"x":1745,"y":1274,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/blueprints/advanced_processor.png": -{ - "frame": {"x":3,"y":994,"w":281,"h":270}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":8,"w":281,"h":270}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/blueprints/belt_left.png": -{ - "frame": {"x":695,"y":886,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":8,"w":87,"h":87}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/blueprints/belt_right.png": -{ - "frame": {"x":695,"y":1456,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":8,"w":87,"h":87}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/blueprints/belt_top.png": -{ - "frame": {"x":1077,"y":781,"w":79,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":79,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/blueprints/cutter-quad.png": -{ - "frame": {"x":3,"y":556,"w":548,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":548,"h":144}, - "sourceSize": {"w":576,"h":144} -}, -"sprites/blueprints/cutter.png": -{ - "frame": {"x":1411,"y":150,"w":256,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/energy_generator.png": -{ - "frame": {"x":288,"y":996,"w":262,"h":274}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":262,"h":274}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/blueprints/miner-chainable.png": -{ - "frame": {"x":701,"y":977,"w":136,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/miner.png": -{ - "frame": {"x":701,"y":1124,"w":136,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/mixer.png": -{ - "frame": {"x":547,"y":738,"w":261,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/painter-double.png": -{ - "frame": {"x":555,"y":299,"w":288,"h":287}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":287}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/blueprints/painter-mirrored.png": -{ - "frame": {"x":1119,"y":150,"w":288,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/painter-quad.png": -{ - "frame": {"x":555,"y":3,"w":560,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, - "sourceSize": {"w":576,"h":144} -}, -"sprites/blueprints/painter.png": -{ - "frame": {"x":1671,"y":3,"w":288,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/rotater-ccw.png": -{ - "frame": {"x":554,"y":993,"w":143,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/rotater.png": -{ - "frame": {"x":554,"y":1141,"w":143,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/splitter-compact-inverse.png": -{ - "frame": {"x":1355,"y":592,"w":142,"h":138}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":142,"h":138}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/splitter-compact.png": -{ - "frame": {"x":1646,"y":594,"w":139,"h":138}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":2,"w":139,"h":138}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/splitter.png": -{ - "frame": {"x":847,"y":591,"w":256,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/stacker.png": -{ - "frame": {"x":812,"y":739,"w":261,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/trash-storage.png": -{ - "frame": {"x":847,"y":299,"w":250,"h":288}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":21,"y":0,"w":250,"h":288}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/blueprints/trash.png": -{ - "frame": {"x":1646,"y":446,"w":144,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/underground_belt_entry-tier2.png": -{ - "frame": {"x":841,"y":1136,"w":138,"h":125}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":19,"w":138,"h":125}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/underground_belt_entry.png": -{ - "frame": {"x":983,"y":1118,"w":138,"h":112}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":32,"w":138,"h":112}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/underground_belt_exit-tier2.png": -{ - "frame": {"x":552,"y":1436,"w":139,"h":112}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":139,"h":112}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/underground_belt_exit.png": -{ - "frame": {"x":841,"y":1265,"w":138,"h":112}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":138,"h":112}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/wire_crossings-merger.png": -{ - "frame": {"x":547,"y":886,"w":144,"h":103}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":103}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/wire_crossings.png": -{ - "frame": {"x":876,"y":887,"w":144,"h":99}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":45,"w":144,"h":99}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/wire_left.png": -{ - "frame": {"x":1365,"y":1004,"w":60,"h":60}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":35,"w":60,"h":60}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/blueprints/wire_right.png": -{ - "frame": {"x":852,"y":1496,"w":60,"h":61}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":35,"y":34,"w":60,"h":61}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/blueprints/wire_top.png": -{ - "frame": {"x":1160,"y":781,"w":25,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":35,"y":0,"w":25,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/buildings/advanced_processor.png": -{ - "frame": {"x":3,"y":1268,"w":280,"h":268}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":9,"w":280,"h":268}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":1864,"y":1364,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":1864,"y":1454,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/buildings/belt_top.png": -{ - "frame": {"x":1907,"y":299,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/buildings/cutter-quad.png": -{ - "frame": {"x":1119,"y":3,"w":548,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":548,"h":143}, - "sourceSize": {"w":576,"h":144} -}, -"sprites/buildings/cutter.png": -{ - "frame": {"x":1647,"y":299,"w":256,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/energy_generator.png": -{ - "frame": {"x":287,"y":1274,"w":261,"h":273}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":15,"y":15,"w":261,"h":273}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/buildings/hub.png": -{ - "frame": {"x":3,"y":3,"w":548,"h":549}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":16,"w":548,"h":549}, - "sourceSize": {"w":576,"h":576} -}, -"sprites/buildings/miner-chainable.png": -{ - "frame": {"x":1101,"y":445,"w":136,"h":142}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/miner.png": -{ - "frame": {"x":841,"y":990,"w":136,"h":142}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/mixer.png": -{ - "frame": {"x":1119,"y":298,"w":260,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/painter-double.png": -{ - "frame": {"x":3,"y":704,"w":288,"h":286}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":286}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/buildings/painter-mirrored.png": -{ - "frame": {"x":1671,"y":151,"w":288,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/painter-quad.png": -{ - "frame": {"x":555,"y":151,"w":560,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, - "sourceSize": {"w":576,"h":144} -}, -"sprites/buildings/painter.png": -{ - "frame": {"x":555,"y":590,"w":288,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/rotater-ccw.png": -{ - "frame": {"x":1501,"y":445,"w":141,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/rotater.png": -{ - "frame": {"x":552,"y":1289,"w":141,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/splitter-compact-inverse.png": -{ - "frame": {"x":1501,"y":592,"w":141,"h":136}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":3,"w":141,"h":136}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/splitter-compact.png": -{ - "frame": {"x":1789,"y":594,"w":139,"h":136}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":3,"w":139,"h":136}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/splitter.png": -{ - "frame": {"x":1241,"y":445,"w":256,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/stacker.png": -{ - "frame": {"x":1383,"y":298,"w":260,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/trash-storage.png": -{ - "frame": {"x":295,"y":704,"w":248,"h":288}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":22,"y":0,"w":248,"h":288}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/buildings/trash.png": -{ - "frame": {"x":1794,"y":446,"w":144,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/underground_belt_entry-tier2.png": -{ - "frame": {"x":981,"y":990,"w":137,"h":124}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":20,"w":137,"h":124}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/underground_belt_entry.png": -{ - "frame": {"x":983,"y":1336,"w":137,"h":111}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":33,"w":137,"h":111}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/underground_belt_exit-tier2.png": -{ - "frame": {"x":697,"y":1341,"w":137,"h":111}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/underground_belt_exit.png": -{ - "frame": {"x":838,"y":1381,"w":137,"h":111}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/wire_crossings-merger.png": -{ - "frame": {"x":1207,"y":592,"w":144,"h":102}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":102}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/wire_crossings.png": -{ - "frame": {"x":983,"y":1234,"w":144,"h":98}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":46,"w":144,"h":98}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/wire_left.png": -{ - "frame": {"x":1455,"y":904,"w":60,"h":60}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":35,"w":60,"h":60}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/buildings/wire_right.png": -{ - "frame": {"x":1455,"y":968,"w":60,"h":60}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":35,"y":35,"w":60,"h":60}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/buildings/wire_top.png": -{ - "frame": {"x":1186,"y":880,"w":25,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":35,"y":0,"w":25,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/debug/acceptor_slot.png": -{ - "frame": {"x":1710,"y":1006,"w":38,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":38,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/debug/ejector_slot.png": -{ - "frame": {"x":1954,"y":1364,"w":38,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":38,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/map_overview/belt_forward.png": -{ - "frame": {"x":1907,"y":398,"w":20,"h":24}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":20,"h":24}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/map_overview/belt_left.png": -{ - "frame": {"x":1429,"y":1004,"w":22,"h":22}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":22,"h":22}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/map_overview/belt_right.png": -{ - "frame": {"x":1980,"y":693,"w":22,"h":22}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":22,"h":22}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/deletion_marker.png": -{ - "frame": {"x":786,"y":1496,"w":62,"h":62}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":62,"h":62}, - "sourceSize": {"w":72,"h":72} -}, -"sprites/misc/energy_generator_overlay.png": -{ - "frame": {"x":979,"y":1451,"w":116,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":137,"y":217,"w":116,"h":44}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/misc/hub_direction_indicator.png": -{ - "frame": {"x":1077,"y":739,"w":24,"h":24}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":24,"h":24}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/lock_direction_indicator.png": -{ - "frame": {"x":1552,"y":1518,"w":36,"h":24}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":36,"h":24}, - "sourceSize": {"w":36,"h":36} -}, -"sprites/misc/slot_bad_arrow.png": -{ - "frame": {"x":786,"y":1496,"w":62,"h":62}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":62,"h":62}, - "sourceSize": {"w":72,"h":72} -}, -"sprites/misc/slot_good_arrow.png": -{ - "frame": {"x":1287,"y":698,"w":62,"h":72}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":62,"h":72}, - "sourceSize": {"w":72,"h":72} -}, -"sprites/misc/storage_overlay.png": -{ - "frame": {"x":701,"y":1271,"w":133,"h":66}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":133,"h":66}, - "sourceSize": {"w":135,"h":68} -}, -"sprites/misc/waypoint.png": -{ - "frame": {"x":1508,"y":824,"w":20,"h":24}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":20,"h":24}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/wires_overlay_tile.png": -{ - "frame": {"x":1107,"y":591,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/battery_empty.png": -{ - "frame": {"x":1963,"y":249,"w":29,"h":46}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":1,"w":29,"h":46}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/battery_full.png": -{ - "frame": {"x":786,"y":1456,"w":44,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":10,"w":44,"h":30}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/battery_low.png": -{ - "frame": {"x":1932,"y":693,"w":44,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":10,"w":44,"h":30}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/battery_medium.png": -{ - "frame": {"x":1504,"y":1518,"w":44,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":10,"w":44,"h":30}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/negative_energy.png": -{ - "frame": {"x":1710,"y":1058,"w":32,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":8,"w":32,"h":32}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/pin_negative_accept.png": -{ - "frame": {"x":1963,"y":3,"w":56,"h":79}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":0,"w":56,"h":79}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/pin_negative_eject.png": -{ - "frame": {"x":1963,"y":169,"w":49,"h":76}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":49,"h":76}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/pin_positive_accept.png": -{ - "frame": {"x":1455,"y":824,"w":49,"h":76}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":49,"h":76}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/pin_positive_eject.png": -{ - "frame": {"x":1963,"y":86,"w":56,"h":79}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":0,"w":56,"h":79}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/positive_energy.png": -{ - "frame": {"x":1746,"y":1058,"w":32,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":8,"w":32,"h":32}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/waste_piled.png": -{ - "frame": {"x":916,"y":1496,"w":44,"h":43}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":44,"h":43}, - "sourceSize": {"w":48,"h":48} -}}, -"meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "atlas0_75.png", - "format": "RGBA8888", - "size": {"w":2031,"h":1561}, - "scale": "0.75", - "smartupdate": "$TexturePacker:SmartUpdate:4e5fb3bd7f1e5423e4fcea2215debe11:0c5d091d0b928944c68553dcc592c801:f159918d23e5952766c6d23ab52278c6$" -} -} diff --git a/res_built/atlas/atlas0_75.png b/res_built/atlas/atlas0_75.png deleted file mode 100644 index 0916f7aa..00000000 Binary files a/res_built/atlas/atlas0_75.png and /dev/null differ diff --git a/res_built/atlas/atlas0_hq.json b/res_built/atlas/atlas0_hq.json new file mode 100644 index 00000000..9edcc70f --- /dev/null +++ b/res_built/atlas/atlas0_hq.json @@ -0,0 +1,1476 @@ +{"frames": { + +"sprites/belt/built/forward_0.png": +{ + "frame": {"x":440,"y":742,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_1.png": +{ + "frame": {"x":1815,"y":1070,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_2.png": +{ + "frame": {"x":1804,"y":1366,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_3.png": +{ + "frame": {"x":1924,"y":1405,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_4.png": +{ + "frame": {"x":439,"y":1038,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_5.png": +{ + "frame": {"x":1801,"y":1514,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_6.png": +{ + "frame": {"x":1921,"y":1553,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_7.png": +{ + "frame": {"x":1801,"y":1662,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_8.png": +{ + "frame": {"x":1921,"y":1701,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_9.png": +{ + "frame": {"x":137,"y":1849,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_10.png": +{ + "frame": {"x":1539,"y":1139,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_11.png": +{ + "frame": {"x":1538,"y":1287,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_12.png": +{ + "frame": {"x":1806,"y":1218,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_13.png": +{ + "frame": {"x":1926,"y":1257,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_0.png": +{ + "frame": {"x":3,"y":1182,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_1.png": +{ + "frame": {"x":137,"y":1182,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_2.png": +{ + "frame": {"x":283,"y":1703,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_3.png": +{ + "frame": {"x":389,"y":1849,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_4.png": +{ + "frame": {"x":417,"y":1703,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_5.png": +{ + "frame": {"x":523,"y":1849,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_6.png": +{ + "frame": {"x":551,"y":1703,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_7.png": +{ + "frame": {"x":657,"y":1849,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_8.png": +{ + "frame": {"x":791,"y":1408,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_9.png": +{ + "frame": {"x":685,"y":1703,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_10.png": +{ + "frame": {"x":425,"y":1186,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_11.png": +{ + "frame": {"x":425,"y":1320,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_12.png": +{ + "frame": {"x":424,"y":1454,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_13.png": +{ + "frame": {"x":144,"y":1465,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_0.png": +{ + "frame": {"x":925,"y":1476,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_1.png": +{ + "frame": {"x":565,"y":1542,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_2.png": +{ + "frame": {"x":1461,"y":1703,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_3.png": +{ + "frame": {"x":791,"y":1849,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_4.png": +{ + "frame": {"x":925,"y":1610,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_5.png": +{ + "frame": {"x":1059,"y":1740,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_6.png": +{ + "frame": {"x":1193,"y":1805,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_7.png": +{ + "frame": {"x":1327,"y":1827,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_8.png": +{ + "frame": {"x":925,"y":1744,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_9.png": +{ + "frame": {"x":1059,"y":1874,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_10.png": +{ + "frame": {"x":699,"y":1542,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_11.png": +{ + "frame": {"x":1059,"y":1606,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_12.png": +{ + "frame": {"x":1193,"y":1671,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_13.png": +{ + "frame": {"x":1327,"y":1693,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/belt_left.png": +{ + "frame": {"x":925,"y":1878,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/belt_right.png": +{ + "frame": {"x":1461,"y":1849,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/belt_top.png": +{ + "frame": {"x":3,"y":1318,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/constant_signal.png": +{ + "frame": {"x":1938,"y":847,"w":105,"h":127}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":105,"h":127}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/cutter-quad.png": +{ + "frame": {"x":3,"y":151,"w":548,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":548,"h":144}, + "sourceSize": {"w":576,"h":144} +}, +"sprites/blueprints/cutter.png": +{ + "frame": {"x":847,"y":298,"w":256,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/display.png": +{ + "frame": {"x":257,"y":1849,"w":128,"h":136}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":8,"y":8,"w":128,"h":136}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/filter.png": +{ + "frame": {"x":1107,"y":556,"w":268,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":16,"y":0,"w":268,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/lever.png": +{ + "frame": {"x":1823,"y":732,"w":111,"h":129}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":4,"w":111,"h":129}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate-not.png": +{ + "frame": {"x":1545,"y":843,"w":123,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":123,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate-or.png": +{ + "frame": {"x":1249,"y":996,"w":144,"h":123}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":123}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate-transistor.png": +{ + "frame": {"x":708,"y":888,"w":101,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":101,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate-xor.png": +{ + "frame": {"x":291,"y":890,"w":144,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate.png": +{ + "frame": {"x":1397,"y":852,"w":144,"h":133}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":133}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/miner-chainable.png": +{ + "frame": {"x":151,"y":1035,"w":136,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/miner.png": +{ + "frame": {"x":123,"y":1318,"w":136,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/mixer.png": +{ + "frame": {"x":1676,"y":584,"w":261,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/painter-double.png": +{ + "frame": {"x":1683,"y":3,"w":288,"h":287}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":287}, + "sourceSize": {"w":288,"h":288} +}, +"sprites/blueprints/painter-mirrored.png": +{ + "frame": {"x":555,"y":298,"w":288,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/painter-quad.png": +{ + "frame": {"x":3,"y":3,"w":560,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, + "sourceSize": {"w":576,"h":144} +}, +"sprites/blueprints/painter.png": +{ + "frame": {"x":3,"y":299,"w":288,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/reader.png": +{ + "frame": {"x":938,"y":1181,"w":141,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":141,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/rotater-ccw.png": +{ + "frame": {"x":1245,"y":1123,"w":143,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/rotater-fl.png": +{ + "frame": {"x":1658,"y":1325,"w":142,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":142,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/rotater.png": +{ + "frame": {"x":1097,"y":1171,"w":143,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/splitter-compact-inverse.png": +{ + "frame": {"x":560,"y":1036,"w":142,"h":138}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":142,"h":138}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/splitter-compact-merge-inverse.png": +{ + "frame": {"x":792,"y":1118,"w":142,"h":138}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":142,"h":138}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/splitter-compact-merge.png": +{ + "frame": {"x":1373,"y":1409,"w":139,"h":138}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":2,"w":139,"h":138}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/splitter-compact.png": +{ + "frame": {"x":1373,"y":1551,"w":139,"h":138}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":2,"w":139,"h":138}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/splitter.png": +{ + "frame": {"x":295,"y":299,"w":256,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/stacker.png": +{ + "frame": {"x":295,"y":594,"w":261,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/trash-storage.png": +{ + "frame": {"x":847,"y":593,"w":250,"h":288}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":21,"y":0,"w":250,"h":288}, + "sourceSize": {"w":288,"h":288} +}, +"sprites/blueprints/trash.png": +{ + "frame": {"x":292,"y":742,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/underground_belt_entry-tier2.png": +{ + "frame": {"x":1516,"y":1574,"w":138,"h":125}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":19,"w":138,"h":125}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/underground_belt_entry.png": +{ + "frame": {"x":283,"y":1182,"w":138,"h":112}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":32,"w":138,"h":112}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/underground_belt_exit-tier2.png": +{ + "frame": {"x":1225,"y":1555,"w":139,"h":112}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":139,"h":112}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/underground_belt_exit.png": +{ + "frame": {"x":283,"y":1298,"w":138,"h":112}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":138,"h":112}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/virtual_processor-analyzer.png": +{ + "frame": {"x":3,"y":887,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/virtual_processor-rotater.png": +{ + "frame": {"x":1545,"y":991,"w":118,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":118,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/virtual_processor-shapecompare.png": +{ + "frame": {"x":1397,"y":989,"w":144,"h":133}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":133}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/virtual_processor-stacker.png": +{ + "frame": {"x":961,"y":1033,"w":132,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":132,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/virtual_processor-unstacker.png": +{ + "frame": {"x":1101,"y":704,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/virtual_processor.png": +{ + "frame": {"x":291,"y":1037,"w":144,"h":141}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":3,"w":144,"h":141}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire-cross.png": +{ + "frame": {"x":1249,"y":704,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire-split.png": +{ + "frame": {"x":1098,"y":1000,"w":144,"h":82}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":62,"w":144,"h":82}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire-turn.png": +{ + "frame": {"x":706,"y":1036,"w":82,"h":82}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":62,"y":62,"w":82,"h":82}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire.png": +{ + "frame": {"x":1107,"y":151,"w":20,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":62,"y":0,"w":20,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire_tunnel-coating.png": +{ + "frame": {"x":255,"y":677,"w":33,"h":134}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":56,"y":5,"w":33,"h":134}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire_tunnel.png": +{ + "frame": {"x":1516,"y":1435,"w":138,"h":135}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":138,"h":135}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/belt_left.png": +{ + "frame": {"x":3,"y":1182,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/belt_right.png": +{ + "frame": {"x":925,"y":1476,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/belt_top.png": +{ + "frame": {"x":440,"y":742,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/constant_signal.png": +{ + "frame": {"x":1941,"y":716,"w":104,"h":127}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":104,"h":127}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/cutter-quad.png": +{ + "frame": {"x":555,"y":151,"w":548,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":548,"h":143}, + "sourceSize": {"w":576,"h":144} +}, +"sprites/buildings/cutter.png": +{ + "frame": {"x":847,"y":446,"w":256,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/display.png": +{ + "frame": {"x":1545,"y":704,"w":126,"h":135}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":126,"h":135}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/filter.png": +{ + "frame": {"x":1379,"y":556,"w":267,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":267,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/hub.png": +{ + "frame": {"x":1131,"y":3,"w":548,"h":549}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":16,"w":548,"h":549}, + "sourceSize": {"w":576,"h":576} +}, +"sprites/buildings/lever.png": +{ + "frame": {"x":1823,"y":865,"w":109,"h":127}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":18,"y":5,"w":109,"h":127}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate-not.png": +{ + "frame": {"x":972,"y":885,"w":122,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":12,"y":0,"w":122,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate-or.png": +{ + "frame": {"x":1659,"y":1198,"w":143,"h":123}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":123}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate-transistor.png": +{ + "frame": {"x":151,"y":887,"w":100,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":100,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate-xor.png": +{ + "frame": {"x":1392,"y":1126,"w":143,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate.png": +{ + "frame": {"x":1391,"y":1273,"w":143,"h":132}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":132}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/miner-chainable.png": +{ + "frame": {"x":3,"y":1703,"w":136,"h":142}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/miner.png": +{ + "frame": {"x":143,"y":1703,"w":136,"h":142}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/mixer.png": +{ + "frame": {"x":560,"y":594,"w":260,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/painter-double.png": +{ + "frame": {"x":1683,"y":294,"w":288,"h":286}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":286}, + "sourceSize": {"w":288,"h":288} +}, +"sprites/buildings/painter-mirrored.png": +{ + "frame": {"x":555,"y":446,"w":288,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/painter-quad.png": +{ + "frame": {"x":567,"y":3,"w":560,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, + "sourceSize": {"w":576,"h":144} +}, +"sprites/buildings/painter.png": +{ + "frame": {"x":3,"y":447,"w":288,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/reader.png": +{ + "frame": {"x":790,"y":1260,"w":141,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":141,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/rotater-ccw.png": +{ + "frame": {"x":1083,"y":1319,"w":141,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/rotater-fl.png": +{ + "frame": {"x":935,"y":1329,"w":141,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":141,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/rotater.png": +{ + "frame": {"x":1228,"y":1408,"w":141,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/splitter-compact-inverse.png": +{ + "frame": {"x":1080,"y":1466,"w":141,"h":136}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":3,"w":141,"h":136}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/splitter-compact-merge-inverse.png": +{ + "frame": {"x":559,"y":1178,"w":142,"h":136}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":3,"w":142,"h":136}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/splitter-compact-merge.png": +{ + "frame": {"x":1658,"y":1473,"w":139,"h":136}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":3,"w":139,"h":136}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/splitter-compact.png": +{ + "frame": {"x":1658,"y":1613,"w":139,"h":136}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":3,"w":139,"h":136}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/splitter.png": +{ + "frame": {"x":295,"y":447,"w":256,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/stacker.png": +{ + "frame": {"x":560,"y":741,"w":260,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/trash-storage.png": +{ + "frame": {"x":3,"y":595,"w":248,"h":288}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":22,"y":0,"w":248,"h":288}, + "sourceSize": {"w":288,"h":288} +}, +"sprites/buildings/trash.png": +{ + "frame": {"x":1397,"y":704,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/underground_belt_entry-tier2.png": +{ + "frame": {"x":3,"y":1476,"w":137,"h":124}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":20,"w":137,"h":124}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/underground_belt_entry.png": +{ + "frame": {"x":283,"y":1414,"w":137,"h":111}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":33,"w":137,"h":111}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/underground_belt_exit-tier2.png": +{ + "frame": {"x":283,"y":1529,"w":137,"h":111}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/underground_belt_exit.png": +{ + "frame": {"x":424,"y":1588,"w":137,"h":111}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/virtual_processor-analyzer.png": +{ + "frame": {"x":1675,"y":732,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/virtual_processor-rotater.png": +{ + "frame": {"x":439,"y":890,"w":117,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":117,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/virtual_processor-shapecompare.png": +{ + "frame": {"x":1244,"y":1271,"w":143,"h":133}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":133}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/virtual_processor-stacker.png": +{ + "frame": {"x":3,"y":1849,"w":130,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":130,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/virtual_processor-unstacker.png": +{ + "frame": {"x":3,"y":1035,"w":144,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":1,"w":144,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/virtual_processor.png": +{ + "frame": {"x":1249,"y":852,"w":144,"h":140}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":144,"h":140}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire-cross.png": +{ + "frame": {"x":1672,"y":880,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire-split.png": +{ + "frame": {"x":1667,"y":1028,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire-turn.png": +{ + "frame": {"x":1941,"y":631,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire.png": +{ + "frame": {"x":2027,"y":272,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire_tunnel-coating.png": +{ + "frame": {"x":255,"y":815,"w":32,"h":134}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":56,"y":5,"w":32,"h":134}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire_tunnel.png": +{ + "frame": {"x":559,"y":1318,"w":137,"h":134}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":5,"w":137,"h":134}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/debug/acceptor_slot.png": +{ + "frame": {"x":1107,"y":447,"w":12,"h":12}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":12,"h":12}, + "sourceSize": {"w":12,"h":12} +}, +"sprites/debug/ejector_slot.png": +{ + "frame": {"x":1107,"y":463,"w":12,"h":12}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":12,"h":12}, + "sourceSize": {"w":12,"h":12} +}, +"sprites/misc/hub_direction_indicator.png": +{ + "frame": {"x":1975,"y":272,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/misc/processor_disabled.png": +{ + "frame": {"x":3,"y":1606,"w":78,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":10,"y":10,"w":78,"h":81}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/misc/processor_disconnected.png": +{ + "frame": {"x":1975,"y":3,"w":65,"h":84}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":8,"w":65,"h":84}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/misc/reader_overlay.png": +{ + "frame": {"x":1820,"y":996,"w":104,"h":70}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":38,"w":104,"h":70}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/misc/slot_bad_arrow.png": +{ + "frame": {"x":255,"y":638,"w":35,"h":35}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":35,"h":35}, + "sourceSize": {"w":39,"h":39} +}, +"sprites/misc/slot_good_arrow.png": +{ + "frame": {"x":255,"y":595,"w":35,"h":39}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":35,"h":39}, + "sourceSize": {"w":39,"h":39} +}, +"sprites/misc/storage_overlay.png": +{ + "frame": {"x":1935,"y":1209,"w":89,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":89,"h":44}, + "sourceSize": {"w":90,"h":45} +}, +"sprites/misc/waypoint.png": +{ + "frame": {"x":48,"y":1997,"w":38,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":38,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/boolean_false.png": +{ + "frame": {"x":255,"y":953,"w":31,"h":41}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":5,"w":31,"h":41}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/boolean_true.png": +{ + "frame": {"x":1650,"y":556,"w":22,"h":41}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":5,"w":22,"h":41}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/display/blue.png": +{ + "frame": {"x":1975,"y":376,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/cyan.png": +{ + "frame": {"x":1975,"y":427,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/green.png": +{ + "frame": {"x":1975,"y":478,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/purple.png": +{ + "frame": {"x":1975,"y":529,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/red.png": +{ + "frame": {"x":1975,"y":580,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/white.png": +{ + "frame": {"x":90,"y":1997,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/yellow.png": +{ + "frame": {"x":141,"y":1997,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/lever_on.png": +{ + "frame": {"x":1936,"y":978,"w":109,"h":127}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":18,"y":5,"w":109,"h":127}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/logical_acceptor.png": +{ + "frame": {"x":1975,"y":91,"w":62,"h":106}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":43,"y":0,"w":62,"h":106}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/logical_ejector.png": +{ + "frame": {"x":1975,"y":201,"w":60,"h":67}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":44,"y":0,"w":60,"h":67}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/network_conflict.png": +{ + "frame": {"x":192,"y":1997,"w":47,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":2,"w":47,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/network_empty.png": +{ + "frame": {"x":3,"y":1997,"w":41,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":41,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/overlay_tile.png": +{ + "frame": {"x":1935,"y":1109,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/color_cross.png": +{ + "frame": {"x":1101,"y":852,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/color_forward.png": +{ + "frame": {"x":2026,"y":420,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/color_split.png": +{ + "frame": {"x":1667,"y":1113,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/color_turn.png": +{ + "frame": {"x":706,"y":1122,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/conflict_cross.png": +{ + "frame": {"x":824,"y":885,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/conflict_forward.png": +{ + "frame": {"x":2026,"y":568,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/conflict_split.png": +{ + "frame": {"x":813,"y":1033,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/conflict_turn.png": +{ + "frame": {"x":705,"y":1207,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/regular_cross.png": +{ + "frame": {"x":1672,"y":880,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/regular_forward.png": +{ + "frame": {"x":2027,"y":272,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/regular_split.png": +{ + "frame": {"x":1667,"y":1028,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/regular_turn.png": +{ + "frame": {"x":1941,"y":631,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/shape_cross.png": +{ + "frame": {"x":560,"y":888,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/shape_forward.png": +{ + "frame": {"x":1107,"y":299,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/shape_split.png": +{ + "frame": {"x":1097,"y":1086,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/shape_turn.png": +{ + "frame": {"x":705,"y":1292,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/wires_preview.png": +{ + "frame": {"x":1975,"y":324,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "atlas0_hq.png", + "format": "RGBA8888", + "size": {"w":2048,"h":2048}, + "scale": "0.75", + "smartupdate": "$TexturePacker:SmartUpdate:d21082eda6f288e04b0739186004794d:0912211652d1c400e2846013f9de057b:908b89f5ca8ff73e331a35a3b14d0604$" +} +} diff --git a/res_built/atlas/atlas0_hq.png b/res_built/atlas/atlas0_hq.png new file mode 100644 index 00000000..f56d35d0 Binary files /dev/null and b/res_built/atlas/atlas0_hq.png differ diff --git a/res_built/atlas/atlas0_lq.json b/res_built/atlas/atlas0_lq.json new file mode 100644 index 00000000..c5cdf2ad --- /dev/null +++ b/res_built/atlas/atlas0_lq.json @@ -0,0 +1,1476 @@ +{"frames": { + +"sprites/belt/built/forward_0.png": +{ + "frame": {"x":466,"y":519,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_1.png": +{ + "frame": {"x":51,"y":961,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_2.png": +{ + "frame": {"x":352,"y":869,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_3.png": +{ + "frame": {"x":300,"y":891,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_4.png": +{ + "frame": {"x":249,"y":893,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_5.png": +{ + "frame": {"x":455,"y":864,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_6.png": +{ + "frame": {"x":396,"y":912,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_7.png": +{ + "frame": {"x":344,"y":921,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_8.png": +{ + "frame": {"x":227,"y":973,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_9.png": +{ + "frame": {"x":271,"y":973,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_10.png": +{ + "frame": {"x":95,"y":961,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_11.png": +{ + "frame": {"x":139,"y":941,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_12.png": +{ + "frame": {"x":183,"y":917,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_13.png": +{ + "frame": {"x":183,"y":969,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_0.png": +{ + "frame": {"x":326,"y":499,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_1.png": +{ + "frame": {"x":465,"y":571,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_2.png": +{ + "frame": {"x":323,"y":699,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_3.png": +{ + "frame": {"x":275,"y":707,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_4.png": +{ + "frame": {"x":323,"y":747,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_5.png": +{ + "frame": {"x":208,"y":759,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_6.png": +{ + "frame": {"x":156,"y":773,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_7.png": +{ + "frame": {"x":105,"y":797,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_8.png": +{ + "frame": {"x":54,"y":817,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_9.png": +{ + "frame": {"x":3,"y":843,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_10.png": +{ + "frame": {"x":465,"y":619,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_11.png": +{ + "frame": {"x":324,"y":651,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_12.png": +{ + "frame": {"x":223,"y":611,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_13.png": +{ + "frame": {"x":275,"y":659,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_0.png": +{ + "frame": {"x":311,"y":795,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_1.png": +{ + "frame": {"x":256,"y":797,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_2.png": +{ + "frame": {"x":3,"y":891,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_3.png": +{ + "frame": {"x":359,"y":821,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_4.png": +{ + "frame": {"x":304,"y":843,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_5.png": +{ + "frame": {"x":252,"y":845,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_6.png": +{ + "frame": {"x":201,"y":855,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_7.png": +{ + "frame": {"x":150,"y":869,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_8.png": +{ + "frame": {"x":99,"y":893,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_9.png": +{ + "frame": {"x":51,"y":913,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_10.png": +{ + "frame": {"x":204,"y":807,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_11.png": +{ + "frame": {"x":153,"y":821,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_12.png": +{ + "frame": {"x":102,"y":845,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_13.png": +{ + "frame": {"x":51,"y":865,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/belt_left.png": +{ + "frame": {"x":3,"y":939,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/belt_right.png": +{ + "frame": {"x":407,"y":864,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/belt_top.png": +{ + "frame": {"x":315,"y":973,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/constant_signal.png": +{ + "frame": {"x":426,"y":411,"w":36,"h":43}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":36,"h":43}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/cutter-quad.png": +{ + "frame": {"x":191,"y":55,"w":184,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, + "sourceSize": {"w":192,"h":48} +}, +"sprites/blueprints/cutter.png": +{ + "frame": {"x":95,"y":296,"w":87,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/display.png": +{ + "frame": {"x":326,"y":399,"w":44,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":44,"h":46}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/filter.png": +{ + "frame": {"x":3,"y":244,"w":91,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":91,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/lever.png": +{ + "frame": {"x":231,"y":467,"w":38,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":1,"w":38,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate-not.png": +{ + "frame": {"x":467,"y":311,"w":42,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":42,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate-or.png": +{ + "frame": {"x":423,"y":818,"w":48,"h":42}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":42}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate-transistor.png": +{ + "frame": {"x":426,"y":534,"w":35,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":35,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate-xor.png": +{ + "frame": {"x":291,"y":159,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate.png": +{ + "frame": {"x":171,"y":622,"w":48,"h":45}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/miner-chainable.png": +{ + "frame": {"x":107,"y":648,"w":47,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/miner.png": +{ + "frame": {"x":55,"y":672,"w":47,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/mixer.png": +{ + "frame": {"x":98,"y":244,"w":89,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/painter-double.png": +{ + "frame": {"x":387,"y":3,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/painter-mirrored.png": +{ + "frame": {"x":191,"y":159,"w":96,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/painter-quad.png": +{ + "frame": {"x":3,"y":3,"w":188,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, + "sourceSize": {"w":192,"h":48} +}, +"sprites/blueprints/painter.png": +{ + "frame": {"x":375,"y":203,"w":96,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/reader.png": +{ + "frame": {"x":291,"y":211,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/rotater-ccw.png": +{ + "frame": {"x":274,"y":399,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/rotater-fl.png": +{ + "frame": {"x":374,"y":411,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/rotater.png": +{ + "frame": {"x":274,"y":451,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/splitter-compact-inverse.png": +{ + "frame": {"x":374,"y":463,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/splitter-compact-merge-inverse.png": +{ + "frame": {"x":374,"y":515,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/splitter-compact-merge.png": +{ + "frame": {"x":106,"y":700,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/splitter-compact.png": +{ + "frame": {"x":54,"y":724,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/splitter.png": +{ + "frame": {"x":186,"y":315,"w":87,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/stacker.png": +{ + "frame": {"x":374,"y":307,"w":89,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/trash-storage.png": +{ + "frame": {"x":285,"y":299,"w":85,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/trash.png": +{ + "frame": {"x":3,"y":400,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/underground_belt_entry-tier2.png": +{ + "frame": {"x":447,"y":771,"w":48,"h":43}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":5,"w":48,"h":43}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/underground_belt_entry.png": +{ + "frame": {"x":55,"y":556,"w":48,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":10,"w":48,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/underground_belt_exit-tier2.png": +{ + "frame": {"x":55,"y":598,"w":48,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/underground_belt_exit.png": +{ + "frame": {"x":107,"y":606,"w":48,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/virtual_processor-analyzer.png": +{ + "frame": {"x":55,"y":400,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/virtual_processor-rotater.png": +{ + "frame": {"x":466,"y":415,"w":41,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":41,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/virtual_processor-shapecompare.png": +{ + "frame": {"x":223,"y":659,"w":48,"h":45}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/virtual_processor-stacker.png": +{ + "frame": {"x":325,"y":547,"w":45,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":45,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/virtual_processor-unstacker.png": +{ + "frame": {"x":107,"y":400,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/virtual_processor.png": +{ + "frame": {"x":3,"y":452,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire-cross.png": +{ + "frame": {"x":55,"y":452,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire-split.png": +{ + "frame": {"x":285,"y":263,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire-turn.png": +{ + "frame": {"x":479,"y":162,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire.png": +{ + "frame": {"x":159,"y":520,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire_tunnel-coating.png": +{ + "frame": {"x":426,"y":655,"w":12,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":18,"y":1,"w":12,"h":46}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire_tunnel.png": +{ + "frame": {"x":107,"y":504,"w":48,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/belt_left.png": +{ + "frame": {"x":326,"y":499,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/belt_right.png": +{ + "frame": {"x":311,"y":795,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/belt_top.png": +{ + "frame": {"x":466,"y":519,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/constant_signal.png": +{ + "frame": {"x":426,"y":458,"w":36,"h":43}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":36,"h":43}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/cutter-quad.png": +{ + "frame": {"x":191,"y":107,"w":184,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, + "sourceSize": {"w":192,"h":48} +}, +"sprites/buildings/cutter.png": +{ + "frame": {"x":3,"y":348,"w":87,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/display.png": +{ + "frame": {"x":326,"y":449,"w":44,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":44,"h":46}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/filter.png": +{ + "frame": {"x":191,"y":263,"w":90,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":90,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/hub.png": +{ + "frame": {"x":3,"y":55,"w":184,"h":185}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":184,"h":185}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/buildings/lever.png": +{ + "frame": {"x":231,"y":515,"w":38,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":1,"w":38,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate-not.png": +{ + "frame": {"x":466,"y":363,"w":43,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":43,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate-or.png": +{ + "frame": {"x":3,"y":556,"w":48,"h":42}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":42}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate-transistor.png": +{ + "frame": {"x":426,"y":586,"w":35,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":35,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate-xor.png": +{ + "frame": {"x":107,"y":452,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate.png": +{ + "frame": {"x":371,"y":723,"w":48,"h":45}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/miner-chainable.png": +{ + "frame": {"x":3,"y":698,"w":47,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/miner.png": +{ + "frame": {"x":158,"y":671,"w":47,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/mixer.png": +{ + "frame": {"x":374,"y":359,"w":88,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/painter-double.png": +{ + "frame": {"x":379,"y":103,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/painter-mirrored.png": +{ + "frame": {"x":191,"y":211,"w":96,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/painter-quad.png": +{ + "frame": {"x":195,"y":3,"w":188,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, + "sourceSize": {"w":192,"h":48} +}, +"sprites/buildings/painter.png": +{ + "frame": {"x":375,"y":255,"w":96,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/reader.png": +{ + "frame": {"x":179,"y":467,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/rotater-ccw.png": +{ + "frame": {"x":273,"y":503,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/rotater-fl.png": +{ + "frame": {"x":374,"y":567,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/rotater.png": +{ + "frame": {"x":273,"y":555,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/splitter-compact-inverse.png": +{ + "frame": {"x":107,"y":555,"w":48,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/splitter-compact-merge-inverse.png": +{ + "frame": {"x":171,"y":571,"w":48,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/splitter-compact-merge.png": +{ + "frame": {"x":3,"y":750,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/splitter-compact.png": +{ + "frame": {"x":209,"y":708,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/splitter.png": +{ + "frame": {"x":94,"y":348,"w":87,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/stacker.png": +{ + "frame": {"x":3,"y":296,"w":88,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/trash-storage.png": +{ + "frame": {"x":185,"y":367,"w":85,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/trash.png": +{ + "frame": {"x":374,"y":619,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/underground_belt_entry-tier2.png": +{ + "frame": {"x":105,"y":751,"w":47,"h":42}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":6,"w":47,"h":42}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/underground_belt_entry.png": +{ + "frame": {"x":54,"y":775,"w":47,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":10,"w":47,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/underground_belt_exit-tier2.png": +{ + "frame": {"x":3,"y":801,"w":47,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/underground_belt_exit.png": +{ + "frame": {"x":260,"y":755,"w":47,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/virtual_processor-analyzer.png": +{ + "frame": {"x":178,"y":519,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/virtual_processor-rotater.png": +{ + "frame": {"x":466,"y":467,"w":41,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":41,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/virtual_processor-shapecompare.png": +{ + "frame": {"x":371,"y":772,"w":48,"h":45}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/virtual_processor-stacker.png": +{ + "frame": {"x":325,"y":599,"w":45,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":45,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/virtual_processor-unstacker.png": +{ + "frame": {"x":272,"y":607,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/virtual_processor.png": +{ + "frame": {"x":372,"y":671,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire-cross.png": +{ + "frame": {"x":458,"y":667,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire-split.png": +{ + "frame": {"x":3,"y":602,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire-turn.png": +{ + "frame": {"x":479,"y":194,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire.png": +{ + "frame": {"x":159,"y":572,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire_tunnel-coating.png": +{ + "frame": {"x":442,"y":655,"w":12,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":18,"y":1,"w":12,"h":46}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire_tunnel.png": +{ + "frame": {"x":157,"y":723,"w":47,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":46}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/debug/acceptor_slot.png": +{ + "frame": {"x":379,"y":55,"w":4,"h":4}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":4,"h":4}, + "sourceSize": {"w":4,"h":4} +}, +"sprites/debug/ejector_slot.png": +{ + "frame": {"x":379,"y":63,"w":4,"h":4}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":4,"h":4}, + "sourceSize": {"w":4,"h":4} +}, +"sprites/misc/hub_direction_indicator.png": +{ + "frame": {"x":487,"y":30,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/misc/processor_disabled.png": +{ + "frame": {"x":479,"y":129,"w":28,"h":29}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":28,"h":29}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/misc/processor_disconnected.png": +{ + "frame": {"x":475,"y":258,"w":23,"h":29}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":2,"w":23,"h":29}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/misc/reader_overlay.png": +{ + "frame": {"x":426,"y":505,"w":36,"h":25}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":12,"w":36,"h":25}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/misc/slot_bad_arrow.png": +{ + "frame": {"x":426,"y":638,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/misc/slot_good_arrow.png": +{ + "frame": {"x":443,"y":638,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/misc/storage_overlay.png": +{ + "frame": {"x":479,"y":110,"w":30,"h":15}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":15}, + "sourceSize": {"w":30,"h":15} +}, +"sprites/misc/waypoint.png": +{ + "frame": {"x":495,"y":291,"w":14,"h":16}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/boolean_false.png": +{ + "frame": {"x":424,"y":705,"w":12,"h":15}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":1,"w":12,"h":15}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/boolean_true.png": +{ + "frame": {"x":440,"y":705,"w":9,"h":15}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":1,"w":9,"h":15}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/blue.png": +{ + "frame": {"x":487,"y":50,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/cyan.png": +{ + "frame": {"x":487,"y":70,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/green.png": +{ + "frame": {"x":487,"y":90,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/purple.png": +{ + "frame": {"x":475,"y":291,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/red.png": +{ + "frame": {"x":159,"y":400,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/white.png": +{ + "frame": {"x":159,"y":420,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/yellow.png": +{ + "frame": {"x":159,"y":440,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/lever_on.png": +{ + "frame": {"x":230,"y":563,"w":38,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":1,"w":38,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/logical_acceptor.png": +{ + "frame": {"x":343,"y":259,"w":23,"h":36}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":23,"h":36}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/logical_ejector.png": +{ + "frame": {"x":487,"y":3,"w":22,"h":23}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":22,"h":23}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/network_conflict.png": +{ + "frame": {"x":159,"y":460,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/network_empty.png": +{ + "frame": {"x":159,"y":500,"w":15,"h":16}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":15,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/overlay_tile.png": +{ + "frame": {"x":343,"y":159,"w":32,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/sets/color_cross.png": +{ + "frame": {"x":453,"y":719,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/color_forward.png": +{ + "frame": {"x":423,"y":724,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/color_split.png": +{ + "frame": {"x":3,"y":634,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/color_turn.png": +{ + "frame": {"x":343,"y":195,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/conflict_cross.png": +{ + "frame": {"x":3,"y":504,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/conflict_forward.png": +{ + "frame": {"x":435,"y":724,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/conflict_split.png": +{ + "frame": {"x":55,"y":640,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/conflict_turn.png": +{ + "frame": {"x":475,"y":226,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/regular_cross.png": +{ + "frame": {"x":458,"y":667,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/regular_forward.png": +{ + "frame": {"x":159,"y":572,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/regular_split.png": +{ + "frame": {"x":3,"y":602,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/regular_turn.png": +{ + "frame": {"x":479,"y":194,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/shape_cross.png": +{ + "frame": {"x":55,"y":504,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/shape_forward.png": +{ + "frame": {"x":499,"y":771,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/shape_split.png": +{ + "frame": {"x":3,"y":666,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/shape_turn.png": +{ + "frame": {"x":343,"y":227,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/wires_preview.png": +{ + "frame": {"x":159,"y":480,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "atlas0_lq.png", + "format": "RGBA8888", + "size": {"w":512,"h":1024}, + "scale": "0.25", + "smartupdate": "$TexturePacker:SmartUpdate:d21082eda6f288e04b0739186004794d:0912211652d1c400e2846013f9de057b:908b89f5ca8ff73e331a35a3b14d0604$" +} +} diff --git a/res_built/atlas/atlas0_lq.png b/res_built/atlas/atlas0_lq.png new file mode 100644 index 00000000..1c60156c Binary files /dev/null and b/res_built/atlas/atlas0_lq.png differ diff --git a/res_built/atlas/atlas0_mq.json b/res_built/atlas/atlas0_mq.json new file mode 100644 index 00000000..c5d7d311 --- /dev/null +++ b/res_built/atlas/atlas0_mq.json @@ -0,0 +1,1476 @@ +{"frames": { + +"sprites/belt/built/forward_0.png": +{ + "frame": {"x":943,"y":803,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_1.png": +{ + "frame": {"x":94,"y":1746,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_2.png": +{ + "frame": {"x":754,"y":1555,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_3.png": +{ + "frame": {"x":653,"y":1564,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_4.png": +{ + "frame": {"x":556,"y":1601,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_5.png": +{ + "frame": {"x":458,"y":1663,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_6.png": +{ + "frame": {"x":359,"y":1711,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_7.png": +{ + "frame": {"x":268,"y":1771,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_8.png": +{ + "frame": {"x":176,"y":1835,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_9.png": +{ + "frame": {"x":85,"y":1846,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_10.png": +{ + "frame": {"x":3,"y":1789,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_11.png": +{ + "frame": {"x":3,"y":1889,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_12.png": +{ + "frame": {"x":856,"y":1469,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_13.png": +{ + "frame": {"x":938,"y":1469,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_0.png": +{ + "frame": {"x":403,"y":911,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_1.png": +{ + "frame": {"x":403,"y":1002,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_2.png": +{ + "frame": {"x":3,"y":1516,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_3.png": +{ + "frame": {"x":785,"y":1191,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_4.png": +{ + "frame": {"x":876,"y":1196,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_5.png": +{ + "frame": {"x":785,"y":1282,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_6.png": +{ + "frame": {"x":685,"y":1287,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_7.png": +{ + "frame": {"x":583,"y":1325,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_8.png": +{ + "frame": {"x":482,"y":1381,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_9.png": +{ + "frame": {"x":383,"y":1429,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_10.png": +{ + "frame": {"x":391,"y":1338,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_11.png": +{ + "frame": {"x":292,"y":1398,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_12.png": +{ + "frame": {"x":196,"y":1462,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_13.png": +{ + "frame": {"x":99,"y":1473,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_0.png": +{ + "frame": {"x":287,"y":1489,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_1.png": +{ + "frame": {"x":190,"y":1553,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_2.png": +{ + "frame": {"x":674,"y":1378,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_3.png": +{ + "frame": {"x":573,"y":1416,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_4.png": +{ + "frame": {"x":474,"y":1472,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_5.png": +{ + "frame": {"x":378,"y":1520,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_6.png": +{ + "frame": {"x":281,"y":1580,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_7.png": +{ + "frame": {"x":185,"y":1644,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_8.png": +{ + "frame": {"x":94,"y":1655,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_9.png": +{ + "frame": {"x":3,"y":1698,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_10.png": +{ + "frame": {"x":94,"y":1564,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_11.png": +{ + "frame": {"x":3,"y":1607,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_12.png": +{ + "frame": {"x":876,"y":1287,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_13.png": +{ + "frame": {"x":776,"y":1373,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/belt_left.png": +{ + "frame": {"x":867,"y":1378,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/belt_right.png": +{ + "frame": {"x":765,"y":1464,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/belt_top.png": +{ + "frame": {"x":85,"y":1946,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/constant_signal.png": +{ + "frame": {"x":949,"y":396,"w":71,"h":85}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":71,"h":85}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/cutter-quad.png": +{ + "frame": {"x":373,"y":103,"w":366,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, + "sourceSize": {"w":384,"h":96} +}, +"sprites/blueprints/cutter.png": +{ + "frame": {"x":745,"y":594,"w":172,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":172,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/display.png": +{ + "frame": {"x":664,"y":1469,"w":86,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":5,"w":86,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/filter.png": +{ + "frame": {"x":569,"y":303,"w":180,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":10,"y":0,"w":180,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/lever.png": +{ + "frame": {"x":167,"y":1935,"w":75,"h":86}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":3,"w":75,"h":86}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate-not.png": +{ + "frame": {"x":469,"y":1563,"w":83,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":7,"y":0,"w":83,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate-or.png": +{ + "frame": {"x":303,"y":903,"w":96,"h":82}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":82}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate-transistor.png": +{ + "frame": {"x":451,"y":703,"w":68,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":68,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate-xor.png": +{ + "frame": {"x":3,"y":674,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate.png": +{ + "frame": {"x":910,"y":1103,"w":96,"h":89}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":89}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/miner-chainable.png": +{ + "frame": {"x":100,"y":1373,"w":92,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/miner.png": +{ + "frame": {"x":3,"y":1416,"w":92,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/mixer.png": +{ + "frame": {"x":3,"y":474,"w":175,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/painter-double.png": +{ + "frame": {"x":759,"y":3,"w":192,"h":192}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":192}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/blueprints/painter-mirrored.png": +{ + "frame": {"x":373,"y":303,"w":192,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/painter-quad.png": +{ + "frame": {"x":3,"y":3,"w":374,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, + "sourceSize": {"w":384,"h":96} +}, +"sprites/blueprints/painter.png": +{ + "frame": {"x":753,"y":394,"w":192,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/reader.png": +{ + "frame": {"x":3,"y":926,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/rotater-ccw.png": +{ + "frame": {"x":103,"y":674,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/rotater-fl.png": +{ + "frame": {"x":102,"y":983,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/rotater.png": +{ + "frame": {"x":203,"y":674,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/splitter-compact-inverse.png": +{ + "frame": {"x":300,"y":1047,"w":95,"h":93}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":1,"w":95,"h":93}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/splitter-compact-merge-inverse.png": +{ + "frame": {"x":201,"y":1111,"w":95,"h":93}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":1,"w":95,"h":93}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/splitter-compact-merge.png": +{ + "frame": {"x":300,"y":1144,"w":93,"h":93}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":1,"w":93,"h":93}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/splitter-compact.png": +{ + "frame": {"x":201,"y":1208,"w":93,"h":93}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":1,"w":93,"h":93}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/splitter.png": +{ + "frame": {"x":3,"y":574,"w":171,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/stacker.png": +{ + "frame": {"x":182,"y":474,"w":175,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/trash-storage.png": +{ + "frame": {"x":528,"y":603,"w":167,"h":192}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":167,"h":192}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/blueprints/trash.png": +{ + "frame": {"x":351,"y":703,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/underground_belt_entry-tier2.png": +{ + "frame": {"x":397,"y":1172,"w":93,"h":84}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":12,"w":93,"h":84}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/underground_belt_entry.png": +{ + "frame": {"x":298,"y":1241,"w":93,"h":75}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":21,"w":93,"h":75}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/underground_belt_exit-tier2.png": +{ + "frame": {"x":399,"y":1093,"w":94,"h":75}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":94,"h":75}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/underground_belt_exit.png": +{ + "frame": {"x":198,"y":1305,"w":93,"h":75}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":93,"h":75}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/virtual_processor-analyzer.png": +{ + "frame": {"x":523,"y":799,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/virtual_processor-rotater.png": +{ + "frame": {"x":276,"y":1671,"w":79,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":79,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/virtual_processor-shapecompare.png": +{ + "frame": {"x":3,"y":774,"w":96,"h":89}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":89}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/virtual_processor-stacker.png": +{ + "frame": {"x":931,"y":903,"w":88,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":88,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/virtual_processor-unstacker.png": +{ + "frame": {"x":349,"y":803,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/virtual_processor.png": +{ + "frame": {"x":710,"y":1090,"w":96,"h":94}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":96,"h":94}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire-cross.png": +{ + "frame": {"x":522,"y":899,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire-split.png": +{ + "frame": {"x":3,"y":867,"w":96,"h":55}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":41,"w":96,"h":55}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire-turn.png": +{ + "frame": {"x":955,"y":105,"w":55,"h":55}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":41,"y":41,"w":55,"h":55}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire.png": +{ + "frame": {"x":699,"y":603,"w":14,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":41,"y":0,"w":14,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire_tunnel-coating.png": +{ + "frame": {"x":921,"y":594,"w":23,"h":90}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":37,"y":3,"w":23,"h":90}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire_tunnel.png": +{ + "frame": {"x":101,"y":1278,"w":93,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":93,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/belt_left.png": +{ + "frame": {"x":403,"y":911,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/belt_right.png": +{ + "frame": {"x":287,"y":1489,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/belt_top.png": +{ + "frame": {"x":943,"y":803,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/constant_signal.png": +{ + "frame": {"x":949,"y":485,"w":70,"h":85}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":70,"h":85}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/cutter-quad.png": +{ + "frame": {"x":373,"y":203,"w":366,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, + "sourceSize": {"w":384,"h":96} +}, +"sprites/buildings/cutter.png": +{ + "frame": {"x":178,"y":574,"w":171,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/display.png": +{ + "frame": {"x":565,"y":1507,"w":84,"h":90}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":84,"h":90}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/filter.png": +{ + "frame": {"x":569,"y":403,"w":179,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":179,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/hub.png": +{ + "frame": {"x":3,"y":103,"w":366,"h":367}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":10,"w":366,"h":367}, + "sourceSize": {"w":384,"h":384} +}, +"sprites/buildings/lever.png": +{ + "frame": {"x":948,"y":574,"w":73,"h":85}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":12,"y":3,"w":73,"h":85}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate-not.png": +{ + "frame": {"x":372,"y":1611,"w":82,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":8,"y":0,"w":82,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate-or.png": +{ + "frame": {"x":203,"y":866,"w":96,"h":83}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":83}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate-transistor.png": +{ + "frame": {"x":623,"y":799,"w":68,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":68,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate-xor.png": +{ + "frame": {"x":610,"y":1033,"w":96,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":95}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate.png": +{ + "frame": {"x":203,"y":774,"w":96,"h":88}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":88}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/miner-chainable.png": +{ + "frame": {"x":690,"y":1188,"w":91,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/miner.png": +{ + "frame": {"x":590,"y":1226,"w":91,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/mixer.png": +{ + "frame": {"x":361,"y":503,"w":174,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/painter-double.png": +{ + "frame": {"x":759,"y":199,"w":192,"h":191}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":191}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/buildings/painter-mirrored.png": +{ + "frame": {"x":373,"y":403,"w":192,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/painter-quad.png": +{ + "frame": {"x":381,"y":3,"w":374,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, + "sourceSize": {"w":384,"h":96} +}, +"sprites/buildings/painter.png": +{ + "frame": {"x":752,"y":494,"w":192,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/reader.png": +{ + "frame": {"x":3,"y":1026,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/rotater-ccw.png": +{ + "frame": {"x":201,"y":1011,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/rotater-fl.png": +{ + "frame": {"x":102,"y":1083,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/rotater.png": +{ + "frame": {"x":3,"y":1126,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/splitter-compact-inverse.png": +{ + "frame": {"x":3,"y":1226,"w":94,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":94,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/splitter-compact-merge-inverse.png": +{ + "frame": {"x":102,"y":1183,"w":95,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":95,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/splitter-compact-merge.png": +{ + "frame": {"x":3,"y":1321,"w":93,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":2,"w":93,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/splitter-compact.png": +{ + "frame": {"x":497,"y":1099,"w":93,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":2,"w":93,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/splitter.png": +{ + "frame": {"x":353,"y":603,"w":171,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/stacker.png": +{ + "frame": {"x":539,"y":503,"w":174,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/trash-storage.png": +{ + "frame": {"x":736,"y":694,"w":166,"h":192}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":166,"h":192}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/buildings/trash.png": +{ + "frame": {"x":731,"y":890,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/underground_belt_entry-tier2.png": +{ + "frame": {"x":494,"y":1194,"w":92,"h":83}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":13,"w":92,"h":83}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/underground_belt_entry.png": +{ + "frame": {"x":395,"y":1260,"w":92,"h":74}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":22,"w":92,"h":74}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/underground_belt_exit-tier2.png": +{ + "frame": {"x":295,"y":1320,"w":92,"h":74}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/underground_belt_exit.png": +{ + "frame": {"x":196,"y":1384,"w":92,"h":74}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/virtual_processor-analyzer.png": +{ + "frame": {"x":622,"y":933,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/virtual_processor-rotater.png": +{ + "frame": {"x":185,"y":1735,"w":79,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":79,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/virtual_processor-shapecompare.png": +{ + "frame": {"x":103,"y":774,"w":96,"h":89}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":89}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/virtual_processor-stacker.png": +{ + "frame": {"x":491,"y":1281,"w":88,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":88,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/virtual_processor-unstacker.png": +{ + "frame": {"x":510,"y":999,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/virtual_processor.png": +{ + "frame": {"x":810,"y":1093,"w":96,"h":94}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":96,"h":94}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire-cross.png": +{ + "frame": {"x":831,"y":893,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire-split.png": +{ + "frame": {"x":103,"y":867,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire-turn.png": +{ + "frame": {"x":955,"y":164,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire.png": +{ + "frame": {"x":743,"y":103,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire_tunnel-coating.png": +{ + "frame": {"x":921,"y":688,"w":22,"h":90}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":37,"y":3,"w":22,"h":90}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire_tunnel.png": +{ + "frame": {"x":594,"y":1132,"w":92,"h":90}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":3,"w":92,"h":90}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/debug/acceptor_slot.png": +{ + "frame": {"x":1013,"y":164,"w":8,"h":8}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, + "sourceSize": {"w":8,"h":8} +}, +"sprites/debug/ejector_slot.png": +{ + "frame": {"x":1013,"y":176,"w":8,"h":8}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, + "sourceSize": {"w":8,"h":8} +}, +"sprites/misc/hub_direction_indicator.png": +{ + "frame": {"x":695,"y":851,"w":32,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/misc/processor_disabled.png": +{ + "frame": {"x":449,"y":803,"w":53,"h":55}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":53,"h":55}, + "sourceSize": {"w":64,"h":64} +}, +"sprites/misc/processor_disconnected.png": +{ + "frame": {"x":303,"y":674,"w":44,"h":57}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":5,"w":44,"h":57}, + "sourceSize": {"w":64,"h":64} +}, +"sprites/misc/reader_overlay.png": +{ + "frame": {"x":947,"y":752,"w":70,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":25,"w":70,"h":47}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/misc/slot_bad_arrow.png": +{ + "frame": {"x":717,"y":605,"w":24,"h":24}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":24,"h":24}, + "sourceSize": {"w":26,"h":26} +}, +"sprites/misc/slot_good_arrow.png": +{ + "frame": {"x":717,"y":575,"w":24,"h":26}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":24,"h":26}, + "sourceSize": {"w":26,"h":26} +}, +"sprites/misc/storage_overlay.png": +{ + "frame": {"x":955,"y":71,"w":60,"h":30}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":30}, + "sourceSize": {"w":60,"h":30} +}, +"sprites/misc/waypoint.png": +{ + "frame": {"x":717,"y":539,"w":26,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":26,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/boolean_false.png": +{ + "frame": {"x":717,"y":633,"w":21,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":3,"w":21,"h":28}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/boolean_true.png": +{ + "frame": {"x":717,"y":665,"w":15,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":7,"y":3,"w":15,"h":28}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/display/blue.png": +{ + "frame": {"x":699,"y":703,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/cyan.png": +{ + "frame": {"x":699,"y":740,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/green.png": +{ + "frame": {"x":699,"y":777,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/purple.png": +{ + "frame": {"x":906,"y":782,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/red.png": +{ + "frame": {"x":906,"y":819,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/white.png": +{ + "frame": {"x":906,"y":856,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/yellow.png": +{ + "frame": {"x":695,"y":814,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/lever_on.png": +{ + "frame": {"x":948,"y":663,"w":73,"h":85}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":12,"y":3,"w":73,"h":85}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/logical_acceptor.png": +{ + "frame": {"x":303,"y":735,"w":42,"h":71}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":28,"y":0,"w":42,"h":71}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/logical_ejector.png": +{ + "frame": {"x":449,"y":862,"w":41,"h":45}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":29,"y":0,"w":41,"h":45}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/network_conflict.png": +{ + "frame": {"x":622,"y":899,"w":32,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":1,"w":32,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/network_empty.png": +{ + "frame": {"x":717,"y":503,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/overlay_tile.png": +{ + "frame": {"x":955,"y":3,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"sprites/wires/sets/color_cross.png": +{ + "frame": {"x":722,"y":990,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/color_forward.png": +{ + "frame": {"x":743,"y":203,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/color_split.png": +{ + "frame": {"x":103,"y":925,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/color_turn.png": +{ + "frame": {"x":955,"y":222,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/conflict_cross.png": +{ + "frame": {"x":822,"y":993,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/conflict_forward.png": +{ + "frame": {"x":506,"y":803,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/conflict_split.png": +{ + "frame": {"x":203,"y":953,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/conflict_turn.png": +{ + "frame": {"x":955,"y":280,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/regular_cross.png": +{ + "frame": {"x":831,"y":893,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/regular_forward.png": +{ + "frame": {"x":743,"y":103,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/regular_split.png": +{ + "frame": {"x":103,"y":867,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/regular_turn.png": +{ + "frame": {"x":955,"y":164,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/shape_cross.png": +{ + "frame": {"x":922,"y":1003,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/shape_forward.png": +{ + "frame": {"x":494,"y":903,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/shape_split.png": +{ + "frame": {"x":303,"y":989,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/shape_turn.png": +{ + "frame": {"x":955,"y":338,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/wires_preview.png": +{ + "frame": {"x":695,"y":887,"w":32,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, + "sourceSize": {"w":32,"h":32} +}}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "atlas0_mq.png", + "format": "RGBA8888", + "size": {"w":1024,"h":2048}, + "scale": "0.5", + "smartupdate": "$TexturePacker:SmartUpdate:d21082eda6f288e04b0739186004794d:0912211652d1c400e2846013f9de057b:908b89f5ca8ff73e331a35a3b14d0604$" +} +} diff --git a/res_built/atlas/atlas0_mq.png b/res_built/atlas/atlas0_mq.png new file mode 100644 index 00000000..9e9b97c6 Binary files /dev/null and b/res_built/atlas/atlas0_mq.png differ diff --git a/res_raw/atlas.tps b/res_raw/atlas.tps index 87eacd70..947bdb04 100644 --- a/res_raw/atlas.tps +++ b/res_raw/atlas.tps @@ -7,28 +7,11 @@ 5.4.0 autoSDSettings - - scale - 1 - extension - _100 - spriteFilter - - acceptFractionalValues - - maxTextureSize - - width - 4096 - height - 4096 - - scale 0.75 extension - _75 + _hq spriteFilter acceptFractionalValues @@ -45,7 +28,7 @@ scale 0.5 extension - _50 + _mq spriteFilter acceptFractionalValues @@ -62,7 +45,7 @@ scale 0.25 extension - _25 + _lq spriteFilter acceptFractionalValues @@ -70,26 +53,9 @@ maxTextureSize width - 1024 + 2048 height - 1024 - - - - scale - 0.1 - extension - _10 - spriteFilter - - acceptFractionalValues - - maxTextureSize - - width - -1 - height - -1 + 2048 @@ -174,7 +140,7 @@ freeSizeMode Best sizeConstraints - AnySize + POT forceSquared maxRects @@ -249,17 +215,123 @@ individualSpriteSettings - sprites/belt/forward_0.png - sprites/belt/forward_1.png - sprites/belt/forward_2.png - sprites/buildings/miner.png - sprites/buildings/rotater.png - sprites/buildings/trash.png - sprites/misc/wires_overlay_tile.png - sprites/wires/pin_negative_accept.png - sprites/wires/pin_negative_eject.png - sprites/wires/pin_positive_accept.png - sprites/wires/pin_positive_eject.png + sprites/belt/built/forward_0.png + sprites/belt/built/forward_1.png + sprites/belt/built/forward_10.png + sprites/belt/built/forward_11.png + sprites/belt/built/forward_12.png + sprites/belt/built/forward_13.png + sprites/belt/built/forward_2.png + sprites/belt/built/forward_3.png + sprites/belt/built/forward_4.png + sprites/belt/built/forward_5.png + sprites/belt/built/forward_6.png + sprites/belt/built/forward_7.png + sprites/belt/built/forward_8.png + sprites/belt/built/forward_9.png + sprites/belt/built/left_0.png + sprites/belt/built/left_1.png + sprites/belt/built/left_10.png + sprites/belt/built/left_11.png + sprites/belt/built/left_12.png + sprites/belt/built/left_13.png + sprites/belt/built/left_2.png + sprites/belt/built/left_3.png + sprites/belt/built/left_4.png + sprites/belt/built/left_5.png + sprites/belt/built/left_6.png + sprites/belt/built/left_7.png + sprites/belt/built/left_8.png + sprites/belt/built/left_9.png + sprites/belt/built/right_0.png + sprites/belt/built/right_1.png + sprites/belt/built/right_10.png + sprites/belt/built/right_11.png + sprites/belt/built/right_12.png + sprites/belt/built/right_13.png + sprites/belt/built/right_2.png + sprites/belt/built/right_3.png + sprites/belt/built/right_4.png + sprites/belt/built/right_5.png + sprites/belt/built/right_6.png + sprites/belt/built/right_7.png + sprites/belt/built/right_8.png + sprites/belt/built/right_9.png + sprites/blueprints/constant_signal.png + sprites/blueprints/display.png + sprites/blueprints/lever.png + sprites/blueprints/logic_gate-not.png + sprites/blueprints/logic_gate-or.png + sprites/blueprints/logic_gate-transistor.png + sprites/blueprints/logic_gate-xor.png + sprites/blueprints/logic_gate.png + sprites/blueprints/miner-chainable.png + sprites/blueprints/miner.png + sprites/blueprints/reader.png + sprites/blueprints/rotater-ccw.png + sprites/blueprints/rotater-fl.png + sprites/blueprints/rotater.png + sprites/blueprints/splitter-compact-inverse.png + sprites/blueprints/splitter-compact-merge-inverse.png + sprites/blueprints/splitter-compact-merge.png + sprites/blueprints/splitter-compact.png + sprites/blueprints/trash.png + sprites/blueprints/underground_belt_entry-tier2.png + sprites/blueprints/underground_belt_entry.png + sprites/blueprints/underground_belt_exit-tier2.png + sprites/blueprints/underground_belt_exit.png + sprites/blueprints/virtual_processor-analyzer.png + sprites/blueprints/virtual_processor-rotater.png + sprites/blueprints/virtual_processor-shapecompare.png + sprites/blueprints/virtual_processor-unstacker.png + sprites/blueprints/virtual_processor.png + sprites/blueprints/wire_tunnel-coating.png + sprites/blueprints/wire_tunnel.png + sprites/buildings/constant_signal.png + sprites/buildings/display.png + sprites/buildings/lever.png + sprites/buildings/logic_gate-not.png + sprites/buildings/logic_gate-or.png + sprites/buildings/logic_gate-transistor.png + sprites/buildings/logic_gate-xor.png + sprites/buildings/logic_gate.png + sprites/buildings/miner-chainable.png + sprites/buildings/reader.png + sprites/buildings/rotater-ccw.png + sprites/buildings/rotater-fl.png + sprites/buildings/splitter-compact-inverse.png + sprites/buildings/splitter-compact-merge-inverse.png + sprites/buildings/splitter-compact-merge.png + sprites/buildings/splitter-compact.png + sprites/buildings/underground_belt_entry-tier2.png + sprites/buildings/underground_belt_entry.png + sprites/buildings/underground_belt_exit-tier2.png + sprites/buildings/underground_belt_exit.png + sprites/buildings/virtual_processor-analyzer.png + sprites/buildings/virtual_processor-rotater.png + sprites/buildings/virtual_processor-shapecompare.png + sprites/buildings/virtual_processor-unstacker.png + sprites/buildings/virtual_processor.png + sprites/buildings/wire_tunnel-coating.png + sprites/buildings/wire_tunnel.png + sprites/misc/reader_overlay.png + sprites/wires/lever_on.png + sprites/wires/sets/color_cross.png + sprites/wires/sets/color_forward.png + sprites/wires/sets/color_split.png + sprites/wires/sets/color_turn.png + sprites/wires/sets/conflict_cross.png + sprites/wires/sets/conflict_forward.png + sprites/wires/sets/conflict_split.png + sprites/wires/sets/conflict_turn.png + sprites/wires/sets/regular_cross.png + sprites/wires/sets/regular_forward.png + sprites/wires/sets/regular_split.png + sprites/wires/sets/regular_turn.png + sprites/wires/sets/shape_cross.png + sprites/wires/sets/shape_forward.png + sprites/wires/sets/shape_split.png + sprites/wires/sets/shape_turn.png pivotPoint 0.5,0.5 @@ -268,109 +340,26 @@ scale9Enabled scale9Borders - 32,32,64,64 + 48,48,96,96 scale9Paddings - 32,32,64,64 + 48,48,96,96 scale9FromFile - sprites/belt/forward_10.png - sprites/belt/forward_11.png - sprites/belt/forward_12.png - sprites/belt/forward_13.png - sprites/belt/forward_14.png - sprites/belt/forward_15.png - sprites/belt/forward_16.png - sprites/belt/forward_17.png - sprites/belt/forward_18.png - sprites/belt/forward_19.png - sprites/belt/forward_20.png - sprites/belt/forward_21.png - sprites/belt/forward_22.png - sprites/belt/forward_23.png - sprites/belt/forward_24.png - sprites/belt/forward_25.png - sprites/belt/forward_26.png - sprites/belt/forward_27.png - sprites/belt/forward_3.png - sprites/belt/forward_4.png - sprites/belt/forward_5.png - sprites/belt/forward_6.png - sprites/belt/forward_7.png - sprites/belt/forward_8.png - sprites/belt/forward_9.png - sprites/belt/left_0.png - sprites/belt/left_1.png - sprites/belt/left_10.png - sprites/belt/left_11.png - sprites/belt/left_12.png - sprites/belt/left_13.png - sprites/belt/left_14.png - sprites/belt/left_15.png - sprites/belt/left_16.png - sprites/belt/left_17.png - sprites/belt/left_18.png - sprites/belt/left_19.png - sprites/belt/left_2.png - sprites/belt/left_20.png - sprites/belt/left_21.png - sprites/belt/left_22.png - sprites/belt/left_23.png - sprites/belt/left_24.png - sprites/belt/left_25.png - sprites/belt/left_26.png - sprites/belt/left_27.png - sprites/belt/left_3.png - sprites/belt/left_4.png - sprites/belt/left_5.png - sprites/belt/left_6.png - sprites/belt/left_7.png - sprites/belt/left_8.png - sprites/belt/left_9.png - sprites/belt/right_0.png - sprites/belt/right_1.png - sprites/belt/right_10.png - sprites/belt/right_11.png - sprites/belt/right_12.png - sprites/belt/right_13.png - sprites/belt/right_14.png - sprites/belt/right_15.png - sprites/belt/right_16.png - sprites/belt/right_17.png - sprites/belt/right_18.png - sprites/belt/right_19.png - sprites/belt/right_2.png - sprites/belt/right_20.png - sprites/belt/right_21.png - sprites/belt/right_22.png - sprites/belt/right_23.png - sprites/belt/right_24.png - sprites/belt/right_25.png - sprites/belt/right_26.png - sprites/belt/right_27.png - sprites/belt/right_3.png - sprites/belt/right_4.png - sprites/belt/right_5.png - sprites/belt/right_6.png - sprites/belt/right_7.png - sprites/belt/right_8.png - sprites/belt/right_9.png sprites/blueprints/belt_left.png sprites/blueprints/belt_right.png sprites/blueprints/belt_top.png - sprites/blueprints/wire_crossings-merger.png - sprites/blueprints/wire_crossings.png - sprites/blueprints/wire_left.png - sprites/blueprints/wire_right.png - sprites/blueprints/wire_top.png + sprites/blueprints/wire-cross.png + sprites/blueprints/wire-split.png + sprites/blueprints/wire-turn.png + sprites/blueprints/wire.png sprites/buildings/belt_left.png sprites/buildings/belt_right.png sprites/buildings/belt_top.png - sprites/buildings/wire_crossings-merger.png - sprites/buildings/wire_crossings.png - sprites/buildings/wire_left.png - sprites/buildings/wire_right.png - sprites/buildings/wire_top.png + sprites/buildings/wire-cross.png + sprites/buildings/wire-split.png + sprites/buildings/wire-turn.png + sprites/buildings/wire.png pivotPoint 0.5,0.5 @@ -385,28 +374,6 @@ scale9FromFile - sprites/blueprints/advanced_processor.png - sprites/blueprints/energy_generator.png - sprites/blueprints/painter-double.png - sprites/blueprints/trash-storage.png - sprites/buildings/advanced_processor.png - sprites/buildings/energy_generator.png - sprites/buildings/painter-double.png - sprites/misc/energy_generator_overlay.png - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 96,96,192,192 - scale9Paddings - 96,96,192,192 - scale9FromFile - - sprites/blueprints/cutter-quad.png sprites/blueprints/painter-quad.png sprites/buildings/cutter-quad.png @@ -426,11 +393,13 @@ sprites/blueprints/cutter.png + sprites/blueprints/filter.png sprites/blueprints/mixer.png sprites/blueprints/painter-mirrored.png sprites/blueprints/painter.png sprites/blueprints/splitter.png sprites/blueprints/stacker.png + sprites/buildings/filter.png sprites/buildings/painter-mirrored.png pivotPoint @@ -446,25 +415,9 @@ scale9FromFile - sprites/blueprints/miner-chainable.png - sprites/blueprints/miner.png - sprites/blueprints/rotater-ccw.png - sprites/blueprints/rotater.png - sprites/blueprints/splitter-compact-inverse.png - sprites/blueprints/splitter-compact.png - sprites/blueprints/trash.png - sprites/blueprints/underground_belt_entry-tier2.png - sprites/blueprints/underground_belt_entry.png - sprites/blueprints/underground_belt_exit-tier2.png - sprites/blueprints/underground_belt_exit.png - sprites/buildings/miner-chainable.png - sprites/buildings/rotater-ccw.png - sprites/buildings/splitter-compact-inverse.png - sprites/buildings/splitter-compact.png - sprites/buildings/underground_belt_entry-tier2.png - sprites/buildings/underground_belt_entry.png - sprites/buildings/underground_belt_exit-tier2.png - sprites/buildings/underground_belt_exit.png + sprites/blueprints/painter-double.png + sprites/blueprints/trash-storage.png + sprites/buildings/painter-double.png pivotPoint 0.5,0.5 @@ -473,9 +426,9 @@ scale9Enabled scale9Borders - 48,48,96,96 + 96,96,192,192 scale9Paddings - 48,48,96,96 + 96,96,192,192 scale9FromFile @@ -513,6 +466,28 @@ scale9FromFile + sprites/buildings/miner.png + sprites/buildings/rotater.png + sprites/buildings/trash.png + sprites/misc/processor_disabled.png + sprites/misc/processor_disconnected.png + sprites/wires/logical_acceptor.png + sprites/wires/logical_ejector.png + sprites/wires/overlay_tile.png + + pivotPoint + 0.5,0.5 + spriteScale + 1 + scale9Enabled + + scale9Borders + 32,32,64,64 + scale9Paddings + 32,32,64,64 + scale9FromFile + + sprites/buildings/trash-storage.png pivotPoint @@ -530,9 +505,6 @@ sprites/debug/acceptor_slot.png sprites/debug/ejector_slot.png - sprites/map_overview/belt_forward.png - sprites/map_overview/belt_left.png - sprites/map_overview/belt_right.png sprites/misc/hub_direction_indicator.png sprites/misc/waypoint.png @@ -549,7 +521,6 @@ scale9FromFile - sprites/misc/deletion_marker.png sprites/misc/slot_bad_arrow.png sprites/misc/slot_good_arrow.png @@ -566,21 +537,6 @@ scale9FromFile - sprites/misc/lock_direction_indicator.png - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 12,12,24,24 - scale9Paddings - 12,12,24,24 - scale9FromFile - - sprites/misc/storage_overlay.png pivotPoint @@ -596,13 +552,11 @@ scale9FromFile - sprites/wires/battery_empty.png - sprites/wires/battery_full.png - sprites/wires/battery_low.png - sprites/wires/battery_medium.png - sprites/wires/negative_energy.png - sprites/wires/positive_energy.png - sprites/wires/waste_piled.png + sprites/wires/boolean_false.png + sprites/wires/boolean_true.png + sprites/wires/network_conflict.png + sprites/wires/network_empty.png + sprites/wires/wires_preview.png pivotPoint 0.5,0.5 @@ -617,6 +571,27 @@ scale9FromFile + sprites/wires/display/blue.png + sprites/wires/display/cyan.png + sprites/wires/display/green.png + sprites/wires/display/purple.png + sprites/wires/display/red.png + sprites/wires/display/white.png + sprites/wires/display/yellow.png + + pivotPoint + 0.5,0.5 + spriteScale + 1 + scale9Enabled + + scale9Borders + 11,11,22,22 + scale9Paddings + 11,11,22,22 + scale9FromFile + + fileList diff --git a/res_raw/sounds/music/theme-full.mp3 b/res_raw/sounds/music/theme-full.mp3 new file mode 100644 index 00000000..be4f3a7b --- /dev/null +++ b/res_raw/sounds/music/theme-full.mp3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e6959df75e915fb1a8d55e3d0ab750349b27276788ded63178f2a117c2edcf5 +size 79441572 diff --git a/res_raw/sounds/music/theme.wav b/res_raw/sounds/music/theme-short.wav similarity index 100% rename from res_raw/sounds/music/theme.wav rename to res_raw/sounds/music/theme-short.wav diff --git a/res_raw/sounds/sfx/level_complete.wav b/res_raw/sounds/sfx/level_complete.wav index 71444cd8..2977de84 100644 --- a/res_raw/sounds/sfx/level_complete.wav +++ b/res_raw/sounds/sfx/level_complete.wav @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4f810fcfbfcea08cfb48a8d58f9b65d1fd14cd20ff3cabf94a03c39b5250547 -size 1765124 +oid sha256:3207e92c0fa5e71030d04c739647032be2697bf910eb7b7d9548bf04e95803b1 +size 1223220 diff --git a/res_raw/sprites/belt/built/forward_0.png b/res_raw/sprites/belt/built/forward_0.png new file mode 100644 index 00000000..67b47330 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_0.png differ diff --git a/res_raw/sprites/belt/built/forward_1.png b/res_raw/sprites/belt/built/forward_1.png new file mode 100644 index 00000000..6e765f42 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_1.png differ diff --git a/res_raw/sprites/belt/built/forward_10.png b/res_raw/sprites/belt/built/forward_10.png new file mode 100644 index 00000000..cb427231 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_10.png differ diff --git a/res_raw/sprites/belt/built/forward_11.png b/res_raw/sprites/belt/built/forward_11.png new file mode 100644 index 00000000..b44a62ad Binary files /dev/null and b/res_raw/sprites/belt/built/forward_11.png differ diff --git a/res_raw/sprites/belt/built/forward_12.png b/res_raw/sprites/belt/built/forward_12.png new file mode 100644 index 00000000..b9c74030 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_12.png differ diff --git a/res_raw/sprites/belt/built/forward_13.png b/res_raw/sprites/belt/built/forward_13.png new file mode 100644 index 00000000..29c64d5f Binary files /dev/null and b/res_raw/sprites/belt/built/forward_13.png differ diff --git a/res_raw/sprites/belt/built/forward_2.png b/res_raw/sprites/belt/built/forward_2.png new file mode 100644 index 00000000..e1bf428e Binary files /dev/null and b/res_raw/sprites/belt/built/forward_2.png differ diff --git a/res_raw/sprites/belt/built/forward_3.png b/res_raw/sprites/belt/built/forward_3.png new file mode 100644 index 00000000..11907e19 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_3.png differ diff --git a/res_raw/sprites/belt/built/forward_4.png b/res_raw/sprites/belt/built/forward_4.png new file mode 100644 index 00000000..7b26e823 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_4.png differ diff --git a/res_raw/sprites/belt/built/forward_5.png b/res_raw/sprites/belt/built/forward_5.png new file mode 100644 index 00000000..481f9362 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_5.png differ diff --git a/res_raw/sprites/belt/built/forward_6.png b/res_raw/sprites/belt/built/forward_6.png new file mode 100644 index 00000000..95bc984c Binary files /dev/null and b/res_raw/sprites/belt/built/forward_6.png differ diff --git a/res_raw/sprites/belt/built/forward_7.png b/res_raw/sprites/belt/built/forward_7.png new file mode 100644 index 00000000..099368f1 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_7.png differ diff --git a/res_raw/sprites/belt/built/forward_8.png b/res_raw/sprites/belt/built/forward_8.png new file mode 100644 index 00000000..d48f8560 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_8.png differ diff --git a/res_raw/sprites/belt/built/forward_9.png b/res_raw/sprites/belt/built/forward_9.png new file mode 100644 index 00000000..34c41082 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_9.png differ diff --git a/res_raw/sprites/belt/built/left_0.png b/res_raw/sprites/belt/built/left_0.png new file mode 100644 index 00000000..8575be67 Binary files /dev/null and b/res_raw/sprites/belt/built/left_0.png differ diff --git a/res_raw/sprites/belt/built/left_1.png b/res_raw/sprites/belt/built/left_1.png new file mode 100644 index 00000000..cfe14b9a Binary files /dev/null and b/res_raw/sprites/belt/built/left_1.png differ diff --git a/res_raw/sprites/belt/built/left_10.png b/res_raw/sprites/belt/built/left_10.png new file mode 100644 index 00000000..c1c82da1 Binary files /dev/null and b/res_raw/sprites/belt/built/left_10.png differ diff --git a/res_raw/sprites/belt/built/left_11.png b/res_raw/sprites/belt/built/left_11.png new file mode 100644 index 00000000..3a75ab79 Binary files /dev/null and b/res_raw/sprites/belt/built/left_11.png differ diff --git a/res_raw/sprites/belt/built/left_12.png b/res_raw/sprites/belt/built/left_12.png new file mode 100644 index 00000000..5a8abc35 Binary files /dev/null and b/res_raw/sprites/belt/built/left_12.png differ diff --git a/res_raw/sprites/belt/built/left_13.png b/res_raw/sprites/belt/built/left_13.png new file mode 100644 index 00000000..ea072a4d Binary files /dev/null and b/res_raw/sprites/belt/built/left_13.png differ diff --git a/res_raw/sprites/belt/built/left_2.png b/res_raw/sprites/belt/built/left_2.png new file mode 100644 index 00000000..263da5aa Binary files /dev/null and b/res_raw/sprites/belt/built/left_2.png differ diff --git a/res_raw/sprites/belt/built/left_3.png b/res_raw/sprites/belt/built/left_3.png new file mode 100644 index 00000000..92441c6e Binary files /dev/null and b/res_raw/sprites/belt/built/left_3.png differ diff --git a/res_raw/sprites/belt/built/left_4.png b/res_raw/sprites/belt/built/left_4.png new file mode 100644 index 00000000..816373da Binary files /dev/null and b/res_raw/sprites/belt/built/left_4.png differ diff --git a/res_raw/sprites/belt/built/left_5.png b/res_raw/sprites/belt/built/left_5.png new file mode 100644 index 00000000..d851b7db Binary files /dev/null and b/res_raw/sprites/belt/built/left_5.png differ diff --git a/res_raw/sprites/belt/built/left_6.png b/res_raw/sprites/belt/built/left_6.png new file mode 100644 index 00000000..bd126a41 Binary files /dev/null and b/res_raw/sprites/belt/built/left_6.png differ diff --git a/res_raw/sprites/belt/built/left_7.png b/res_raw/sprites/belt/built/left_7.png new file mode 100644 index 00000000..6e3de943 Binary files /dev/null and b/res_raw/sprites/belt/built/left_7.png differ diff --git a/res_raw/sprites/belt/built/left_8.png b/res_raw/sprites/belt/built/left_8.png new file mode 100644 index 00000000..ee95dc92 Binary files /dev/null and b/res_raw/sprites/belt/built/left_8.png differ diff --git a/res_raw/sprites/belt/built/left_9.png b/res_raw/sprites/belt/built/left_9.png new file mode 100644 index 00000000..7334bdf3 Binary files /dev/null and b/res_raw/sprites/belt/built/left_9.png differ diff --git a/res_raw/sprites/belt/built/right_0.png b/res_raw/sprites/belt/built/right_0.png new file mode 100644 index 00000000..51cb8c7c Binary files /dev/null and b/res_raw/sprites/belt/built/right_0.png differ diff --git a/res_raw/sprites/belt/built/right_1.png b/res_raw/sprites/belt/built/right_1.png new file mode 100644 index 00000000..199e5d1d Binary files /dev/null and b/res_raw/sprites/belt/built/right_1.png differ diff --git a/res_raw/sprites/belt/built/right_10.png b/res_raw/sprites/belt/built/right_10.png new file mode 100644 index 00000000..ca6e117d Binary files /dev/null and b/res_raw/sprites/belt/built/right_10.png differ diff --git a/res_raw/sprites/belt/built/right_11.png b/res_raw/sprites/belt/built/right_11.png new file mode 100644 index 00000000..19596a73 Binary files /dev/null and b/res_raw/sprites/belt/built/right_11.png differ diff --git a/res_raw/sprites/belt/built/right_12.png b/res_raw/sprites/belt/built/right_12.png new file mode 100644 index 00000000..0299e22d Binary files /dev/null and b/res_raw/sprites/belt/built/right_12.png differ diff --git a/res_raw/sprites/belt/built/right_13.png b/res_raw/sprites/belt/built/right_13.png new file mode 100644 index 00000000..e7e25ba7 Binary files /dev/null and b/res_raw/sprites/belt/built/right_13.png differ diff --git a/res_raw/sprites/belt/built/right_2.png b/res_raw/sprites/belt/built/right_2.png new file mode 100644 index 00000000..428649bb Binary files /dev/null and b/res_raw/sprites/belt/built/right_2.png differ diff --git a/res_raw/sprites/belt/built/right_3.png b/res_raw/sprites/belt/built/right_3.png new file mode 100644 index 00000000..91d419a4 Binary files /dev/null and b/res_raw/sprites/belt/built/right_3.png differ diff --git a/res_raw/sprites/belt/built/right_4.png b/res_raw/sprites/belt/built/right_4.png new file mode 100644 index 00000000..ff0782f3 Binary files /dev/null and b/res_raw/sprites/belt/built/right_4.png differ diff --git a/res_raw/sprites/belt/built/right_5.png b/res_raw/sprites/belt/built/right_5.png new file mode 100644 index 00000000..fd362c5f Binary files /dev/null and b/res_raw/sprites/belt/built/right_5.png differ diff --git a/res_raw/sprites/belt/built/right_6.png b/res_raw/sprites/belt/built/right_6.png new file mode 100644 index 00000000..f542f805 Binary files /dev/null and b/res_raw/sprites/belt/built/right_6.png differ diff --git a/res_raw/sprites/belt/built/right_7.png b/res_raw/sprites/belt/built/right_7.png new file mode 100644 index 00000000..521c110b Binary files /dev/null and b/res_raw/sprites/belt/built/right_7.png differ diff --git a/res_raw/sprites/belt/built/right_8.png b/res_raw/sprites/belt/built/right_8.png new file mode 100644 index 00000000..2591f537 Binary files /dev/null and b/res_raw/sprites/belt/built/right_8.png differ diff --git a/res_raw/sprites/belt/built/right_9.png b/res_raw/sprites/belt/built/right_9.png new file mode 100644 index 00000000..da54ea01 Binary files /dev/null and b/res_raw/sprites/belt/built/right_9.png differ diff --git a/res_raw/sprites/belt/forward_0.png b/res_raw/sprites/belt/forward_0.png deleted file mode 100644 index cf5b20d7..00000000 Binary files a/res_raw/sprites/belt/forward_0.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_1.png b/res_raw/sprites/belt/forward_1.png deleted file mode 100644 index 44e5b8c8..00000000 Binary files a/res_raw/sprites/belt/forward_1.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_10.png b/res_raw/sprites/belt/forward_10.png deleted file mode 100644 index d599463d..00000000 Binary files a/res_raw/sprites/belt/forward_10.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_11.png b/res_raw/sprites/belt/forward_11.png deleted file mode 100644 index 69fff65c..00000000 Binary files a/res_raw/sprites/belt/forward_11.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_12.png b/res_raw/sprites/belt/forward_12.png deleted file mode 100644 index a278e6f0..00000000 Binary files a/res_raw/sprites/belt/forward_12.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_13.png b/res_raw/sprites/belt/forward_13.png deleted file mode 100644 index 13630f42..00000000 Binary files a/res_raw/sprites/belt/forward_13.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_14.png b/res_raw/sprites/belt/forward_14.png deleted file mode 100644 index 1c6bdfb8..00000000 Binary files a/res_raw/sprites/belt/forward_14.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_15.png b/res_raw/sprites/belt/forward_15.png deleted file mode 100644 index be3daa82..00000000 Binary files a/res_raw/sprites/belt/forward_15.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_16.png b/res_raw/sprites/belt/forward_16.png deleted file mode 100644 index 7b9c9dcf..00000000 Binary files a/res_raw/sprites/belt/forward_16.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_17.png b/res_raw/sprites/belt/forward_17.png deleted file mode 100644 index cc37d11a..00000000 Binary files a/res_raw/sprites/belt/forward_17.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_18.png b/res_raw/sprites/belt/forward_18.png deleted file mode 100644 index 7a6460f3..00000000 Binary files a/res_raw/sprites/belt/forward_18.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_19.png b/res_raw/sprites/belt/forward_19.png deleted file mode 100644 index c18e2773..00000000 Binary files a/res_raw/sprites/belt/forward_19.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_2.png b/res_raw/sprites/belt/forward_2.png deleted file mode 100644 index 5a621fbb..00000000 Binary files a/res_raw/sprites/belt/forward_2.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_20.png b/res_raw/sprites/belt/forward_20.png deleted file mode 100644 index ac3f50db..00000000 Binary files a/res_raw/sprites/belt/forward_20.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_21.png b/res_raw/sprites/belt/forward_21.png deleted file mode 100644 index 67d63a4a..00000000 Binary files a/res_raw/sprites/belt/forward_21.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_22.png b/res_raw/sprites/belt/forward_22.png deleted file mode 100644 index f20ec8d3..00000000 Binary files a/res_raw/sprites/belt/forward_22.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_23.png b/res_raw/sprites/belt/forward_23.png deleted file mode 100644 index daa5d1d8..00000000 Binary files a/res_raw/sprites/belt/forward_23.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_24.png b/res_raw/sprites/belt/forward_24.png deleted file mode 100644 index c21bc67d..00000000 Binary files a/res_raw/sprites/belt/forward_24.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_25.png b/res_raw/sprites/belt/forward_25.png deleted file mode 100644 index 4e603e43..00000000 Binary files a/res_raw/sprites/belt/forward_25.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_26.png b/res_raw/sprites/belt/forward_26.png deleted file mode 100644 index 55ae0c96..00000000 Binary files a/res_raw/sprites/belt/forward_26.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_27.png b/res_raw/sprites/belt/forward_27.png deleted file mode 100644 index 816ac1c6..00000000 Binary files a/res_raw/sprites/belt/forward_27.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_3.png b/res_raw/sprites/belt/forward_3.png deleted file mode 100644 index cf2ef011..00000000 Binary files a/res_raw/sprites/belt/forward_3.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_4.png b/res_raw/sprites/belt/forward_4.png deleted file mode 100644 index b06fb99f..00000000 Binary files a/res_raw/sprites/belt/forward_4.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_5.png b/res_raw/sprites/belt/forward_5.png deleted file mode 100644 index 79354fbb..00000000 Binary files a/res_raw/sprites/belt/forward_5.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_6.png b/res_raw/sprites/belt/forward_6.png deleted file mode 100644 index 3df44015..00000000 Binary files a/res_raw/sprites/belt/forward_6.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_7.png b/res_raw/sprites/belt/forward_7.png deleted file mode 100644 index 72251706..00000000 Binary files a/res_raw/sprites/belt/forward_7.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_8.png b/res_raw/sprites/belt/forward_8.png deleted file mode 100644 index ad28047a..00000000 Binary files a/res_raw/sprites/belt/forward_8.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_9.png b/res_raw/sprites/belt/forward_9.png deleted file mode 100644 index daae565f..00000000 Binary files a/res_raw/sprites/belt/forward_9.png and /dev/null differ diff --git a/res_raw/sprites/belt/generate_belt_sprites.js b/res_raw/sprites/belt/generate_belt_sprites.js index f0bd4aa1..79c5d149 100644 --- a/res_raw/sprites/belt/generate_belt_sprites.js +++ b/res_raw/sprites/belt/generate_belt_sprites.js @@ -11,9 +11,10 @@ const { fileURLToPath } = require("url"); async function run() { console.log("Running"); - const fps = 28; - const dimensions = 126; - const beltBorder = 15.5; + const fps = 14; + const dimensions = 192; + const beltBorder = 23.5; + const lineSize = 5; const borderColor = "#91949e"; const fillColor = "#d2d4d9"; @@ -21,8 +22,8 @@ async function run() { // Generate arrow sprite - const arrowW = 40; - const arrowH = 20; + const arrowW = 60; + const arrowH = arrowW / 2; /** @type {HTMLCanvasElement} */ const arrowSprite = createCanvas(arrowW, arrowH); const arrowContext = arrowSprite.getContext("2d"); @@ -37,6 +38,8 @@ async function run() { arrowContext.closePath(); arrowContext.fill(); + const promises = []; + // First, generate the forward belt for (let i = 0; i < fps; ++i) { /** @type {HTMLCanvasElement} */ @@ -49,7 +52,7 @@ async function run() { context.fillStyle = fillColor; context.strokeStyle = borderColor; - context.lineWidth = 3; + context.lineWidth = lineSize; context.beginPath(); context.rect(beltBorder, -10, dimensions - 2 * beltBorder, dimensions + 20); @@ -64,9 +67,10 @@ async function run() { context.drawImage(arrowSprite, dimensions / 2 - arrowW / 2, y); } - const out = fs.createWriteStream(path.join(__dirname, "forward_" + i + ".png")); + const out = fs.createWriteStream(path.join(__dirname, "built", "forward_" + i + ".png")); const stream = canvas.createPNGStream(); stream.pipe(out); + promises.push(new Promise(resolve => stream.on("end", resolve))); } // Generate left and right side belt @@ -82,7 +86,7 @@ async function run() { context.fillStyle = fillColor; context.strokeStyle = borderColor; - context.lineWidth = 3; + context.lineWidth = lineSize; context.beginPath(); context.moveTo(beltBorder, dimensions + 10); @@ -160,14 +164,43 @@ async function run() { flippedContext.scale(-1, 1); flippedContext.drawImage(canvas, -dimensions, 0, dimensions, dimensions); - const out = fs.createWriteStream(path.join(__dirname, "right_" + i + ".png")); - const stream = canvas.createPNGStream(); - stream.pipe(out); + const outRight = fs.createWriteStream(path.join(__dirname, "built", "right_" + i + ".png")); + const streamRight = canvas.createPNGStream(); + streamRight.pipe(outRight); - const outLeft = fs.createWriteStream(path.join(__dirname, "left_" + i + ".png")); + const outLeft = fs.createWriteStream(path.join(__dirname, "built", "left_" + i + ".png")); const streamLeft = flippedCanvas.createPNGStream(); streamLeft.pipe(outLeft); + + promises.push(new Promise(resolve => streamRight.on("end", resolve))); + promises.push(new Promise(resolve => streamLeft.on("end", resolve))); } + + console.log("Waiting for completion"); + await Promise.all(promises); + + // Also wait a bit more + await new Promise(resolve => setTimeout(resolve, 1000)); + + console.log("Copying files to all locations"); + + // Copy other files + fs.copyFileSync( + path.join(__dirname, "built", "forward_0.png"), + path.join(__dirname, "..", "buildings", "belt_top.png") + ); + + fs.copyFileSync( + path.join(__dirname, "built", "right_0.png"), + path.join(__dirname, "..", "buildings", "belt_right.png") + ); + + fs.copyFileSync( + path.join(__dirname, "built", "left_0.png"), + path.join(__dirname, "..", "buildings", "belt_left.png") + ); + + console.log("Done!"); } run(); diff --git a/res_raw/sprites/belt/generate_wire_sprites.js b/res_raw/sprites/belt/generate_wire_sprites.js new file mode 100644 index 00000000..24ac319b --- /dev/null +++ b/res_raw/sprites/belt/generate_wire_sprites.js @@ -0,0 +1,226 @@ +/** + * + * Run `yarn global add canvas` first + */ + +const { createCanvas } = require("canvas"); +const fs = require("fs"); +const path = require("path"); + +const outputFolder = path.join(__dirname, "..", "wires", "sets"); + +const dimensions = 192; +const lineSize = 12; +const lowerLineSize = 20; + +function hexToRGB(h) { + let r = 0, + g = 0, + b = 0; + + // 3 digits + if (h.length == 4) { + r = "0x" + h[1] + h[1]; + g = "0x" + h[2] + h[2]; + b = "0x" + h[3] + h[3]; + + // 6 digits + } else if (h.length == 7) { + r = "0x" + h[1] + h[2]; + g = "0x" + h[3] + h[4]; + b = "0x" + h[5] + h[6]; + } + + return [+r, +g, +b]; +} + +function RGBToHSL(r, g, b) { + // Make r, g, and b fractions of 1 + r /= 255; + g /= 255; + b /= 255; + + // Find greatest and smallest channel values + let cmin = Math.min(r, g, b), + cmax = Math.max(r, g, b), + delta = cmax - cmin, + h = 0, + s = 0, + l = 0; + // Calculate hue + // No difference + if (delta == 0) h = 0; + // Red is max + else if (cmax == r) h = ((g - b) / delta) % 6; + // Green is max + else if (cmax == g) h = (b - r) / delta + 2; + // Blue is max + else h = (r - g) / delta + 4; + + h = Math.round(h * 60); + + // Make negative hues positive behind 360° + if (h < 0) h += 360; + + // Calculate lightness + l = (cmax + cmin) / 2; + + // Calculate saturation + s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1)); + + // Multiply l and s by 100 + s = +(s * 100).toFixed(1); + l = +(l * 100).toFixed(1); + + return [h, s, l]; +} + +function HSLToRGB(h, s, l) { + // Must be fractions of 1 + s /= 100; + l /= 100; + + let c = (1 - Math.abs(2 * l - 1)) * s, + x = c * (1 - Math.abs(((h / 60) % 2) - 1)), + m = l - c / 2, + r = 0, + g = 0, + b = 0; + + if (0 <= h && h < 60) { + r = c; + g = x; + b = 0; + } else if (60 <= h && h < 120) { + r = x; + g = c; + b = 0; + } else if (120 <= h && h < 180) { + r = 0; + g = c; + b = x; + } else if (180 <= h && h < 240) { + r = 0; + g = x; + b = c; + } else if (240 <= h && h < 300) { + r = x; + g = 0; + b = c; + } else if (300 <= h && h < 360) { + r = c; + g = 0; + b = x; + } + r = Math.round((r + m) * 255); + g = Math.round((g + m) * 255); + b = Math.round((b + m) * 255); + + return [r, g, b]; +} + +async function run() { + console.log("Running"); + + const variants = { + regular: "#25fff2", + color: "#eba458", + shape: "#8858eb", + conflict: "#ff3e3e", + }; + + const promises = []; + + for (const variantId in variants) { + const variantColor = variants[variantId]; + const variantHSL = RGBToHSL(...hexToRGB(variantColor)); + const darkenedColor = HSLToRGB(variantHSL[0], variantHSL[1] - 15, variantHSL[2] - 20); + const hexDarkenedColor = "rgb(" + darkenedColor.join(",") + ")"; + + console.log(variantColor, "->", hexToRGB(variantColor), variantHSL, "->", darkenedColor); + + const parts = { + forward: [[0.5, 0, 0.5, 1]], + turn: [ + [0.5, 0.5, 0.5, 1], + [0.5, 0.5, 1, 0.5], + ], + split: [ + [0.5, 0.5, 0.5, 1], + [0, 0.5, 1, 0.5], + ], + cross: [ + [0, 0.5, 1, 0.5], + [0.5, 0, 0.5, 1], + ], + }; + + for (const partId in parts) { + const partLines = parts[partId]; + + const canvas = createCanvas(dimensions, dimensions); + const context = canvas.getContext("2d"); + context.quality = "best"; + context.clearRect(0, 0, dimensions, dimensions); + + context.strokeStyle = hexDarkenedColor; + context.lineWidth = lowerLineSize; + context.lineCap = "square"; + context.imageSmoothingEnabled = false; + + // Draw lower lines + partLines.forEach(([x1, y1, x2, y2]) => { + context.beginPath(); + context.moveTo(x1 * dimensions, y1 * dimensions); + context.lineTo(x2 * dimensions, y2 * dimensions); + context.stroke(); + }); + + context.strokeStyle = variantColor; + context.lineWidth = lineSize; + + // Draw upper lines + partLines.forEach(([x1, y1, x2, y2]) => { + context.beginPath(); + context.moveTo(x1 * dimensions, y1 * dimensions); + context.lineTo(x2 * dimensions, y2 * dimensions); + context.stroke(); + }); + + const out = fs.createWriteStream(path.join(outputFolder, variantId + "_" + partId + ".png")); + const stream = canvas.createPNGStream(); + stream.pipe(out); + promises.push(new Promise(resolve => stream.on("end", resolve))); + } + } + + console.log("Waiting for completion"); + await Promise.all(promises); + + // Also wait a bit more + await new Promise(resolve => setTimeout(resolve, 1000)); + + console.log("Copying files to all locations"); + + // // Copy other files + fs.copyFileSync( + path.join(outputFolder, "regular_forward.png"), + path.join(__dirname, "..", "buildings", "wire.png") + ); + fs.copyFileSync( + path.join(outputFolder, "regular_turn.png"), + path.join(__dirname, "..", "buildings", "wire-turn.png") + ); + fs.copyFileSync( + path.join(outputFolder, "regular_split.png"), + path.join(__dirname, "..", "buildings", "wire-split.png") + ); + fs.copyFileSync( + path.join(outputFolder, "regular_cross.png"), + path.join(__dirname, "..", "buildings", "wire-cross.png") + ); + + console.log("Done!"); +} + +run(); diff --git a/res_raw/sprites/belt/left_0.png b/res_raw/sprites/belt/left_0.png deleted file mode 100644 index 7da4c390..00000000 Binary files a/res_raw/sprites/belt/left_0.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_1.png b/res_raw/sprites/belt/left_1.png deleted file mode 100644 index fa446ce4..00000000 Binary files a/res_raw/sprites/belt/left_1.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_10.png b/res_raw/sprites/belt/left_10.png deleted file mode 100644 index 260a4c23..00000000 Binary files a/res_raw/sprites/belt/left_10.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_11.png b/res_raw/sprites/belt/left_11.png deleted file mode 100644 index d0d70ab1..00000000 Binary files a/res_raw/sprites/belt/left_11.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_12.png b/res_raw/sprites/belt/left_12.png deleted file mode 100644 index 3f916501..00000000 Binary files a/res_raw/sprites/belt/left_12.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_13.png b/res_raw/sprites/belt/left_13.png deleted file mode 100644 index 71d9a634..00000000 Binary files a/res_raw/sprites/belt/left_13.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_14.png b/res_raw/sprites/belt/left_14.png deleted file mode 100644 index 134b90af..00000000 Binary files a/res_raw/sprites/belt/left_14.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_15.png b/res_raw/sprites/belt/left_15.png deleted file mode 100644 index 623069a1..00000000 Binary files a/res_raw/sprites/belt/left_15.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_16.png b/res_raw/sprites/belt/left_16.png deleted file mode 100644 index 14b18b45..00000000 Binary files a/res_raw/sprites/belt/left_16.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_17.png b/res_raw/sprites/belt/left_17.png deleted file mode 100644 index 5aa84e5c..00000000 Binary files a/res_raw/sprites/belt/left_17.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_18.png b/res_raw/sprites/belt/left_18.png deleted file mode 100644 index 0fe1dedd..00000000 Binary files a/res_raw/sprites/belt/left_18.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_19.png b/res_raw/sprites/belt/left_19.png deleted file mode 100644 index 46e1b2b3..00000000 Binary files a/res_raw/sprites/belt/left_19.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_2.png b/res_raw/sprites/belt/left_2.png deleted file mode 100644 index 9a8d15c0..00000000 Binary files a/res_raw/sprites/belt/left_2.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_20.png b/res_raw/sprites/belt/left_20.png deleted file mode 100644 index 1d6dd020..00000000 Binary files a/res_raw/sprites/belt/left_20.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_21.png b/res_raw/sprites/belt/left_21.png deleted file mode 100644 index 413afb3c..00000000 Binary files a/res_raw/sprites/belt/left_21.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_22.png b/res_raw/sprites/belt/left_22.png deleted file mode 100644 index c56c9607..00000000 Binary files a/res_raw/sprites/belt/left_22.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_23.png b/res_raw/sprites/belt/left_23.png deleted file mode 100644 index 22c7e9d1..00000000 Binary files a/res_raw/sprites/belt/left_23.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_24.png b/res_raw/sprites/belt/left_24.png deleted file mode 100644 index 1c15838a..00000000 Binary files a/res_raw/sprites/belt/left_24.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_25.png b/res_raw/sprites/belt/left_25.png deleted file mode 100644 index 20120842..00000000 Binary files a/res_raw/sprites/belt/left_25.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_26.png b/res_raw/sprites/belt/left_26.png deleted file mode 100644 index 1d4de05f..00000000 Binary files a/res_raw/sprites/belt/left_26.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_27.png b/res_raw/sprites/belt/left_27.png deleted file mode 100644 index ba0d699a..00000000 Binary files a/res_raw/sprites/belt/left_27.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_3.png b/res_raw/sprites/belt/left_3.png deleted file mode 100644 index 7fc8c6fc..00000000 Binary files a/res_raw/sprites/belt/left_3.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_4.png b/res_raw/sprites/belt/left_4.png deleted file mode 100644 index e8da79fd..00000000 Binary files a/res_raw/sprites/belt/left_4.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_5.png b/res_raw/sprites/belt/left_5.png deleted file mode 100644 index 1a26dc72..00000000 Binary files a/res_raw/sprites/belt/left_5.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_6.png b/res_raw/sprites/belt/left_6.png deleted file mode 100644 index c2322d45..00000000 Binary files a/res_raw/sprites/belt/left_6.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_7.png b/res_raw/sprites/belt/left_7.png deleted file mode 100644 index a85a31fc..00000000 Binary files a/res_raw/sprites/belt/left_7.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_8.png b/res_raw/sprites/belt/left_8.png deleted file mode 100644 index 9ff9945b..00000000 Binary files a/res_raw/sprites/belt/left_8.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_9.png b/res_raw/sprites/belt/left_9.png deleted file mode 100644 index bfe4360e..00000000 Binary files a/res_raw/sprites/belt/left_9.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_0.png b/res_raw/sprites/belt/right_0.png deleted file mode 100644 index fca35eab..00000000 Binary files a/res_raw/sprites/belt/right_0.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_1.png b/res_raw/sprites/belt/right_1.png deleted file mode 100644 index 101578e9..00000000 Binary files a/res_raw/sprites/belt/right_1.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_10.png b/res_raw/sprites/belt/right_10.png deleted file mode 100644 index cd733017..00000000 Binary files a/res_raw/sprites/belt/right_10.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_11.png b/res_raw/sprites/belt/right_11.png deleted file mode 100644 index 5d082ecc..00000000 Binary files a/res_raw/sprites/belt/right_11.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_12.png b/res_raw/sprites/belt/right_12.png deleted file mode 100644 index 3c7f08bb..00000000 Binary files a/res_raw/sprites/belt/right_12.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_13.png b/res_raw/sprites/belt/right_13.png deleted file mode 100644 index 71364d48..00000000 Binary files a/res_raw/sprites/belt/right_13.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_14.png b/res_raw/sprites/belt/right_14.png deleted file mode 100644 index cf5df0a4..00000000 Binary files a/res_raw/sprites/belt/right_14.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_15.png b/res_raw/sprites/belt/right_15.png deleted file mode 100644 index 1292ec67..00000000 Binary files a/res_raw/sprites/belt/right_15.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_16.png b/res_raw/sprites/belt/right_16.png deleted file mode 100644 index 4dcc2c5f..00000000 Binary files a/res_raw/sprites/belt/right_16.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_17.png b/res_raw/sprites/belt/right_17.png deleted file mode 100644 index 489f0e54..00000000 Binary files a/res_raw/sprites/belt/right_17.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_18.png b/res_raw/sprites/belt/right_18.png deleted file mode 100644 index 208f402b..00000000 Binary files a/res_raw/sprites/belt/right_18.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_19.png b/res_raw/sprites/belt/right_19.png deleted file mode 100644 index 5e4e376b..00000000 Binary files a/res_raw/sprites/belt/right_19.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_2.png b/res_raw/sprites/belt/right_2.png deleted file mode 100644 index c9affce1..00000000 Binary files a/res_raw/sprites/belt/right_2.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_20.png b/res_raw/sprites/belt/right_20.png deleted file mode 100644 index 77a4f43b..00000000 Binary files a/res_raw/sprites/belt/right_20.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_21.png b/res_raw/sprites/belt/right_21.png deleted file mode 100644 index ca1d0f5f..00000000 Binary files a/res_raw/sprites/belt/right_21.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_22.png b/res_raw/sprites/belt/right_22.png deleted file mode 100644 index d07bf72d..00000000 Binary files a/res_raw/sprites/belt/right_22.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_23.png b/res_raw/sprites/belt/right_23.png deleted file mode 100644 index babfca3f..00000000 Binary files a/res_raw/sprites/belt/right_23.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_24.png b/res_raw/sprites/belt/right_24.png deleted file mode 100644 index 1c614c85..00000000 Binary files a/res_raw/sprites/belt/right_24.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_25.png b/res_raw/sprites/belt/right_25.png deleted file mode 100644 index d72a8615..00000000 Binary files a/res_raw/sprites/belt/right_25.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_26.png b/res_raw/sprites/belt/right_26.png deleted file mode 100644 index ed37636f..00000000 Binary files a/res_raw/sprites/belt/right_26.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_27.png b/res_raw/sprites/belt/right_27.png deleted file mode 100644 index fe9ffc10..00000000 Binary files a/res_raw/sprites/belt/right_27.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_3.png b/res_raw/sprites/belt/right_3.png deleted file mode 100644 index feb7101b..00000000 Binary files a/res_raw/sprites/belt/right_3.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_4.png b/res_raw/sprites/belt/right_4.png deleted file mode 100644 index 22c885a6..00000000 Binary files a/res_raw/sprites/belt/right_4.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_5.png b/res_raw/sprites/belt/right_5.png deleted file mode 100644 index 27bb27aa..00000000 Binary files a/res_raw/sprites/belt/right_5.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_6.png b/res_raw/sprites/belt/right_6.png deleted file mode 100644 index 5ca871b7..00000000 Binary files a/res_raw/sprites/belt/right_6.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_7.png b/res_raw/sprites/belt/right_7.png deleted file mode 100644 index a9cde450..00000000 Binary files a/res_raw/sprites/belt/right_7.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_8.png b/res_raw/sprites/belt/right_8.png deleted file mode 100644 index f09195fe..00000000 Binary files a/res_raw/sprites/belt/right_8.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_9.png b/res_raw/sprites/belt/right_9.png deleted file mode 100644 index b6ca38c1..00000000 Binary files a/res_raw/sprites/belt/right_9.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/advanced_processor.png b/res_raw/sprites/blueprints/advanced_processor.png deleted file mode 100644 index ab385816..00000000 Binary files a/res_raw/sprites/blueprints/advanced_processor.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/belt_left.png b/res_raw/sprites/blueprints/belt_left.png index 594bb203..2046637c 100644 Binary files a/res_raw/sprites/blueprints/belt_left.png and b/res_raw/sprites/blueprints/belt_left.png differ diff --git a/res_raw/sprites/blueprints/belt_right.png b/res_raw/sprites/blueprints/belt_right.png index 9c33404b..48629eaa 100644 Binary files a/res_raw/sprites/blueprints/belt_right.png and b/res_raw/sprites/blueprints/belt_right.png differ diff --git a/res_raw/sprites/blueprints/belt_top.png b/res_raw/sprites/blueprints/belt_top.png index 881c443a..88d7917b 100644 Binary files a/res_raw/sprites/blueprints/belt_top.png and b/res_raw/sprites/blueprints/belt_top.png differ diff --git a/res_raw/sprites/blueprints/constant_signal.png b/res_raw/sprites/blueprints/constant_signal.png new file mode 100644 index 00000000..9acb86d2 Binary files /dev/null and b/res_raw/sprites/blueprints/constant_signal.png differ diff --git a/res_raw/sprites/blueprints/display.png b/res_raw/sprites/blueprints/display.png new file mode 100644 index 00000000..bb0319f2 Binary files /dev/null and b/res_raw/sprites/blueprints/display.png differ diff --git a/res_raw/sprites/blueprints/energy_generator.png b/res_raw/sprites/blueprints/energy_generator.png deleted file mode 100644 index 42258c63..00000000 Binary files a/res_raw/sprites/blueprints/energy_generator.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/filter.png b/res_raw/sprites/blueprints/filter.png new file mode 100644 index 00000000..dd791666 Binary files /dev/null and b/res_raw/sprites/blueprints/filter.png differ diff --git a/res_raw/sprites/blueprints/lever.png b/res_raw/sprites/blueprints/lever.png new file mode 100644 index 00000000..84ef5f03 Binary files /dev/null and b/res_raw/sprites/blueprints/lever.png differ diff --git a/res_raw/sprites/blueprints/logic_gate-not.png b/res_raw/sprites/blueprints/logic_gate-not.png new file mode 100644 index 00000000..a45b6ce5 Binary files /dev/null and b/res_raw/sprites/blueprints/logic_gate-not.png differ diff --git a/res_raw/sprites/blueprints/logic_gate-or.png b/res_raw/sprites/blueprints/logic_gate-or.png new file mode 100644 index 00000000..f58c3656 Binary files /dev/null and b/res_raw/sprites/blueprints/logic_gate-or.png differ diff --git a/res_raw/sprites/blueprints/logic_gate-transistor.png b/res_raw/sprites/blueprints/logic_gate-transistor.png new file mode 100644 index 00000000..c3d3682d Binary files /dev/null and b/res_raw/sprites/blueprints/logic_gate-transistor.png differ diff --git a/res_raw/sprites/blueprints/logic_gate-xor.png b/res_raw/sprites/blueprints/logic_gate-xor.png new file mode 100644 index 00000000..97823a7a Binary files /dev/null and b/res_raw/sprites/blueprints/logic_gate-xor.png differ diff --git a/res_raw/sprites/blueprints/logic_gate.png b/res_raw/sprites/blueprints/logic_gate.png new file mode 100644 index 00000000..de59fa57 Binary files /dev/null and b/res_raw/sprites/blueprints/logic_gate.png differ diff --git a/res_raw/sprites/blueprints/painter-quad.png b/res_raw/sprites/blueprints/painter-quad.png index c3c755f2..6f8ce2a0 100644 Binary files a/res_raw/sprites/blueprints/painter-quad.png and b/res_raw/sprites/blueprints/painter-quad.png differ diff --git a/res_raw/sprites/blueprints/reader.png b/res_raw/sprites/blueprints/reader.png new file mode 100644 index 00000000..dc2f5bfa Binary files /dev/null and b/res_raw/sprites/blueprints/reader.png differ diff --git a/res_raw/sprites/blueprints/rotater-fl.png b/res_raw/sprites/blueprints/rotater-fl.png new file mode 100644 index 00000000..25a66453 Binary files /dev/null and b/res_raw/sprites/blueprints/rotater-fl.png differ diff --git a/res_raw/sprites/blueprints/splitter-compact-merge-inverse.png b/res_raw/sprites/blueprints/splitter-compact-merge-inverse.png new file mode 100644 index 00000000..90a429c0 Binary files /dev/null and b/res_raw/sprites/blueprints/splitter-compact-merge-inverse.png differ diff --git a/res_raw/sprites/blueprints/splitter-compact-merge.png b/res_raw/sprites/blueprints/splitter-compact-merge.png new file mode 100644 index 00000000..93488fd9 Binary files /dev/null and b/res_raw/sprites/blueprints/splitter-compact-merge.png differ diff --git a/res_raw/sprites/blueprints/trash-storage.png b/res_raw/sprites/blueprints/trash-storage.png index a4e6122f..cc719a5a 100644 Binary files a/res_raw/sprites/blueprints/trash-storage.png and b/res_raw/sprites/blueprints/trash-storage.png differ diff --git a/res_raw/sprites/blueprints/virtual_processor-analyzer.png b/res_raw/sprites/blueprints/virtual_processor-analyzer.png new file mode 100644 index 00000000..9aa5d298 Binary files /dev/null and b/res_raw/sprites/blueprints/virtual_processor-analyzer.png differ diff --git a/res_raw/sprites/blueprints/virtual_processor-rotater.png b/res_raw/sprites/blueprints/virtual_processor-rotater.png new file mode 100644 index 00000000..d50da022 Binary files /dev/null and b/res_raw/sprites/blueprints/virtual_processor-rotater.png differ diff --git a/res_raw/sprites/blueprints/virtual_processor-shapecompare.png b/res_raw/sprites/blueprints/virtual_processor-shapecompare.png new file mode 100644 index 00000000..6fe8abfb Binary files /dev/null and b/res_raw/sprites/blueprints/virtual_processor-shapecompare.png differ diff --git a/res_raw/sprites/blueprints/virtual_processor-stacker.png b/res_raw/sprites/blueprints/virtual_processor-stacker.png new file mode 100644 index 00000000..1d691491 Binary files /dev/null and b/res_raw/sprites/blueprints/virtual_processor-stacker.png differ diff --git a/res_raw/sprites/blueprints/virtual_processor-unstacker.png b/res_raw/sprites/blueprints/virtual_processor-unstacker.png new file mode 100644 index 00000000..a9ce56dd Binary files /dev/null and b/res_raw/sprites/blueprints/virtual_processor-unstacker.png differ diff --git a/res_raw/sprites/blueprints/virtual_processor.png b/res_raw/sprites/blueprints/virtual_processor.png new file mode 100644 index 00000000..230c4a23 Binary files /dev/null and b/res_raw/sprites/blueprints/virtual_processor.png differ diff --git a/res_raw/sprites/blueprints/wire-cross.png b/res_raw/sprites/blueprints/wire-cross.png new file mode 100644 index 00000000..c9aeb1c5 Binary files /dev/null and b/res_raw/sprites/blueprints/wire-cross.png differ diff --git a/res_raw/sprites/blueprints/wire-split.png b/res_raw/sprites/blueprints/wire-split.png new file mode 100644 index 00000000..f0cdfb11 Binary files /dev/null and b/res_raw/sprites/blueprints/wire-split.png differ diff --git a/res_raw/sprites/blueprints/wire-turn.png b/res_raw/sprites/blueprints/wire-turn.png new file mode 100644 index 00000000..becf6411 Binary files /dev/null and b/res_raw/sprites/blueprints/wire-turn.png differ diff --git a/res_raw/sprites/blueprints/wire.png b/res_raw/sprites/blueprints/wire.png new file mode 100644 index 00000000..15bfde22 Binary files /dev/null and b/res_raw/sprites/blueprints/wire.png differ diff --git a/res_raw/sprites/blueprints/wire_crossings-merger.png b/res_raw/sprites/blueprints/wire_crossings-merger.png deleted file mode 100644 index 82d9862c..00000000 Binary files a/res_raw/sprites/blueprints/wire_crossings-merger.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/wire_crossings.png b/res_raw/sprites/blueprints/wire_crossings.png deleted file mode 100644 index 113af179..00000000 Binary files a/res_raw/sprites/blueprints/wire_crossings.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/wire_left.png b/res_raw/sprites/blueprints/wire_left.png deleted file mode 100644 index 232c13e9..00000000 Binary files a/res_raw/sprites/blueprints/wire_left.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/wire_right.png b/res_raw/sprites/blueprints/wire_right.png deleted file mode 100644 index fba98482..00000000 Binary files a/res_raw/sprites/blueprints/wire_right.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/wire_top.png b/res_raw/sprites/blueprints/wire_top.png deleted file mode 100644 index 52efcc01..00000000 Binary files a/res_raw/sprites/blueprints/wire_top.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/wire_tunnel-coating.png b/res_raw/sprites/blueprints/wire_tunnel-coating.png new file mode 100644 index 00000000..af93022a Binary files /dev/null and b/res_raw/sprites/blueprints/wire_tunnel-coating.png differ diff --git a/res_raw/sprites/blueprints/wire_tunnel.png b/res_raw/sprites/blueprints/wire_tunnel.png new file mode 100644 index 00000000..9a7cdd2a Binary files /dev/null and b/res_raw/sprites/blueprints/wire_tunnel.png differ diff --git a/res_raw/sprites/buildings/advanced_processor.png b/res_raw/sprites/buildings/advanced_processor.png deleted file mode 100644 index 5402760b..00000000 Binary files a/res_raw/sprites/buildings/advanced_processor.png and /dev/null differ diff --git a/res_raw/sprites/buildings/belt_left.png b/res_raw/sprites/buildings/belt_left.png index 60bebd29..8575be67 100644 Binary files a/res_raw/sprites/buildings/belt_left.png and b/res_raw/sprites/buildings/belt_left.png differ diff --git a/res_raw/sprites/buildings/belt_right.png b/res_raw/sprites/buildings/belt_right.png index 547387b4..51cb8c7c 100644 Binary files a/res_raw/sprites/buildings/belt_right.png and b/res_raw/sprites/buildings/belt_right.png differ diff --git a/res_raw/sprites/buildings/belt_top.png b/res_raw/sprites/buildings/belt_top.png index cf5b20d7..67b47330 100644 Binary files a/res_raw/sprites/buildings/belt_top.png and b/res_raw/sprites/buildings/belt_top.png differ diff --git a/res_raw/sprites/buildings/constant_signal.png b/res_raw/sprites/buildings/constant_signal.png new file mode 100644 index 00000000..ae9329e0 Binary files /dev/null and b/res_raw/sprites/buildings/constant_signal.png differ diff --git a/res_raw/sprites/buildings/display.png b/res_raw/sprites/buildings/display.png new file mode 100644 index 00000000..ec7b95d9 Binary files /dev/null and b/res_raw/sprites/buildings/display.png differ diff --git a/res_raw/sprites/buildings/energy_generator.png b/res_raw/sprites/buildings/energy_generator.png deleted file mode 100644 index 5bd9f9a2..00000000 Binary files a/res_raw/sprites/buildings/energy_generator.png and /dev/null differ diff --git a/res_raw/sprites/buildings/filter.png b/res_raw/sprites/buildings/filter.png new file mode 100644 index 00000000..95b749c7 Binary files /dev/null and b/res_raw/sprites/buildings/filter.png differ diff --git a/res_raw/sprites/buildings/hub.png b/res_raw/sprites/buildings/hub.png index 8fdd5305..68283f09 100644 Binary files a/res_raw/sprites/buildings/hub.png and b/res_raw/sprites/buildings/hub.png differ diff --git a/res_raw/sprites/buildings/lever.png b/res_raw/sprites/buildings/lever.png new file mode 100644 index 00000000..bdb6c8c8 Binary files /dev/null and b/res_raw/sprites/buildings/lever.png differ diff --git a/res_raw/sprites/buildings/logic_gate-not.png b/res_raw/sprites/buildings/logic_gate-not.png new file mode 100644 index 00000000..b5e8246c Binary files /dev/null and b/res_raw/sprites/buildings/logic_gate-not.png differ diff --git a/res_raw/sprites/buildings/logic_gate-or.png b/res_raw/sprites/buildings/logic_gate-or.png new file mode 100644 index 00000000..1b9c9e34 Binary files /dev/null and b/res_raw/sprites/buildings/logic_gate-or.png differ diff --git a/res_raw/sprites/buildings/logic_gate-transistor.png b/res_raw/sprites/buildings/logic_gate-transistor.png new file mode 100644 index 00000000..35952db4 Binary files /dev/null and b/res_raw/sprites/buildings/logic_gate-transistor.png differ diff --git a/res_raw/sprites/buildings/logic_gate-xor.png b/res_raw/sprites/buildings/logic_gate-xor.png new file mode 100644 index 00000000..c7d43a58 Binary files /dev/null and b/res_raw/sprites/buildings/logic_gate-xor.png differ diff --git a/res_raw/sprites/buildings/logic_gate.png b/res_raw/sprites/buildings/logic_gate.png new file mode 100644 index 00000000..2d206aa3 Binary files /dev/null and b/res_raw/sprites/buildings/logic_gate.png differ diff --git a/res_raw/sprites/buildings/painter-quad.png b/res_raw/sprites/buildings/painter-quad.png index 18790a78..d14bd382 100644 Binary files a/res_raw/sprites/buildings/painter-quad.png and b/res_raw/sprites/buildings/painter-quad.png differ diff --git a/res_raw/sprites/buildings/reader.png b/res_raw/sprites/buildings/reader.png new file mode 100644 index 00000000..f03f4405 Binary files /dev/null and b/res_raw/sprites/buildings/reader.png differ diff --git a/res_raw/sprites/buildings/rotater-fl.png b/res_raw/sprites/buildings/rotater-fl.png new file mode 100644 index 00000000..7c2fbc16 Binary files /dev/null and b/res_raw/sprites/buildings/rotater-fl.png differ diff --git a/res_raw/sprites/buildings/splitter-compact-merge-inverse.png b/res_raw/sprites/buildings/splitter-compact-merge-inverse.png new file mode 100644 index 00000000..704663c0 Binary files /dev/null and b/res_raw/sprites/buildings/splitter-compact-merge-inverse.png differ diff --git a/res_raw/sprites/buildings/splitter-compact-merge.png b/res_raw/sprites/buildings/splitter-compact-merge.png new file mode 100644 index 00000000..d5a72dd4 Binary files /dev/null and b/res_raw/sprites/buildings/splitter-compact-merge.png differ diff --git a/res_raw/sprites/buildings/trash-storage.png b/res_raw/sprites/buildings/trash-storage.png index 57b1519e..39a4df1f 100644 Binary files a/res_raw/sprites/buildings/trash-storage.png and b/res_raw/sprites/buildings/trash-storage.png differ diff --git a/res_raw/sprites/buildings/virtual_processor-analyzer.png b/res_raw/sprites/buildings/virtual_processor-analyzer.png new file mode 100644 index 00000000..f30c8d3b Binary files /dev/null and b/res_raw/sprites/buildings/virtual_processor-analyzer.png differ diff --git a/res_raw/sprites/buildings/virtual_processor-rotater.png b/res_raw/sprites/buildings/virtual_processor-rotater.png new file mode 100644 index 00000000..8c9dcbdc Binary files /dev/null and b/res_raw/sprites/buildings/virtual_processor-rotater.png differ diff --git a/res_raw/sprites/buildings/virtual_processor-shapecompare.png b/res_raw/sprites/buildings/virtual_processor-shapecompare.png new file mode 100644 index 00000000..dad1e4bf Binary files /dev/null and b/res_raw/sprites/buildings/virtual_processor-shapecompare.png differ diff --git a/res_raw/sprites/buildings/virtual_processor-stacker.png b/res_raw/sprites/buildings/virtual_processor-stacker.png new file mode 100644 index 00000000..15882e63 Binary files /dev/null and b/res_raw/sprites/buildings/virtual_processor-stacker.png differ diff --git a/res_raw/sprites/buildings/virtual_processor-unstacker.png b/res_raw/sprites/buildings/virtual_processor-unstacker.png new file mode 100644 index 00000000..a51edf6d Binary files /dev/null and b/res_raw/sprites/buildings/virtual_processor-unstacker.png differ diff --git a/res_raw/sprites/buildings/virtual_processor.png b/res_raw/sprites/buildings/virtual_processor.png new file mode 100644 index 00000000..87093df4 Binary files /dev/null and b/res_raw/sprites/buildings/virtual_processor.png differ diff --git a/res_raw/sprites/buildings/wire-cross.png b/res_raw/sprites/buildings/wire-cross.png new file mode 100644 index 00000000..e9c71dac Binary files /dev/null and b/res_raw/sprites/buildings/wire-cross.png differ diff --git a/res_raw/sprites/buildings/wire-split.png b/res_raw/sprites/buildings/wire-split.png new file mode 100644 index 00000000..e26b552c Binary files /dev/null and b/res_raw/sprites/buildings/wire-split.png differ diff --git a/res_raw/sprites/buildings/wire-turn.png b/res_raw/sprites/buildings/wire-turn.png new file mode 100644 index 00000000..5b50bb09 Binary files /dev/null and b/res_raw/sprites/buildings/wire-turn.png differ diff --git a/res_raw/sprites/buildings/wire.png b/res_raw/sprites/buildings/wire.png new file mode 100644 index 00000000..8310be84 Binary files /dev/null and b/res_raw/sprites/buildings/wire.png differ diff --git a/res_raw/sprites/buildings/wire_crossings-merger.png b/res_raw/sprites/buildings/wire_crossings-merger.png deleted file mode 100644 index 42cef3f8..00000000 Binary files a/res_raw/sprites/buildings/wire_crossings-merger.png and /dev/null differ diff --git a/res_raw/sprites/buildings/wire_crossings.png b/res_raw/sprites/buildings/wire_crossings.png deleted file mode 100644 index 814349ba..00000000 Binary files a/res_raw/sprites/buildings/wire_crossings.png and /dev/null differ diff --git a/res_raw/sprites/buildings/wire_left.png b/res_raw/sprites/buildings/wire_left.png deleted file mode 100644 index 5799ab5b..00000000 Binary files a/res_raw/sprites/buildings/wire_left.png and /dev/null differ diff --git a/res_raw/sprites/buildings/wire_right.png b/res_raw/sprites/buildings/wire_right.png deleted file mode 100644 index b3f2df5a..00000000 Binary files a/res_raw/sprites/buildings/wire_right.png and /dev/null differ diff --git a/res_raw/sprites/buildings/wire_top.png b/res_raw/sprites/buildings/wire_top.png deleted file mode 100644 index a9f90aaa..00000000 Binary files a/res_raw/sprites/buildings/wire_top.png and /dev/null differ diff --git a/res_raw/sprites/buildings/wire_tunnel-coating.png b/res_raw/sprites/buildings/wire_tunnel-coating.png new file mode 100644 index 00000000..f5dd3ffe Binary files /dev/null and b/res_raw/sprites/buildings/wire_tunnel-coating.png differ diff --git a/res_raw/sprites/buildings/wire_tunnel.png b/res_raw/sprites/buildings/wire_tunnel.png new file mode 100644 index 00000000..8349e981 Binary files /dev/null and b/res_raw/sprites/buildings/wire_tunnel.png differ diff --git a/res_raw/sprites/debug/acceptor_slot.png b/res_raw/sprites/debug/acceptor_slot.png index 4ab91b5b..7d2f697e 100644 Binary files a/res_raw/sprites/debug/acceptor_slot.png and b/res_raw/sprites/debug/acceptor_slot.png differ diff --git a/res_raw/sprites/debug/ejector_slot.png b/res_raw/sprites/debug/ejector_slot.png index a1736a79..0b3f8fed 100644 Binary files a/res_raw/sprites/debug/ejector_slot.png and b/res_raw/sprites/debug/ejector_slot.png differ diff --git a/res_raw/sprites/map_overview/belt_forward.png b/res_raw/sprites/map_overview/belt_forward.png deleted file mode 100644 index e7fb900c..00000000 Binary files a/res_raw/sprites/map_overview/belt_forward.png and /dev/null differ diff --git a/res_raw/sprites/map_overview/belt_left.png b/res_raw/sprites/map_overview/belt_left.png deleted file mode 100644 index 9279c743..00000000 Binary files a/res_raw/sprites/map_overview/belt_left.png and /dev/null differ diff --git a/res_raw/sprites/map_overview/belt_right.png b/res_raw/sprites/map_overview/belt_right.png deleted file mode 100644 index 1f897cf5..00000000 Binary files a/res_raw/sprites/map_overview/belt_right.png and /dev/null differ diff --git a/res_raw/sprites/misc/deletion_marker.png b/res_raw/sprites/misc/deletion_marker.png deleted file mode 100644 index bb3a2b75..00000000 Binary files a/res_raw/sprites/misc/deletion_marker.png and /dev/null differ diff --git a/res_raw/sprites/misc/energy_generator_overlay.png b/res_raw/sprites/misc/energy_generator_overlay.png deleted file mode 100644 index 634c2e10..00000000 Binary files a/res_raw/sprites/misc/energy_generator_overlay.png and /dev/null differ diff --git a/res_raw/sprites/misc/hub_direction_indicator.png b/res_raw/sprites/misc/hub_direction_indicator.png index 006ba8fa..40414cc1 100644 Binary files a/res_raw/sprites/misc/hub_direction_indicator.png and b/res_raw/sprites/misc/hub_direction_indicator.png differ diff --git a/res_raw/sprites/misc/lock_direction_indicator.png b/res_raw/sprites/misc/lock_direction_indicator.png deleted file mode 100644 index fe693ba2..00000000 Binary files a/res_raw/sprites/misc/lock_direction_indicator.png and /dev/null differ diff --git a/res_raw/sprites/misc/processor_disabled.png b/res_raw/sprites/misc/processor_disabled.png new file mode 100644 index 00000000..37dfe32b Binary files /dev/null and b/res_raw/sprites/misc/processor_disabled.png differ diff --git a/res_raw/sprites/misc/processor_disconnected.png b/res_raw/sprites/misc/processor_disconnected.png new file mode 100644 index 00000000..eb99ca65 Binary files /dev/null and b/res_raw/sprites/misc/processor_disconnected.png differ diff --git a/res_raw/sprites/misc/reader_overlay.png b/res_raw/sprites/misc/reader_overlay.png new file mode 100644 index 00000000..c9fcb573 Binary files /dev/null and b/res_raw/sprites/misc/reader_overlay.png differ diff --git a/res_raw/sprites/misc/slot_bad_arrow.png b/res_raw/sprites/misc/slot_bad_arrow.png index 27c938ac..fe5c5d3b 100644 Binary files a/res_raw/sprites/misc/slot_bad_arrow.png and b/res_raw/sprites/misc/slot_bad_arrow.png differ diff --git a/res_raw/sprites/misc/slot_good_arrow.png b/res_raw/sprites/misc/slot_good_arrow.png index 3001e8b4..ffe9bbb4 100644 Binary files a/res_raw/sprites/misc/slot_good_arrow.png and b/res_raw/sprites/misc/slot_good_arrow.png differ diff --git a/res_raw/sprites/misc/storage_overlay.png b/res_raw/sprites/misc/storage_overlay.png index 92b2ecf8..cad98032 100644 Binary files a/res_raw/sprites/misc/storage_overlay.png and b/res_raw/sprites/misc/storage_overlay.png differ diff --git a/res_raw/sprites/misc/waypoint.png b/res_raw/sprites/misc/waypoint.png index 105f7cd5..889fb707 100644 Binary files a/res_raw/sprites/misc/waypoint.png and b/res_raw/sprites/misc/waypoint.png differ diff --git a/res_raw/sprites/misc/wires_overlay_tile.png b/res_raw/sprites/misc/wires_overlay_tile.png deleted file mode 100644 index b8ec3480..00000000 Binary files a/res_raw/sprites/misc/wires_overlay_tile.png and /dev/null differ diff --git a/res_raw/sprites/wires/battery_empty.png b/res_raw/sprites/wires/battery_empty.png deleted file mode 100644 index 78095666..00000000 Binary files a/res_raw/sprites/wires/battery_empty.png and /dev/null differ diff --git a/res_raw/sprites/wires/battery_full.png b/res_raw/sprites/wires/battery_full.png deleted file mode 100644 index 5256150f..00000000 Binary files a/res_raw/sprites/wires/battery_full.png and /dev/null differ diff --git a/res_raw/sprites/wires/battery_low.png b/res_raw/sprites/wires/battery_low.png deleted file mode 100644 index 79fbd8a4..00000000 Binary files a/res_raw/sprites/wires/battery_low.png and /dev/null differ diff --git a/res_raw/sprites/wires/battery_medium.png b/res_raw/sprites/wires/battery_medium.png deleted file mode 100644 index ba0151a0..00000000 Binary files a/res_raw/sprites/wires/battery_medium.png and /dev/null differ diff --git a/res_raw/sprites/wires/boolean_false.png b/res_raw/sprites/wires/boolean_false.png new file mode 100644 index 00000000..757b6cd9 Binary files /dev/null and b/res_raw/sprites/wires/boolean_false.png differ diff --git a/res_raw/sprites/wires/boolean_true.png b/res_raw/sprites/wires/boolean_true.png new file mode 100644 index 00000000..f63bae3f Binary files /dev/null and b/res_raw/sprites/wires/boolean_true.png differ diff --git a/res_raw/sprites/wires/display/blue.png b/res_raw/sprites/wires/display/blue.png new file mode 100644 index 00000000..c131ed84 Binary files /dev/null and b/res_raw/sprites/wires/display/blue.png differ diff --git a/res_raw/sprites/wires/display/cyan.png b/res_raw/sprites/wires/display/cyan.png new file mode 100644 index 00000000..9cc20690 Binary files /dev/null and b/res_raw/sprites/wires/display/cyan.png differ diff --git a/res_raw/sprites/wires/display/green.png b/res_raw/sprites/wires/display/green.png new file mode 100644 index 00000000..cf390a5b Binary files /dev/null and b/res_raw/sprites/wires/display/green.png differ diff --git a/res_raw/sprites/wires/display/purple.png b/res_raw/sprites/wires/display/purple.png new file mode 100644 index 00000000..1285a151 Binary files /dev/null and b/res_raw/sprites/wires/display/purple.png differ diff --git a/res_raw/sprites/wires/display/red.png b/res_raw/sprites/wires/display/red.png new file mode 100644 index 00000000..fabf484c Binary files /dev/null and b/res_raw/sprites/wires/display/red.png differ diff --git a/res_raw/sprites/wires/display/white.png b/res_raw/sprites/wires/display/white.png new file mode 100644 index 00000000..0430f042 Binary files /dev/null and b/res_raw/sprites/wires/display/white.png differ diff --git a/res_raw/sprites/wires/display/yellow.png b/res_raw/sprites/wires/display/yellow.png new file mode 100644 index 00000000..02018a71 Binary files /dev/null and b/res_raw/sprites/wires/display/yellow.png differ diff --git a/res_raw/sprites/wires/lever_on.png b/res_raw/sprites/wires/lever_on.png new file mode 100644 index 00000000..f6a04e16 Binary files /dev/null and b/res_raw/sprites/wires/lever_on.png differ diff --git a/res_raw/sprites/wires/logical_acceptor.png b/res_raw/sprites/wires/logical_acceptor.png new file mode 100644 index 00000000..74325565 Binary files /dev/null and b/res_raw/sprites/wires/logical_acceptor.png differ diff --git a/res_raw/sprites/wires/logical_ejector.png b/res_raw/sprites/wires/logical_ejector.png new file mode 100644 index 00000000..c1d002aa Binary files /dev/null and b/res_raw/sprites/wires/logical_ejector.png differ diff --git a/res_raw/sprites/wires/negative_energy.png b/res_raw/sprites/wires/negative_energy.png deleted file mode 100644 index cc372330..00000000 Binary files a/res_raw/sprites/wires/negative_energy.png and /dev/null differ diff --git a/res_raw/sprites/wires/network_conflict.png b/res_raw/sprites/wires/network_conflict.png new file mode 100644 index 00000000..4b941bc0 Binary files /dev/null and b/res_raw/sprites/wires/network_conflict.png differ diff --git a/res_raw/sprites/wires/network_empty.png b/res_raw/sprites/wires/network_empty.png new file mode 100644 index 00000000..1f8d1c36 Binary files /dev/null and b/res_raw/sprites/wires/network_empty.png differ diff --git a/res_raw/sprites/wires/overlay_tile.png b/res_raw/sprites/wires/overlay_tile.png new file mode 100644 index 00000000..0b62ebc9 Binary files /dev/null and b/res_raw/sprites/wires/overlay_tile.png differ diff --git a/res_raw/sprites/wires/pin_negative_accept.png b/res_raw/sprites/wires/pin_negative_accept.png deleted file mode 100644 index 82581abb..00000000 Binary files a/res_raw/sprites/wires/pin_negative_accept.png and /dev/null differ diff --git a/res_raw/sprites/wires/pin_negative_eject.png b/res_raw/sprites/wires/pin_negative_eject.png deleted file mode 100644 index e816bd83..00000000 Binary files a/res_raw/sprites/wires/pin_negative_eject.png and /dev/null differ diff --git a/res_raw/sprites/wires/pin_positive_accept.png b/res_raw/sprites/wires/pin_positive_accept.png deleted file mode 100644 index 57044532..00000000 Binary files a/res_raw/sprites/wires/pin_positive_accept.png and /dev/null differ diff --git a/res_raw/sprites/wires/pin_positive_eject.png b/res_raw/sprites/wires/pin_positive_eject.png deleted file mode 100644 index a7da6bc0..00000000 Binary files a/res_raw/sprites/wires/pin_positive_eject.png and /dev/null differ diff --git a/res_raw/sprites/wires/positive_energy.png b/res_raw/sprites/wires/positive_energy.png deleted file mode 100644 index c95c80c9..00000000 Binary files a/res_raw/sprites/wires/positive_energy.png and /dev/null differ diff --git a/res_raw/sprites/wires/sets/README.md b/res_raw/sprites/wires/sets/README.md new file mode 100644 index 00000000..6153c07a --- /dev/null +++ b/res_raw/sprites/wires/sets/README.md @@ -0,0 +1 @@ +Built automatically by sprites/belt/generate_wire_sprites.js diff --git a/res_raw/sprites/wires/sets/color_cross.png b/res_raw/sprites/wires/sets/color_cross.png new file mode 100644 index 00000000..c3b2a3c2 Binary files /dev/null and b/res_raw/sprites/wires/sets/color_cross.png differ diff --git a/res_raw/sprites/wires/sets/color_forward.png b/res_raw/sprites/wires/sets/color_forward.png new file mode 100644 index 00000000..f6584aaa Binary files /dev/null and b/res_raw/sprites/wires/sets/color_forward.png differ diff --git a/res_raw/sprites/wires/sets/color_split.png b/res_raw/sprites/wires/sets/color_split.png new file mode 100644 index 00000000..af9ddfb6 Binary files /dev/null and b/res_raw/sprites/wires/sets/color_split.png differ diff --git a/res_raw/sprites/wires/sets/color_turn.png b/res_raw/sprites/wires/sets/color_turn.png new file mode 100644 index 00000000..1cf4dcb0 Binary files /dev/null and b/res_raw/sprites/wires/sets/color_turn.png differ diff --git a/res_raw/sprites/wires/sets/conflict_cross.png b/res_raw/sprites/wires/sets/conflict_cross.png new file mode 100644 index 00000000..fee403a6 Binary files /dev/null and b/res_raw/sprites/wires/sets/conflict_cross.png differ diff --git a/res_raw/sprites/wires/sets/conflict_forward.png b/res_raw/sprites/wires/sets/conflict_forward.png new file mode 100644 index 00000000..8b9ab43a Binary files /dev/null and b/res_raw/sprites/wires/sets/conflict_forward.png differ diff --git a/res_raw/sprites/wires/sets/conflict_split.png b/res_raw/sprites/wires/sets/conflict_split.png new file mode 100644 index 00000000..6e22aaf0 Binary files /dev/null and b/res_raw/sprites/wires/sets/conflict_split.png differ diff --git a/res_raw/sprites/wires/sets/conflict_turn.png b/res_raw/sprites/wires/sets/conflict_turn.png new file mode 100644 index 00000000..93bd3250 Binary files /dev/null and b/res_raw/sprites/wires/sets/conflict_turn.png differ diff --git a/res_raw/sprites/wires/sets/regular_cross.png b/res_raw/sprites/wires/sets/regular_cross.png new file mode 100644 index 00000000..e9c71dac Binary files /dev/null and b/res_raw/sprites/wires/sets/regular_cross.png differ diff --git a/res_raw/sprites/wires/sets/regular_forward.png b/res_raw/sprites/wires/sets/regular_forward.png new file mode 100644 index 00000000..8310be84 Binary files /dev/null and b/res_raw/sprites/wires/sets/regular_forward.png differ diff --git a/res_raw/sprites/wires/sets/regular_split.png b/res_raw/sprites/wires/sets/regular_split.png new file mode 100644 index 00000000..e26b552c Binary files /dev/null and b/res_raw/sprites/wires/sets/regular_split.png differ diff --git a/res_raw/sprites/wires/sets/regular_turn.png b/res_raw/sprites/wires/sets/regular_turn.png new file mode 100644 index 00000000..5b50bb09 Binary files /dev/null and b/res_raw/sprites/wires/sets/regular_turn.png differ diff --git a/res_raw/sprites/wires/sets/shape_cross.png b/res_raw/sprites/wires/sets/shape_cross.png new file mode 100644 index 00000000..d04812aa Binary files /dev/null and b/res_raw/sprites/wires/sets/shape_cross.png differ diff --git a/res_raw/sprites/wires/sets/shape_forward.png b/res_raw/sprites/wires/sets/shape_forward.png new file mode 100644 index 00000000..15ec3b9c Binary files /dev/null and b/res_raw/sprites/wires/sets/shape_forward.png differ diff --git a/res_raw/sprites/wires/sets/shape_split.png b/res_raw/sprites/wires/sets/shape_split.png new file mode 100644 index 00000000..d19c9b71 Binary files /dev/null and b/res_raw/sprites/wires/sets/shape_split.png differ diff --git a/res_raw/sprites/wires/sets/shape_turn.png b/res_raw/sprites/wires/sets/shape_turn.png new file mode 100644 index 00000000..4f40caa7 Binary files /dev/null and b/res_raw/sprites/wires/sets/shape_turn.png differ diff --git a/res_raw/sprites/wires/waste_piled.png b/res_raw/sprites/wires/waste_piled.png deleted file mode 100644 index 062d0df6..00000000 Binary files a/res_raw/sprites/wires/waste_piled.png and /dev/null differ diff --git a/res_raw/sprites/wires/wires_preview.png b/res_raw/sprites/wires/wires_preview.png new file mode 100644 index 00000000..03c9d0ef Binary files /dev/null and b/res_raw/sprites/wires/wires_preview.png differ diff --git a/src/css/common.scss b/src/css/common.scss index 6a87012e..5ae13dda 100644 --- a/src/css/common.scss +++ b/src/css/common.scss @@ -1,5 +1,4 @@ // Common classes and style - * { margin: 0; padding: 0; @@ -14,7 +13,6 @@ body { overflow: hidden; font-family: $mainFont; font-synthesis: none; - position: fixed; top: 0; left: 0; @@ -26,19 +24,15 @@ html { position: fixed; // scroll-behavior: smooth; background: $mainBgColor; - // Disable zooming and thus -ms-touch-action: pan-x, pan-y; touch-action: pan-x, pan-y; -ms-content-zooming: none; - top: 0; left: 0; bottom: 0; right: 0; - background: #dee1ea; - @include DarkThemeOverride { background: $darkModeGameBackground; } @@ -50,7 +44,6 @@ body { -moz-user-select: none; -ms-user-select: none; background: inherit !important; - text-transform: none; white-space: normal; word-break: normal; @@ -66,16 +59,17 @@ body { scrollbar-width: 6px; -webkit-font-smoothing: antialiased; // -webkit-overflow-scrolling: touch; /* stop scrolling immediately */ - -webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */ - -webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */ - + -webkit-touch-callout: none; + /* prevent callout to copy image, etc when tap to hold */ + -webkit-text-size-adjust: none; + /* prevent webkit from resizing text to fit */ // Internet explorer scrollbar-face-color: #888; scrollbar-track-color: rgba(255, 255, 255, 0.1); - + // Firefox + scrollbar-color: #cdd0d4 rgba(#000, 0.05); overflow: hidden; @include Text; - &.externalAdOpen { &::before { text-transform: uppercase; @@ -94,7 +88,6 @@ body { justify-content: center; align-items: center; color: #fff; - @include InlineAnimation(1s ease-in-out infinite) { 50% { transform: scale(1.05); @@ -102,9 +95,7 @@ body { } } } - // For recording the bg video - // filter: blur(5px); // &::after { // position: fixed; @@ -119,20 +110,24 @@ body { } img { - -webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */ + -webkit-touch-callout: none; + /* prevent callout to copy image, etc when tap to hold */ } i { font-style: normal; } + b, strong { font-weight: normal; } + u, a { text-decoration: none; } + input, textarea, select { @@ -149,7 +144,6 @@ button { cursor: pointer; position: relative; @include TextShadow3D; - &.prefab_BuyButtonWithResources { display: flex; box-sizing: border-box; @@ -160,27 +154,23 @@ button { justify-content: center; align-items: center; @include S(width, 85px); - &.tooExpensive { color: $colorRedBright; background-color: #555; cursor: default; } - .cost_entry { display: flex; flex-grow: 1; justify-content: center; align-items: center; } - b { display: flex; flex-grow: 1; justify-content: center; align-items: center; } - &.tooExpensive { cursor: default !important; background-color: #565859 !important; @@ -205,13 +195,12 @@ button { border: 0; background: $colorBlueBright; color: #fff; - + @include S(border-radius, $globalBorderRadius); // border: #{D(1px)} solid rgba(0, 10, 20, 0.2); @include S(border-bottom-width, 2px); // color: $accentColorDark; letter-spacing: 0.05em !important; // box-shadow: 0 #{D(1px)} #{D(2px)} 0 rgba(0, 10, 20, 0.2); - .keybinding { @include S(bottom, -2.5px); @include S(right, -2px); @@ -223,10 +212,13 @@ button { } ::selection { - background: $colorGreenBright; /* WebKit/Blink Browsers */ + background: $colorGreenBright; + /* WebKit/Blink Browsers */ } + ::-moz-selection { - background: $colorGreenBright; /* Gecko Browsers */ + background: $colorGreenBright; + /* Gecko Browsers */ } input[type="text"], @@ -241,35 +233,27 @@ input[type="email"] { background: lighten($mainBgColor, 8); color: #eee; text-align: left; - user-select: text !important; pointer-events: all !important; - @include Text; @include IncreasedClickArea(15px); @include S(border-radius, $globalBorderRadius); - &::placeholder { color: #fff; opacity: 0.4; } - transition: background-color 0.1s ease-in-out !important; @include TextShadow3D(#fff); @include BoxShadow3D(lighten($mainBgColor, 30)); - &:focus { @include BoxShadow3D(lighten($mainBgColor, 35)); } - &.errored { @include BoxShadow3D(mix(lighten($mainBgColor, 30), #f77, 25%)); - &:focus { @include BoxShadow3D(mix(lighten($mainBgColor, 50), #f77, 25%)); } } - &.input-token { @include SuperHeading; text-align: center; @@ -315,13 +299,12 @@ input { canvas { pointer-events: all; - image-rendering: auto; + // image-rendering: pixelated; // &.smoothed { - // } + // }1 // &.unsmoothed { // } letter-spacing: 0 !important; - transform: translateZ(0); backface-visibility: hidden; -webkit-backface-visibility: hidden; @@ -345,6 +328,7 @@ canvas { ::-webkit-scrollbar-thumb { // border-radius: 4px; + @include S(border-radius, $globalBorderRadius); background: #cdd0d4; } @@ -367,12 +351,12 @@ canvas { box-sizing: border-box; } -.pressed { - transform: scale(0.95) !important; +.pressed:not(.noPressEffect) { + transform: scale(0.98) !important; animation: none !important; } -.pressedSmallElement { +.pressedSmallElement:not(.noPressEffect) { transform: scale(0.88) !important; animation: none !important; } @@ -400,13 +384,11 @@ canvas { align-items: center; justify-content: center; text-transform: uppercase; - @include Text; @include TextShadow3D; opacity: 1; z-index: 20; color: #393747; - &::after { content: " "; background: uiResource("loading.svg") center center / contain no-repeat; @@ -417,7 +399,6 @@ canvas { display: inline-block; vertical-align: middle; } - @include DarkThemeOverride { color: #fff; } @@ -439,7 +420,6 @@ canvas { .prefab_FeatureComingSoon { position: relative; - &::after { @include S(top, -5px); @include S(left, -5px); @@ -457,9 +437,7 @@ canvas { @include PlainText; text-transform: uppercase; } - opacity: 0.6; - > * { opacity: 0.5 !important; } @@ -484,14 +462,12 @@ canvas { align-items: center; justify-content: center; flex-direction: column; - .loadingImage { background: uiResource("loading.svg") center center / #{D(60px)} no-repeat; width: 100%; display: flex; flex-grow: 1; } - .loadingStatus { position: absolute; @include S(left, 20px); @@ -499,12 +475,10 @@ canvas { @include S(bottom, 30px); @include Text; @include TextShadow3D(#aaa); - display: flex; flex-direction: column; justify-content: center; align-items: center; - > .bar { display: none; @include S(margin-top, 15px); @@ -513,7 +487,6 @@ canvas { position: relative; @include TextShadow3D(#fff); height: 2px; - .inner { position: absolute !important; top: 0; @@ -522,9 +495,7 @@ canvas { z-index: 1; @include BoxShadow3D($themeColor, $size: 1px); @include S(border-radius, $globalBorderRadius); - transform-origin: 0% 50%; - @include InlineAnimation(1.3s ease-in-out infinite) { 0% { background-color: darken($themeColor, 5); @@ -540,7 +511,6 @@ canvas { } } } - .status { display: none; position: relative; @@ -575,11 +545,9 @@ canvas { &.loading { opacity: 0.2; } - &:hover { background-color: darken($bgColor, 5); } - .knob { @include S(width, 20px); @include S(height, 17px); @@ -590,20 +558,61 @@ canvas { @include BorderRadius(20px); @include BoxShadow3D(#fff, $size: 1px); } - &.checked { background-color: $themeColor; @include BoxShadow3D($themeColor, $size: 2px); .knob { @include S(margin-left, 15px); } - &:hover { background-color: lighten($themeColor, 15); } } } +.rangeInputContainer { + display: flex; + align-items: center; + justify-content: center; + + label { + @include S(margin-right, 5px); + &, + & * { + @include PlainText; + } + } +} + +input.rangeInput { + cursor: pointer; + background-color: transparent; + @include S(width, 100px); + @include S(height, 16px); + + &::-webkit-slider-runnable-track { + background-color: darken($mainBgColor, 3); + color: darken($mainBgColor, 3); + // @include S(height, 16px); + @include S(border-radius, 8px); + } + + &::-webkit-slider-thumb { + appearance: none; + -webkit-appearance: none; + box-shadow: inset 0 0 0 D(10px) $themeColor; + border-radius: 50%; + + transition: box-shadow 0.3s; + } + + &:hover { + &::-webkit-slider-thumb { + box-shadow: inset 0 0 0 D(10px) lighten($themeColor, 15); + } + } +} + .keybinding { background: #fff; text-transform: uppercase; @@ -618,7 +627,6 @@ canvas { text-shadow: none !important; // font-family: Arial, sans-serif !important; } - font-weight: bold; color: $accentColorDark; text-align: center; @@ -634,7 +642,6 @@ canvas { @include S(height, 12px); overflow: hidden; border: #{D(0px)} solid $accentColorDark; - .keybinding_space { @include S(font-size, 17px); @include S(line-height, 11px); @@ -647,7 +654,6 @@ canvas { .xpaystation-widget-lightbox-overlay { background: rgba($mainBgColor, 0.94); } - &, iframe { pointer-events: all; @@ -660,7 +666,7 @@ iframe { user-select: all; } -// Steam overlay fiy +// Steam overlay fix #steamOverlayCanvasFix { position: fixed; top: 0px; @@ -688,9 +694,7 @@ iframe { * { pointer-events: all; } - background: rgba($mainBgColor, 0.94) !important; - .cpmsvideoclosebanner { font-family: GameFont !important; font-size: 16px !important; diff --git a/src/css/icons.scss b/src/css/icons.scss index a0967656..841fccd9 100644 --- a/src/css/icons.scss +++ b/src/css/icons.scss @@ -1,38 +1,38 @@ -$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt, - energy_generator, wire, advanced_processor, wire_crossings; - -@each $building in $buildings { - [data-icon="building_icons/#{$building}.png"] { - background-image: uiResource("res/ui/building_icons/#{$building}.png") !important; - } -} - -$buildingsAndVariants: belt, splitter, splitter-compact, splitter-compact-inverse, underground_belt, - underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer, - painter, painter-double, painter-quad, trash, trash-storage; -@each $building in $buildingsAndVariants { - [data-icon="building_tutorials/#{$building}.png"] { - background-image: uiResource("res/ui/building_tutorials/#{$building}.png") !important; - } -} - -// Special case -[data-icon="building_tutorials/painter-mirrored.png"] { - background-image: uiResource("res/ui/building_tutorials/painter.png") !important; -} - -$icons: notification_saved, notification_success, notification_upgrade; -@each $icon in $icons { - [data-icon="icons/#{$icon}.png"] { - background-image: uiResource("res/ui/icons/#{$icon}.png") !important; - } -} - -$languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, zh-CN, nb, mt-MT, ar, nl, vi, - th, hu, pl, ja, kor, no, pt-PT; - -@each $language in $languages { - [data-languageicon="#{$language}"] { - background-image: uiResource("languages/#{$language}.svg") !important; - } -} +$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt, wire, + constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader; + +@each $building in $buildings { + [data-icon="building_icons/#{$building}.png"] { + background-image: uiResource("res/ui/building_icons/#{$building}.png") !important; + } +} + +$buildingsAndVariants: belt, splitter, splitter-compact, splitter-compact-inverse, underground_belt, + underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, rotater-fl, + stacker, mixer, painter, painter-double, painter-quad, trash, trash-storage; +@each $building in $buildingsAndVariants { + [data-icon="building_tutorials/#{$building}.png"] { + background-image: uiResource("res/ui/building_tutorials/#{$building}.png") !important; + } +} + +// Special case +[data-icon="building_tutorials/painter-mirrored.png"] { + background-image: uiResource("res/ui/building_tutorials/painter.png") !important; +} + +$icons: notification_saved, notification_success, notification_upgrade; +@each $icon in $icons { + [data-icon="icons/#{$icon}.png"] { + background-image: uiResource("res/ui/icons/#{$icon}.png") !important; + } +} + +$languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, zh-CN, nb, mt-MT, ar, nl, vi, + th, hu, pl, ja, kor, no, pt-PT; + +@each $language in $languages { + [data-languageicon="#{$language}"] { + background-image: uiResource("languages/#{$language}.svg") !important; + } +} diff --git a/src/css/ingame_hud/building_placer.scss b/src/css/ingame_hud/building_placer.scss index 8ca53655..9c038340 100644 --- a/src/css/ingame_hud/building_placer.scss +++ b/src/css/ingame_hud/building_placer.scss @@ -18,6 +18,14 @@ background-color: #55585a; } + transition: opacity 0.1s ease-out; + &.hovered { + opacity: 0.1; + .buildingImage { + opacity: 0; + } + } + .buildingLabel { @include PlainText; @include S(margin-bottom, 2px); @@ -70,6 +78,7 @@ @include S(height, 100px); background: top left / 100% 100% no-repeat; @include S(border-radius, $globalBorderRadius); + transition: opacity 0.1s ease-in-out; } @include StyleBelowWidth(700px) { diff --git a/src/css/ingame_hud/buildings_toolbar.scss b/src/css/ingame_hud/buildings_toolbar.scss index ed5bb7a2..d394106d 100644 --- a/src/css/ingame_hud/buildings_toolbar.scss +++ b/src/css/ingame_hud/buildings_toolbar.scss @@ -4,27 +4,31 @@ left: 50%; transform: translateX(-50%); + // NOTE: This flex rule may not be necessary. Need to find out intent. display: flex; flex-direction: column; - background-color: rgb(255, 255, 255); background: transparent; border-bottom-width: 0; - transition: transform 0.12s ease-in-out; + transition: transform 120ms ease-in-out; + will-change: transform; - background: rgba(mix(#ddd, $colorBlueBright, 90%), 0.75); + background-color: rgba(mix(#ddd, $colorBlueBright, 90%), 0.5); + backdrop-filter: blur(D(3px)); @include DarkThemeOverride { - background: #222428; + background-color: #222428; } &:not(.visible) { transform: translateX(-50%) translateY(#{D(100px)}); } + @include S(border-top-left-radius, $globalBorderRadius); + @include S(border-top-right-radius, $globalBorderRadius); + .buildings { display: grid; grid-auto-flow: column; - @include S(margin-bottom, 2px); .building { color: $accentColorDark; @@ -38,7 +42,7 @@ @include S(width, 35px); @include S(height, 40px); - background: center center / 70% no-repeat; + background: center center / 65% no-repeat; &:not(.unlocked) { @include S(width, 20px); @@ -60,21 +64,43 @@ @include S(border-radius, $globalBorderRadius); - &.selected { - background-color: rgba($colorBlueBright, 0.6) !important; - transform: scale(1.05); - .keybinding { - color: #111; - } - } - - pointer-events: all; - transition: all 0.05s ease-in-out; - transition-property: background-color, transform; - - &.unlocked:hover { - background-color: rgba($accentColorDark, 0.1); + &.unlocked { + pointer-events: all; + transition: all 50ms ease-in-out; + transition-property: background-color, transform; cursor: pointer; + will-change: transform; + + &::before { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: $accentColorDark; + opacity: 0; + will-change: opacity; + } + + &:hover { + &::before { + opacity: 0.1; + } + } + + &.selected { + transform: scale(1.05); + + &::before { + background-color: $colorBlueBright; + opacity: 0.6; + } + + .keybinding { + color: #111; + } + } } } } diff --git a/src/css/ingame_hud/dialogs.scss b/src/css/ingame_hud/dialogs.scss index d72265e7..9c9ce7a4 100644 --- a/src/css/ingame_hud/dialogs.scss +++ b/src/css/ingame_hud/dialogs.scss @@ -55,6 +55,7 @@ .dialogInner { opacity: 1; } + backdrop-filter: blur(D(3px)); } .dialogInner { diff --git a/src/css/ingame_hud/game_menu.scss b/src/css/ingame_hud/game_menu.scss index 41ea600f..f893904c 100644 --- a/src/css/ingame_hud/game_menu.scss +++ b/src/css/ingame_hud/game_menu.scss @@ -1,159 +1,147 @@ -#ingame_HUD_GameMenu { - position: absolute; - top: 0; - right: 0; - display: flex; - grid-auto-flow: column; - - > .menuButtons { - position: relative; - display: flex; - flex-grow: 1; - @include S(padding, 5px, 4px); - justify-content: flex-end; - @include S(margin-left, 20px); - - > .button { - @include S(width, 30px); - @include S(height, 30px); - display: inline-block; - background: center center / 60% no-repeat; - pointer-events: all; - cursor: pointer; - transition: all 0.12s ease-in-out; - transition-property: opacity, transform; - opacity: 0.9; - @include S(margin-left, 5px); - position: relative; - - @include IncreasedClickArea(0px); - - @include DarkThemeInvert; - - &:hover { - opacity: 0.8; - } - &.music { - background-image: uiResource("icons/music_on.png"); - &.muted { - background-image: uiResource("icons/music_off.png"); - } - } - - &.sfx { - background-image: uiResource("icons/sound_on.png"); - &.muted { - background-image: uiResource("icons/sound_off.png"); - } - } - - &.save { - background-image: uiResource("icons/save.png"); - @include MakeAnimationWrappedEvenOdd(0.5s ease-in-out) { - 0% { - transform: scale(1, 1); - } - - 70% { - transform: scale(1.5, 1.5) rotate(20deg); - opacity: 0.2; - } - - 85% { - transform: scale(0.9, 0.9); - opacity: 1; - } - - 90% { - transform: scale(1.1, 1.1); - } - } - } - - &.settings { - background-image: uiResource("icons/settings.png"); - } - } - } - - .buttonContainer button { - @include PlainText; - color: #fff; - border-color: rgba(0, 0, 0, 0.1); - @include S(padding, 5px, 5px, 5px); - - @include S(padding-left, 30px); - @include S(margin-right, 3px); - @include IncreasedClickArea(0px); - @include ButtonText; - @include S(min-height, 40px); - transition: all 0.12s ease-in-out; - transition-property: opacity, transform; - display: inline-flex; - background: center #{D(13px)} / #{D(20px)} no-repeat; - background-color: $colorGreenBright; - - &[data-button-id="shop"] { - background-color: rgb(93, 103, 250); - background-image: uiResource("icons/shop.png"); - background-size: #{D(18px)}; - } - &[data-button-id="stats"] { - background-color: rgb(85, 199, 138); - background-image: uiResource("icons/statistics.png"); - } - - &:hover { - opacity: 0.9; - } - - .keybinding { - border: 0; - color: #fff; - border-top-left-radius: 0; - border-top-right-radius: 0; - bottom: unset; - background: transparent; - @include S(top, 0px); - right: unset; - left: 50%; - transform: translateX(-50%); - } - - &:not(.hasBadge) .badge { - display: none; - } - - &.hasBadge { - transform-origin: 50% 0%; - @include InlineAnimation(1s ease-in-out infinite) { - 50% { - transform: scale(1.02); - } - } - - .badge { - position: absolute; - @include S(bottom, -8px); - left: 50%; - transform: translateX(-50%); - - background: #333; - @include PlainText; - display: flex; - justify-content: center; - align-items: center; - @include S(min-width, 5px); - @include S(height, 10px); - @include S(padding, 1px, 3px, 2px); - @include S(border-radius, $globalBorderRadius); - border: #{D(1px)} solid #fff; - @include InlineAnimation(1s ease-in-out infinite) { - 50% { - transform: translateX(-50%) scale(1.05); - } - } - } - } - } -} +#ingame_HUD_GameMenu { + position: absolute; + top: 0; + right: 0; + display: flex; + grid-auto-flow: column; + + > .menuButtons { + position: relative; + display: flex; + flex-grow: 1; + @include S(padding, 5px, 4px); + justify-content: flex-end; + @include S(margin-left, 20px); + + > .button { + @include S(width, 30px); + @include S(height, 30px); + display: inline-block; + background: center center / 60% no-repeat; + pointer-events: all; + cursor: pointer; + transition: all 0.12s ease-in-out; + transition-property: opacity, transform; + will-change: opacity; + opacity: 0.9; + @include S(margin-left, 5px); + position: relative; + + @include IncreasedClickArea(0px); + + @include DarkThemeInvert; + + &:hover { + opacity: 0.8; + } + + &.save { + background-image: uiResource("icons/save.png"); + @include MakeAnimationWrappedEvenOdd(0.5s ease-in-out) { + 0% { + transform: scale(1, 1); + } + + 70% { + transform: scale(1.5, 1.5) rotate(20deg); + opacity: 0.2; + } + + 85% { + transform: scale(0.9, 0.9); + opacity: 1; + } + + 90% { + transform: scale(1.1, 1.1); + } + } + } + + &.settings { + background-image: uiResource("icons/settings.png"); + } + } + } + + .buttonContainer button { + @include PlainText; + color: #fff; + border-color: rgba(0, 0, 0, 0.1); + @include S(padding, 5px, 5px, 5px); + + @include S(padding-left, 30px); + @include S(margin-right, 3px); + @include IncreasedClickArea(0px); + @include ButtonText; + @include S(min-height, 40px); + transition: all 0.12s ease-in-out; + transition-property: opacity, transform; + display: inline-flex; + background: center #{D(13px)} / #{D(20px)} no-repeat; + background-color: $colorGreenBright; + + &[data-button-id="shop"] { + background-color: rgb(93, 103, 250); + background-image: uiResource("icons/shop.png"); + background-size: #{D(18px)}; + } + &[data-button-id="stats"] { + background-color: rgb(85, 199, 138); + background-image: uiResource("icons/statistics.png"); + } + + &:hover { + opacity: 0.9; + } + + .keybinding { + border: 0; + color: #fff; + border-top-left-radius: 0; + border-top-right-radius: 0; + bottom: unset; + background: transparent; + @include S(top, 0px); + right: unset; + left: 50%; + transform: translateX(-50%); + } + + &:not(.hasBadge) .badge { + display: none; + } + + &.hasBadge { + transform-origin: 50% 0%; + @include InlineAnimation(1s ease-in-out infinite) { + 50% { + transform: scale(1.02); + } + } + + .badge { + position: absolute; + @include S(bottom, -8px); + left: 50%; + transform: translateX(-50%); + + background: #333; + @include PlainText; + display: flex; + justify-content: center; + align-items: center; + @include S(min-width, 5px); + @include S(height, 10px); + @include S(padding, 1px, 3px, 2px); + @include S(border-radius, $globalBorderRadius); + border: #{D(1px)} solid #fff; + @include InlineAnimation(1s ease-in-out infinite) { + 50% { + transform: translateX(-50%) scale(1.05); + } + } + } + } + } +} diff --git a/src/css/ingame_hud/interactive_tutorial.scss b/src/css/ingame_hud/interactive_tutorial.scss index d4fb58e1..9d4aeffc 100644 --- a/src/css/ingame_hud/interactive_tutorial.scss +++ b/src/css/ingame_hud/interactive_tutorial.scss @@ -15,6 +15,8 @@ display: flex; flex-direction: column; + @include S(border-radius, $globalBorderRadius); + @include MakeAnimationWrappedEvenOdd(0.5s ease-in-out) { 0% { } @@ -27,6 +29,16 @@ } } + pointer-events: all; + + transition: opacity 0.1s ease-out; + &.hovered { + opacity: 10%; + .helperGif { + opacity: 0%; + } + } + .title { color: #fff; opacity: 0.5; @@ -46,5 +58,6 @@ @include S(margin-top, 5px); @include S(height, 150px); background: center center / contain no-repeat; + transition: opacity 0.1s ease-out; } } diff --git a/src/css/ingame_hud/keybindings_overlay.scss b/src/css/ingame_hud/keybindings_overlay.scss index 38b560d8..21d07b4b 100644 --- a/src/css/ingame_hud/keybindings_overlay.scss +++ b/src/css/ingame_hud/keybindings_overlay.scss @@ -1,68 +1,74 @@ -#ingame_HUD_KeybindingOverlay { - position: absolute; - @include S(top, 10px); - @include S(left, 10px); - - display: flex; - flex-direction: column; - align-items: flex-start; - color: #333438; - // text-shadow: #{D(1px)} #{D(1px)} 0 rgba(0, 10, 20, 0.1); - - @include DarkThemeOverride { - color: #fff; - } - - > .binding { - &:not(.visible) { - display: none !important; - } - - display: inline-grid; - @include PlainText; - align-items: center; - @include S(margin-bottom, 3px); - grid-auto-flow: column; - @include S(grid-gap, 2px); - - i { - display: inline-block; - @include S(height, 10px); - width: 1px; - @include S(margin, 0, 3px); - background-color: #fff; - transform: rotate(10deg); - // @include S(margin, 0, 3px); - } - - code { - position: relative; - top: unset; - left: unset; - margin: 0; - &.rightMouse { - background: #fff uiResource("icons/mouse_right.png") center center / 85% no-repeat; - } - - &.leftMouse { - background: #fff uiResource("icons/mouse_left.png") center center / 85% no-repeat; - } - } - - label { - color: #333438; - @include SuperSmallText; - text-transform: uppercase; - // color: #fff; - @include DarkThemeOverride { - color: #fff; - } - - @include S(margin-left, 5px); - } - } -} - -body.uiHidden #ingame_HUD_KeybindingOverlay .binding:not(.hudToggle) { - display: none; -} +#ingame_HUD_KeybindingOverlay { + position: absolute; + @include S(top, 10px); + @include S(left, 10px); + + display: flex; + flex-direction: column; + align-items: flex-start; + color: #333438; + backdrop-filter: blur(D(2px)); + padding: D(3px); + + @include DarkThemeOverride { + color: #fff; + } + + transition: opacity 0.1s ease-out; + &.hovered { + opacity: 0.1; + } + + > .binding { + &:not(.visible) { + display: none !important; + } + + display: inline-grid; + @include PlainText; + align-items: center; + @include S(margin-bottom, 3px); + grid-auto-flow: column; + @include S(grid-gap, 2px); + + i { + display: inline-block; + @include S(height, 10px); + width: 1px; + @include S(margin, 0, 3px); + background-color: #fff; + transform: rotate(10deg); + // @include S(margin, 0, 3px); + } + + code { + position: relative; + top: unset; + left: unset; + margin: 0; + &.rightMouse { + background: #fff uiResource("icons/mouse_right.png") center center / 85% no-repeat; + } + + &.leftMouse { + background: #fff uiResource("icons/mouse_left.png") center center / 85% no-repeat; + } + } + + label { + color: #333438; + @include SuperSmallText; + text-transform: uppercase; + // color: #fff; + @include DarkThemeOverride { + color: #fff; + } + + @include S(margin-left, 5px); + } + } +} + +body.uiHidden #ingame_HUD_KeybindingOverlay .binding:not(.hudToggle) { + display: none; +} diff --git a/src/css/ingame_hud/pinned_shapes.scss b/src/css/ingame_hud/pinned_shapes.scss index 60e9159e..48e5b70e 100644 --- a/src/css/ingame_hud/pinned_shapes.scss +++ b/src/css/ingame_hud/pinned_shapes.scss @@ -18,6 +18,7 @@ @include S(margin-bottom, 4px); color: #333438; // text-shadow: #{D(1px)} #{D(1px)} 0 rgba(0, 10, 20, 0.2); + filter: drop-shadow(#{D(1px)} #{D(1px)} 0 rgba(0, 10, 20, 0.2)); &.unpinable { > canvas { @@ -33,10 +34,12 @@ grid-row: 1 / 3; pointer-events: all; transition: transform 0.1s ease-in-out; + transform-origin: D(2px) center; + will-change: transform; position: relative; z-index: 20; &:hover { - transform: scale(2) translateX(#{D(5px)}); + transform: scale(2); z-index: 21; } } diff --git a/src/css/ingame_hud/statistics.scss b/src/css/ingame_hud/statistics.scss index e53a80d1..12b8c1aa 100644 --- a/src/css/ingame_hud/statistics.scss +++ b/src/css/ingame_hud/statistics.scss @@ -14,20 +14,37 @@ @include S(padding, 1px, 10px); border: 0; box-shadow: none; - border-radius: 0; @include IncreasedClickArea(1px); @include S(min-width, 30px); color: #fff; opacity: 0.25; - @include S(margin-left, 1px); + @include S(border-radius, $globalBorderRadius); + + border-radius: 0; + &:first-child { + @include S(border-top-left-radius, $globalBorderRadius); + @include S(border-bottom-left-radius, $globalBorderRadius); + } + + &:last-child { + @include S(border-top-right-radius, $globalBorderRadius); + @include S(border-bottom-right-radius, $globalBorderRadius); + } &.displayIcons, - &.displayDetailed { + &.displayDetailed, + &.displaySorted { background: uiResource("icons/display_list.png") center center / #{D(15px)} no-repeat; &.displayIcons { background-image: uiResource("icons/display_icons.png"); background-size: #{D(11.5px)}; } + &.displaySorted { + background-image: uiResource("icons/display_sorted.png"); + background-size: #{D(11.5px)}; + margin-right: 4px; + @include S(padding, 1px, 0); + } } background-color: #44484a !important; @@ -80,10 +97,7 @@ background: #f4f4f4; @include S(margin-bottom, 4px); display: grid; - - @include DarkThemeOverride { - background: #222428; - } + @include S(border-radius, $globalBorderRadius); grid-template-columns: 1fr auto; @include S(padding, 5px); @@ -91,6 +105,18 @@ margin-bottom: 0; } + &.pinned { + background: #e3e5e9; + } + + @include DarkThemeOverride { + background: #222428; + + &.pinned { + background: darken(#222428, 10); + } + } + canvas.icon { grid-column: 1 / 2; grid-row: 1 / 2; @@ -100,7 +126,6 @@ .counter { @include SuperSmallText; - @include S(padding, 0, 3px); } } @@ -109,6 +134,7 @@ .dialogInner { &[data-displaymode="detailed"] .displayDetailed, &[data-displaymode="icons"] .displayIcons, + &[data-sorted="true"] .displaySorted, &[data-datasource="produced"] .modeProduced, &[data-datasource="delivered"] .modeDelivered, &[data-datasource="stored"] .modeStored { @@ -132,7 +158,6 @@ .counter { grid-column: 1 / 2; grid-row: 2 / 3; - background: rgba(0, 10, 20, 0.05); justify-self: end; } } diff --git a/src/css/ingame_hud/waypoints.scss b/src/css/ingame_hud/waypoints.scss index 7a9941c0..07a8f7e7 100644 --- a/src/css/ingame_hud/waypoints.scss +++ b/src/css/ingame_hud/waypoints.scss @@ -1,95 +1,107 @@ -#ingame_HUD_Waypoints_Hint { - position: absolute; - @include S(right, 10px); - @include S(bottom, 10px); - - display: flex; - flex-direction: column; - - @include PlainText; - @include S(width, 150px); - background: rgba(0, 10, 20, 0.5); - @include S(padding, 5px); - - color: #eee; - - .desc { - @include SuperSmallText; - color: #babcbf; - .keybinding { - position: relative; - } - - strong { - color: #fff; - } - } -} - -#ingame_HUD_Waypoints { - position: absolute; - @include S(right, 10px); - @include S(top, 45px); - display: flex; - flex-direction: column; - @include DarkThemeInvert(); - - .waypoint { - @include SuperSmallText; - pointer-events: all; - cursor: pointer; - color: #333438; - @include S(padding-left, 11px); - display: grid; - grid-template-columns: 1fr auto; - align-items: center; - background: uiResource("icons/waypoint.png") left 50% / #{D(8px)} no-repeat; - opacity: 0.7; - @include S(margin-bottom, 1px); - font-weight: bold; - - &:hover { - opacity: 0.8; - } - - .editButton { - @include S(width, 10px); - @include S(height, 10px); - @include S(margin-left, 4px); - background: uiResource("icons/edit_key.png") center center / 70% no-repeat; - pointer-events: all; - cursor: pointer; - position: relative; - @include IncreasedClickArea(2px); - transition: transform 0.04s ease-in-out; - - &:hover { - transform: scale(1.5); - } - } - - &.hub { - // Transform because there is a canvas before - @include S(margin-left, -2px); - - grid-template-columns: auto 1fr; - background: none !important; - @include S(padding-left, 0); - canvas { - @include S(width, 12px); - @include S(height, 12px); - @include S(margin-right, 1px); - } - } - - &.shapeIcon { - canvas { - @include S(width, 15px); - @include S(height, 15px); - pointer-events: none; - // Double invert, to make sure it has the right color - @include DarkThemeInvert(); - } - } - } -} +#ingame_HUD_Waypoints_Hint { + position: absolute; + @include S(right, 10px); + @include S(bottom, 10px); + + display: flex; + flex-direction: column; + + @include PlainText; + @include S(width, 150px); + background: rgba(0, 10, 20, 0.5); + @include S(padding, 5px); + + color: #eee; + + .desc { + @include SuperSmallText; + color: #babcbf; + .keybinding { + position: relative; + } + + strong { + color: #fff; + } + } +} + +#ingame_HUD_Waypoints { + position: absolute; + @include S(right, 10px); + @include S(top, 45px); + display: flex; + flex-direction: column; + @include DarkThemeInvert(); + + max-height: 50vh; + overflow-x: hidden; + overflow-y: auto; + pointer-events: all; + @include S(padding-right, 5px); + + // Scrollbar + &::-webkit-scrollbar { + @include S(width, 2px); + @include S(height, 6px); + } + + .waypoint { + @include SuperSmallText; + pointer-events: all; + cursor: pointer; + color: #333438; + @include S(padding-left, 11px); + display: grid; + grid-template-columns: 1fr auto; + align-items: center; + background: uiResource("icons/waypoint.png") left 50% / #{D(8px)} no-repeat; + opacity: 0.7; + @include S(margin-bottom, 1px); + font-weight: bold; + + &:hover { + opacity: 0.8; + } + + .editButton { + @include S(width, 10px); + @include S(height, 10px); + @include S(margin-left, 4px); + background: uiResource("icons/edit_key.png") center center / 70% no-repeat; + pointer-events: all; + cursor: pointer; + position: relative; + @include IncreasedClickArea(2px); + transition: transform 0.04s ease-in-out; + + &:hover { + transform: scale(1.5); + } + } + + &.hub { + // Transform because there is a canvas before + @include S(margin-left, -2px); + + grid-template-columns: auto 1fr; + background: none !important; + @include S(padding-left, 0); + canvas { + @include S(width, 12px); + @include S(height, 12px); + @include S(margin-right, 1px); + } + } + + &.shapeIcon { + canvas { + @include S(width, 15px); + @include S(height, 15px); + pointer-events: none; + // Double invert, to make sure it has the right color + @include DarkThemeInvert(); + } + } + } +} diff --git a/src/css/main.scss b/src/css/main.scss index fa3ed356..5835a84d 100644 --- a/src/css/main.scss +++ b/src/css/main.scss @@ -1,124 +1,124 @@ -// Control here whether to inline all resources or instead load them -@function uiResource($pth) { - @if (str-index($string: $pth, $substring: ".noinline")) { - @return resolve($pth); - } - @return inline($pth); -} - -@import "icons"; -@import "trigonometry"; -@import "material_colors"; -@import "dynamic_ui"; -@import "variables"; - -@import "mixins"; -@import "common"; -@import "animations"; -@import "game_state"; -@import "application_error"; -@import "textual_game_state"; -@import "adinplay"; - -@import "states/preload"; -@import "states/main_menu"; -@import "states/ingame"; -@import "states/keybindings"; -@import "states/settings"; -@import "states/about"; -@import "states/mobile_warning"; -@import "states/changelog"; - -@import "ingame_hud/buildings_toolbar"; -@import "ingame_hud/building_placer"; -@import "ingame_hud/beta_overlay"; -@import "ingame_hud/keybindings_overlay"; -@import "ingame_hud/unlock_notification"; -@import "ingame_hud/shop"; -@import "ingame_hud/game_menu"; -@import "ingame_hud/dialogs"; -@import "ingame_hud/vignette_overlay"; -@import "ingame_hud/statistics"; -@import "ingame_hud/pinned_shapes"; -@import "ingame_hud/notifications"; -@import "ingame_hud/settings_menu"; -@import "ingame_hud/debug_info"; -@import "ingame_hud/entity_debugger"; -@import "ingame_hud/tutorial_hints"; -@import "ingame_hud/watermark"; -@import "ingame_hud/blueprint_placer"; -@import "ingame_hud/waypoints"; -@import "ingame_hud/interactive_tutorial"; -@import "ingame_hud/color_blind_helper"; -@import "ingame_hud/shape_viewer"; -@import "ingame_hud/sandbox_controller"; - -// prettier-ignore -$elements: -// Base -ingame_Canvas, -ingame_VignetteOverlay, - -// Ingame overlays -ingame_HUD_Waypoints, -ingame_HUD_PlacementHints, -ingame_HUD_PlacerVariants, - -// Regular hud -ingame_HUD_PinnedShapes, -ingame_HUD_GameMenu, -ingame_HUD_KeybindingOverlay, -ingame_HUD_Notifications, -ingame_HUD_DebugInfo, -ingame_HUD_EntityDebugger, -ingame_HUD_InteractiveTutorial, -ingame_HUD_TutorialHints, -ingame_HUD_buildings_toolbar, -ingame_HUD_wires_toolbar, -ingame_HUD_BlueprintPlacer, -ingame_HUD_Waypoints_Hint, -ingame_HUD_Watermark, -ingame_HUD_ColorBlindBelowTileHelper, -ingame_HUD_SandboxController, - -// Overlays -ingame_HUD_BetaOverlay, - -// Dialogs -ingame_HUD_Shop, -ingame_HUD_Statistics, -ingame_HUD_ShapeViewer, -ingame_HUD_UnlockNotification, -ingame_HUD_SettingsMenu, -ingame_HUD_ModalDialogs; - -$zindex: 100; - -@each $elem in $elements { - ##{$elem} { - z-index: $zindex; - } - - $zindex: $zindex + 10; -} - -body.uiHidden { - #ingame_HUD_buildings_toolbar, - #ingame_HUD_PlacementHints, - #ingame_HUD_GameMenu, - #ingame_HUD_PinnedShapes, - #ingame_HUD_Notifications, - #ingame_HUD_TutorialHints, - #ingame_HUD_Waypoints, - #ingame_HUD_Waypoints_Hint { - display: none !important; - } -} - -body.modalDialogActive, -body.externalAdOpen, -body.ingameDialogOpen { - > *:not(.ingameDialog):not(.modalDialogParent):not(.loadingDialog):not(.gameLoadingOverlay):not(#ingame_HUD_ModalDialogs):not(.noBlur) { - // filter: blur(5px) !important; - } -} +// Control here whether to inline all resources or instead load them +@function uiResource($pth) { + @if (str-index($string: $pth, $substring: ".noinline")) { + @return resolve($pth); + } + @return inline($pth); +} + +@import "icons"; +@import "trigonometry"; +@import "material_colors"; +@import "dynamic_ui"; +@import "variables"; + +@import "mixins"; +@import "common"; +@import "animations"; +@import "game_state"; +@import "application_error"; +@import "textual_game_state"; +@import "adinplay"; + +@import "states/preload"; +@import "states/main_menu"; +@import "states/ingame"; +@import "states/keybindings"; +@import "states/settings"; +@import "states/about"; +@import "states/mobile_warning"; +@import "states/changelog"; + +@import "ingame_hud/buildings_toolbar"; +@import "ingame_hud/building_placer"; +@import "ingame_hud/beta_overlay"; +@import "ingame_hud/keybindings_overlay"; +@import "ingame_hud/unlock_notification"; +@import "ingame_hud/shop"; +@import "ingame_hud/game_menu"; +@import "ingame_hud/dialogs"; +@import "ingame_hud/vignette_overlay"; +@import "ingame_hud/statistics"; +@import "ingame_hud/pinned_shapes"; +@import "ingame_hud/notifications"; +@import "ingame_hud/settings_menu"; +@import "ingame_hud/debug_info"; +@import "ingame_hud/entity_debugger"; +@import "ingame_hud/tutorial_hints"; +@import "ingame_hud/watermark"; +@import "ingame_hud/blueprint_placer"; +@import "ingame_hud/waypoints"; +@import "ingame_hud/interactive_tutorial"; +@import "ingame_hud/color_blind_helper"; +@import "ingame_hud/shape_viewer"; +@import "ingame_hud/sandbox_controller"; + +// prettier-ignore +$elements: +// Base +ingame_Canvas, +ingame_VignetteOverlay, + +// Ingame overlays +ingame_HUD_Waypoints, +ingame_HUD_PlacementHints, +ingame_HUD_PlacerVariants, + +// Regular hud +ingame_HUD_PinnedShapes, +ingame_HUD_GameMenu, +ingame_HUD_KeybindingOverlay, +ingame_HUD_Notifications, +ingame_HUD_DebugInfo, +ingame_HUD_EntityDebugger, +ingame_HUD_InteractiveTutorial, +ingame_HUD_TutorialHints, +ingame_HUD_buildings_toolbar, +ingame_HUD_wires_toolbar, +ingame_HUD_BlueprintPlacer, +ingame_HUD_Waypoints_Hint, +ingame_HUD_Watermark, +ingame_HUD_ColorBlindBelowTileHelper, +ingame_HUD_SandboxController, + +// Overlays +ingame_HUD_BetaOverlay, + +// Dialogs +ingame_HUD_Shop, +ingame_HUD_Statistics, +ingame_HUD_ShapeViewer, +ingame_HUD_UnlockNotification, +ingame_HUD_SettingsMenu, +ingame_HUD_ModalDialogs; + +$zindex: 100; + +@each $elem in $elements { + ##{$elem} { + z-index: $zindex; + } + + $zindex: $zindex + 10; +} + +body.uiHidden { + .ingame_buildingsToolbar, + #ingame_HUD_PlacementHints, + #ingame_HUD_GameMenu, + #ingame_HUD_PinnedShapes, + #ingame_HUD_Notifications, + #ingame_HUD_TutorialHints, + #ingame_HUD_Waypoints, + #ingame_HUD_Waypoints_Hint { + display: none !important; + } +} + +body.modalDialogActive, +body.externalAdOpen, +body.ingameDialogOpen { + > *:not(.ingameDialog):not(.modalDialogParent):not(.loadingDialog):not(.gameLoadingOverlay):not(#ingame_HUD_ModalDialogs):not(.noBlur) { + // filter: blur(5px) !important; + } +} diff --git a/src/css/mixins.scss b/src/css/mixins.scss index ee0a9752..b40afe3e 100644 --- a/src/css/mixins.scss +++ b/src/css/mixins.scss @@ -2,8 +2,8 @@ /* Forces an element to get rendered on its own layer, increasing the performance when animated. Use only transform and opacity in animations! */ @mixin FastAnimation { - // will-change: transform, opacity; - transform: translateZ(0); + will-change: transform, opacity, filter; + // transform: translateZ(0); backface-visibility: hidden; -webkit-backface-visibility: hidden; } diff --git a/src/css/states/about.scss b/src/css/states/about.scss index aeac1e38..02025e03 100644 --- a/src/css/states/about.scss +++ b/src/css/states/about.scss @@ -1,6 +1,23 @@ #state_AboutState { > .container .content { + @include S(max-width, 600px); @include PlainText; + padding: 0; + background: transparent; + } + + .head { + @include S(padding, 20px); + + img { + display: block; + margin: 0 auto; + @include S(max-width, 200px); + } + } + + .text { + @include S(margin, 10px); } a { diff --git a/src/css/states/changelog.scss b/src/css/states/changelog.scss index 109f1d36..1daa5f04 100644 --- a/src/css/states/changelog.scss +++ b/src/css/states/changelog.scss @@ -1,5 +1,6 @@ #state_ChangelogState { .content { + @include S(max-width, 800px); display: flex; flex-direction: column; } diff --git a/src/css/states/main_menu.scss b/src/css/states/main_menu.scss index 0981cdfc..0d0a289e 100644 --- a/src/css/states/main_menu.scss +++ b/src/css/states/main_menu.scss @@ -1,518 +1,543 @@ -#state_MainMenuState { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - - // background: #aaacb4 center center / cover !important; - background: #bbc2cf center center / cover !important; - - .topButtons { - position: absolute; - @include S(top, 20px); - @include S(right, 20px); - display: grid; - grid-auto-flow: column; - @include S(grid-gap, 15px); - - .settingsButton, - .exitAppButton, - .languageChoose { - @include S(width, 25px); - @include S(height, 25px); - pointer-events: all; - cursor: pointer; - background: uiResource("icons/main_menu_settings.png") center center / contain no-repeat; - transition: opacity 0.12s ease-in-out; - @include IncreasedClickArea(2px); - &:hover { - opacity: 0.9; - } - } - - .exitAppButton { - background-image: uiResource("icons/main_menu_exit.png"); - } - - .languageChoose { - @include S(border-radius, 8px); - border: solid #222428; - background-color: #fff; - @include S(border-width, 2px); - background-size: cover; - } - } - - .fullscreenBackgroundVideo { - // display: none !important; - z-index: -1; - position: fixed; - right: 50%; - bottom: 50%; - min-width: 100%; - min-height: 100%; - - opacity: 0; - display: none; - transform: translate(50%, 50%); - filter: blur(10px); - - $opacity: 0.2; - &.loaded { - display: block; - opacity: $opacity; - - @include InlineAnimation(0.1s ease-in-out) { - 0% { - opacity: 0; - } - 100% { - opacity: $opacity; - } - } - } - } - - .mainWrapper { - @include S(padding, 0, 10px); - align-items: start; - justify-items: center; - - @include S(grid-column-gap, 10px); - display: grid; - grid-template-columns: 1fr; - - &.demo { - grid-template-columns: 1fr 1fr; - } - - .standaloneBanner { - background: rgb(255, 234, 245); - @include S(border-radius, $globalBorderRadius); - box-sizing: border-box; - @include S(padding, 15px); - - display: flex; - flex-direction: column; - - strong { - font-weight: bold; - @include S(margin, 0, 4px); - } - - h3 { - @include Heading; - font-weight: bold; - @include S(margin-bottom, 5px); - text-transform: uppercase; - color: $colorRedBright; - } - - p { - @include Text; - } - - ul { - @include S(margin-top, 5px); - @include S(padding-left, 20px); - li { - @include Text; - } - } - - .steamLink { - width: 100%; - @include S(height, 40px); - - background: uiResource("get_on_steam.png") center center / contain no-repeat; - overflow: hidden; - display: block; - text-indent: -999em; - cursor: pointer; - @include S(margin-top, 20px); - pointer-events: all; - transition: all 0.12s ease-in; - transition-property: opacity, transform; - transform: skewX(-0.5deg); - &:hover { - transform: skewX(-1deg) scale(1.02); - opacity: 0.9; - } - } - } - } - - .logo { - display: flex; - flex-grow: 1; - align-items: center; - justify-content: center; - - flex-direction: column; - @include S(padding-top, 20px); - img { - @include S(width, 350px); - } - - .demoBadge { - @include S(margin, 10px, 0); - @include S(width, 100px); - @include S(height, 30px); - background: uiResource("demo_badge.png") center center / contain no-repeat; - display: inline-block; - } - - position: relative; - .updateLabel { - position: absolute; - transform: translateX(50%) rotate(-5deg); - color: $colorRedBright; - @include Heading; - text-transform: uppercase; - font-weight: bold; - @include S(right, 40px); - @include S(bottom, 20px); - - @include InlineAnimation(1.3s ease-in-out infinite) { - 50% { - transform: translateX(50%) rotate(-7deg) scale(1.1); - } - } - } - } - - .betaWarning { - @include S(width, 400px); - @include PlainText; - background: $colorRedBright; - @include S(padding, 10px); - @include S(border-radius, $globalBorderRadius); - color: #fff; - @include S(margin-top, 10px); - border: #{D(2px)} solid rgba(0, 10, 20, 0.1); - } - - .sideContainer { - display: flex; - flex-direction: column; - @include S(width, 300px); - - .standaloneBanner { - flex-grow: 1; - @include S(margin-bottom, 10px); - } - - .contest { - flex-grow: 1; - background: rgb(32, 187, 166); - @include S(padding, 15px); - - h3 { - @include Heading; - color: #fff; - font-weight: bold; - text-transform: uppercase; - @include S(margin-bottom, 5px); - } - p { - color: #fff; - @include Text; - strong { - font-weight: bold; - } - @include S(margin-bottom, 5px); - } - - button { - background: #fff; - color: #333538; - } - } - } - - .mainContainer { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - background: #fafafa; - @include S(padding, 20px); - @include S(border-radius, $globalBorderRadius); - // border: #{D(2px)} solid rgba(0, 10, 20, 0.1); - height: 100%; - width: 100%; - box-sizing: border-box; - - .buttons { - display: flex; - flex-direction: column; - align-items: center; - } - - .browserWarning { - @include S(margin-bottom, 10px); - background-color: $colorRedBright; - @include PlainText; - color: #fff; - @include S(border-radius, $globalBorderRadius); - @include S(padding, 5px); - @include S(width, 300px); - } - - .playButton, - .continueButton { - @include SuperHeading; - @include S(min-width, 130px); - @include S(padding, 15px, 20px); - letter-spacing: 0.3em !important; - - font-weight: bold; - color: #fff; - background-color: $colorGreenBright; - transition: transform 0.12s ease-in-out; - &:hover { - transform: scale(1.02); - } - - &.continueButton { - @include Heading; - } - } - - .importButton { - @include S(margin-top, 15px); - } - - .newGameButton { - @include S(margin-top, 15px); - @include S(margin-left, 15px); - } - - .savegames { - @include S(max-height, 105px); - overflow-y: auto; - @include S(width, 250px); - pointer-events: all; - @include S(padding-right, 5px); - display: grid; - grid-auto-flow: row; - @include S(grid-gap, 5px); - @include S(margin-top, 10px); - - .savegame { - background: #eee; - @include S(border-radius, $globalBorderRadius); - @include S(padding, 5px); - display: grid; - grid-template-columns: 1fr auto auto; - grid-template-rows: auto auto; - @include S(grid-column-gap, 5px); - @include S(grid-row-gap, 3px); - - .playtime { - grid-column: 1 / 2; - grid-row: 2 / 3; - @include SuperSmallText; - opacity: 0.5; - } - - .level { - grid-column: 1 / 2; - grid-row: 1 / 2; - @include PlainText; - } - - button.resumeGame, - button.downloadGame, - button.deleteGame { - grid-column: 3 / 4; - grid-row: 1 / 3; - @include S(width, 30px); - @include S(height, 30px); - padding: 0; - align-self: center; - @include IncreasedClickArea(0px); - background: #44484a uiResource("icons/play.png") center center / 40% no-repeat; - } - - button.downloadGame { - grid-column: 2 / 3; - grid-row: 1 / 2; - background-image: uiResource("icons/download.png"); - @include S(width, 15px); - @include IncreasedClickArea(0px); - @include S(height, 15px); - align-self: end; - background-size: 60%; - } - - button.deleteGame { - grid-column: 2 / 3; - grid-row: 2 / 3; - background-color: $colorRedBright; - @include IncreasedClickArea(0px); - background-image: uiResource("icons/delete.png"); - @include S(width, 15px); - @include S(height, 15px); - align-self: end; - background-size: 60%; - } - } - } - } - - .footer { - display: grid; - flex-grow: 1; - justify-content: center; - align-items: flex-end; - width: 100%; - grid-template-columns: auto auto auto 1fr; - @include S(padding, 10px); - box-sizing: border-box; - @include S(grid-gap, 5px); - - .author { - flex-grow: 1; - text-align: right; - @include PlainText; - color: #888a8f; - a { - color: #333438; - } - } - - @include S(padding, 15px); - - > .boxLink { - display: grid; - align-items: center; - grid-template-columns: 1fr auto; - - justify-content: center; - background: #fdfdfd; - @include S(padding, 5px); - @include S(padding-left, 10px); - @include S(border-radius, $globalBorderRadius); - @include SuperSmallText(); - - font-weight: bold; - box-sizing: border-box; - text-transform: uppercase; - color: #616266; - - transition: all 0.12s ease-in-out; - transition-property: background-color, transform; - pointer-events: all; - @include S(width, 120px); - @include S(height, 60px); - - cursor: pointer; - &:hover { - background-color: #fff; - } - - .thirdpartyLogo { - display: inline-block; - @include S(width, 50px); - @include S(height, 50px); - background: center center / 80% no-repeat; - &.githubLogo { - background-image: uiResource("main_menu/github.png"); - } - &.discordLogo { - background-image: uiResource("main_menu/discord.png"); - background-size: 95%; - } - } - } - - > .sidelinks { - display: grid; - align-items: flex-start; - justify-content: flex-start; - grid-template-rows: 1fr 1fr 1fr; - @include S(grid-gap, 2px); - @include S(height, 60px); - - > a { - color: #616266; - background: #fdfdfd; - height: 100%; - - &:hover { - background-color: #fff; - } - @include SuperSmallText; - text-transform: uppercase; - width: 100%; - @include S(padding, 2px, 10px); - display: flex; - align-items: center; - justify-content: flex-start; - - @include S(padding-left, 25px); - box-sizing: border-box; - font-weight: bold; - background-position: #{D(5px)} center; - background-size: #{D(12px)}; - background-repeat: no-repeat; - - &.redditLink { - background-image: uiResource("main_menu/reddit.svg"); - } - &.changelog { - background-image: uiResource("main_menu/changelog.svg"); - } - &.helpTranslate { - background-image: uiResource("main_menu/translate.svg"); - } - } - } - } - - @include DarkThemeOverride { - background: $darkModeGameBackground center center / cover !important; - - .topButtons { - filter: invert(1); - - .languageChoose { - filter: invert(1); - } - } - - .mainContainer { - background: darken($darkModeGameBackground, 10); - - .savegames .savegame { - background: darken($darkModeGameBackground, 15); - color: white; - } - } - - .footer { - > a, - .sidelinks > a { - background-color: darken($darkModeGameBackground, 10); - color: #eee; - - &:hover { - background-color: darken($darkModeGameBackground, 8); - } - } - - .author { - color: #bdbdbd; - - > a { - color: white; - } - } - - .thirdpartyLogo.githubLogo { - filter: invert(1); - } - } - } -} +#state_MainMenuState { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + + // background: #aaacb4 center center / cover !important; + background: #bbc2cf center center / cover !important; + + .topButtons { + position: absolute; + @include S(top, 20px); + @include S(right, 20px); + display: grid; + grid-auto-flow: column; + @include S(grid-gap, 15px); + + .settingsButton, + .exitAppButton, + .languageChoose { + @include S(width, 25px); + @include S(height, 25px); + pointer-events: all; + cursor: pointer; + background: uiResource("icons/main_menu_settings.png") center center / contain no-repeat; + transition: opacity 0.12s ease-in-out; + @include IncreasedClickArea(2px); + &:hover { + opacity: 0.9; + } + } + + .exitAppButton { + background-image: uiResource("icons/main_menu_exit.png"); + } + + .languageChoose { + @include S(border-radius, 8px); + border: solid #222428; + background-color: #fff; + @include S(border-width, 2px); + background-size: cover; + } + } + + .fullscreenBackgroundVideo { + // display: none !important; + z-index: -1; + position: fixed; + right: 50%; + bottom: 50%; + min-width: 100%; + min-height: 100%; + + opacity: 0; + display: none; + transform: translate(50%, 50%); + filter: blur(D(3px)); + + $opacity: 0.2; + &.loaded { + display: block; + opacity: $opacity; + + @include InlineAnimation(0.1s ease-in-out) { + 0% { + opacity: 0; + } + 100% { + opacity: $opacity; + } + } + } + } + + .mainWrapper { + @include S(padding, 0, 10px); + align-items: start; + justify-items: center; + + @include S(grid-column-gap, 10px); + display: grid; + grid-template-columns: 1fr; + + &.demo { + grid-template-columns: 1fr 1fr; + } + + .standaloneBanner { + background: rgb(255, 234, 245); + @include S(border-radius, $globalBorderRadius); + box-sizing: border-box; + @include S(padding, 15px); + + display: flex; + flex-direction: column; + + strong { + font-weight: bold; + @include S(margin, 0, 4px); + } + + h3 { + @include Heading; + font-weight: bold; + @include S(margin-bottom, 5px); + text-transform: uppercase; + color: $colorRedBright; + } + + p { + @include Text; + } + + ul { + @include S(margin-top, 5px); + @include S(padding-left, 20px); + li { + @include Text; + } + } + + .steamLink { + width: 100%; + @include S(height, 40px); + + background: uiResource("get_on_steam.png") center center / contain no-repeat; + overflow: hidden; + display: block; + text-indent: -999em; + cursor: pointer; + @include S(margin-top, 20px); + pointer-events: all; + transition: all 0.12s ease-in; + transition-property: opacity, transform; + transform: skewX(-0.5deg); + &:hover { + transform: skewX(-1deg) scale(1.02); + opacity: 0.9; + } + } + } + } + + .logo { + display: flex; + flex-grow: 1; + align-items: center; + justify-content: center; + + flex-direction: column; + @include S(padding-top, 20px); + img { + @include S(width, 350px); + } + + .demoBadge { + @include S(margin, 10px, 0); + @include S(width, 100px); + @include S(height, 30px); + background: uiResource("demo_badge.png") center center / contain no-repeat; + display: inline-block; + } + + position: relative; + .updateLabel { + position: absolute; + transform: translateX(50%) rotate(-5deg); + color: $colorRedBright; + @include Heading; + text-transform: uppercase; + font-weight: bold; + @include S(right, 40px); + @include S(bottom, 20px); + + @include InlineAnimation(1.3s ease-in-out infinite) { + 50% { + transform: translateX(50%) rotate(-7deg) scale(1.1); + } + } + + @include DarkThemeOverride { + color: $colorBlueBright; + } + } + } + + .betaWarning { + @include S(width, 400px); + @include PlainText; + background: $colorRedBright; + @include S(padding, 10px); + @include S(border-radius, $globalBorderRadius); + color: #fff; + @include S(margin-top, 10px); + border: #{D(2px)} solid rgba(0, 10, 20, 0.1); + } + + .sideContainer { + display: flex; + flex-direction: column; + @include S(width, 300px); + + .standaloneBanner { + flex-grow: 1; + @include S(margin-bottom, 10px); + } + } + + .mainContainer { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + background: #fafafa; + @include S(padding, 20px); + @include S(border-radius, $globalBorderRadius); + // border: #{D(2px)} solid rgba(0, 10, 20, 0.1); + height: 100%; + width: 100%; + box-sizing: border-box; + + .buttons { + display: flex; + flex-direction: column; + align-items: center; + } + + .browserWarning { + @include S(margin-bottom, 10px); + background-color: $colorRedBright; + @include PlainText; + color: #fff; + @include S(border-radius, $globalBorderRadius); + @include S(padding, 5px); + @include S(width, 300px); + } + + .playButton, + .continueButton { + @include SuperHeading; + @include S(min-width, 130px); + @include S(padding, 15px, 20px); + letter-spacing: 0.3em !important; + @include IncreasedClickArea(0px); + font-weight: bold; + color: #fff; + background-color: $colorGreenBright; + transition: transform 0.12s ease-in-out, background-color 0.12s ease-in-out; + + &:hover { + background-color: darken($colorGreenBright, 4); + opacity: 1; + } + + &.continueButton { + @include Heading; + } + } + + .importButton { + @include S(margin-top, 15px); + @include IncreasedClickArea(0px); + } + + .newGameButton { + @include IncreasedClickArea(0px); + @include S(margin-top, 15px); + @include S(margin-left, 15px); + } + + .savegames { + @include S(max-height, 105px); + overflow-y: auto; + @include S(width, 250px); + pointer-events: all; + @include S(padding-right, 5px); + display: grid; + grid-auto-flow: row; + @include S(grid-gap, 5px); + @include S(margin-top, 10px); + + .savegame { + background: #eee; + @include S(border-radius, $globalBorderRadius); + @include S(padding, 5px); + display: grid; + grid-template-columns: 1fr 1fr auto auto; + grid-template-rows: auto auto; + @include S(grid-column-gap, 4px); + @include S(grid-row-gap, 1px); + + .playtime { + grid-column: 2 / 3; + grid-row: 2 / 3; + @include SuperSmallText; + opacity: 0.5; + } + + .level { + grid-column: 1 / 2; + grid-row: 2 / 3; + @include SuperSmallText; + opacity: 0.5; + } + + .name { + grid-column: 1 / 3; + grid-row: 1 / 2; + @include PlainText; + display: inline-flex; + align-items: center; + + > span { + display: inline-flex; + @include S(max-width, 140px); + overflow: hidden; + } + } + + button.resumeGame, + button.downloadGame, + button.deleteGame, + button.renameGame { + padding: 0; + align-self: center; + justify-self: center; + @include IncreasedClickArea(0px); + background: #44484a uiResource("icons/play.png") center center / 40% no-repeat; + } + + button.downloadGame { + grid-column: 3 / 4; + grid-row: 1 / 2; + background-color: $colorBlueBright; + background-image: uiResource("icons/download.png"); + @include S(width, 15px); + @include IncreasedClickArea(0px); + @include S(height, 15px); + background-size: 60%; + align-self: start; + } + + button.deleteGame { + grid-column: 3 / 4; + grid-row: 2 / 3; + background-color: $colorRedBright; + @include IncreasedClickArea(0px); + background-image: uiResource("icons/delete.png"); + @include S(width, 15px); + @include S(height, 15px); + align-self: end; + background-size: 60%; + } + + button.renameGame { + background-color: transparent; + @include IncreasedClickArea(2px); + background-image: uiResource("icons/edit_key.png"); + @include S(width, 10px); + @include S(height, 10px); + align-self: center; + justify-self: center; + + background-size: 90%; + opacity: 0.25; + @include S(margin-left, 4px); + + &:hover { + opacity: 0.35; + } + + @include DarkThemeInvert; + } + + button.resumeGame { + grid-column: 4 / 5; + grid-row: 1 / 3; + margin: 0; + @include S(width, 32px); + height: 100%; + } + } + } + } + + .footer { + display: grid; + flex-grow: 1; + justify-content: center; + align-items: flex-end; + width: 100%; + grid-template-columns: auto auto auto 1fr; + @include S(padding, 10px); + box-sizing: border-box; + @include S(grid-gap, 4px); + + .author { + flex-grow: 1; + text-align: right; + @include PlainText; + color: #888a8f; + a { + color: #333438; + } + } + + @include S(padding, 15px); + + > .boxLink { + display: grid; + align-items: center; + grid-template-columns: 1fr auto; + + justify-content: center; + background: #fdfdfd uiResource("icons/link.png") top D(3px) right D(3px) / D(9px) no-repeat; + @include S(padding, 5px); + @include S(padding-left, 10px); + @include S(border-radius, $globalBorderRadius); + @include SuperSmallText(); + + font-weight: bold; + box-sizing: border-box; + text-transform: uppercase; + color: #616266; + + transition: background-color 0.12s ease-in-out; + pointer-events: all; + @include S(width, 120px); + @include S(height, 60px); + + cursor: pointer; + &:hover { + background-color: #f0f6ff; + } + + .thirdpartyLogo { + display: inline-block; + @include S(width, 50px); + @include S(height, 50px); + background: center center / 80% no-repeat; + &.githubLogo { + background-image: uiResource("main_menu/github.png"); + } + &.discordLogo { + background-image: uiResource("main_menu/discord.png"); + background-size: 95%; + } + } + } + + > .sidelinks { + display: grid; + align-items: flex-start; + justify-content: flex-start; + grid-template-rows: 1fr 1fr 1fr; + @include S(grid-gap, 3px); + @include S(height, 60px); + + > a { + color: #616266; + background: #fdfdfd; + height: 100%; + + &:hover { + background-color: #f0f6ff; + } + @include SuperSmallText; + text-transform: uppercase; + width: 100%; + @include S(padding, 2px, 10px); + display: flex; + align-items: center; + justify-content: flex-start; + + @include S(padding-left, 25px); + box-sizing: border-box; + font-weight: bold; + background-position: #{D(5px)} center; + background-size: #{D(12px)}; + background-repeat: no-repeat; + @include S(border-radius, $globalBorderRadius); + + transition: background-color 0.12s ease-in-out; + + &.redditLink { + background-image: uiResource("main_menu/reddit.svg"); + } + &.changelog { + background-image: uiResource("main_menu/changelog.svg"); + } + &.helpTranslate { + background-image: uiResource("main_menu/translate.svg"); + } + } + } + } + + @include DarkThemeOverride { + background: $darkModeGameBackground center center / cover !important; + + .topButtons { + filter: invert(1); + + .languageChoose { + filter: invert(1); + } + } + + .mainContainer { + background: darken($darkModeGameBackground, 10); + + .savegames .savegame { + background: darken($darkModeGameBackground, 15); + color: white; + } + } + + .footer { + > a, + .sidelinks > a { + background-color: darken($darkModeGameBackground, 10); + color: #eee; + + &:hover { + background-color: darken($darkModeGameBackground, 8); + } + } + + .author { + color: #bdbdbd; + + > a { + color: white; + } + } + + .thirdpartyLogo.githubLogo { + filter: invert(1); + } + } + } +} diff --git a/src/css/states/settings.scss b/src/css/states/settings.scss index f06c9b31..9b7df8fb 100644 --- a/src/css/states/settings.scss +++ b/src/css/states/settings.scss @@ -1,113 +1,188 @@ -#state_SettingsState { - .content { - .versionbar { - @include S(margin-top, 20px); - @include SuperSmallText; - display: grid; - align-items: center; - grid-template-columns: 1fr auto; - .buildVersion { - display: flex; - flex-direction: column; - color: #aaadaf; - } - } - - button.about { - background-color: $colorGreenBright; - } - - .setting { - @include S(padding, 10px); - background: #eeeff5; - @include S(border-radius, $globalBorderRadius); - @include S(margin-bottom, 5px); - - label { - text-transform: uppercase; - @include Text; - } - - .desc { - @include S(margin-top, 5px); - @include SuperSmallText; - color: #aaadb2; - } - - > .row { - display: grid; - align-items: center; - grid-template-columns: 1fr auto; - } - - &.disabled { - // opacity: 0.3; - pointer-events: none; - * { - pointer-events: none !important; - cursor: default !important; - } - position: relative; - .standaloneOnlyHint { - @include PlainText; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - pointer-events: all; - display: flex; - align-items: center; - justify-content: center; - background: rgba(#fff, 0.5); - text-transform: uppercase; - color: $colorRedBright; - } - } - - .value.enum { - background: #fff; - @include PlainText; - display: flex; - align-items: flex-start; - pointer-events: all; - cursor: pointer; - justify-content: center; - @include S(min-width, 100px); - @include S(border-radius, $globalBorderRadius); - @include S(padding, 4px); - @include S(padding-right, 15px); - - background: #fff uiResource("icons/enum_selector.png") calc(100% - #{D(5px)}) - calc(50% + #{D(1px)}) / #{D(15px)} no-repeat; - - transition: background-color 0.12s ease-in-out; - &:hover { - background-color: #fafafa; - } - } - } - } - - @include DarkThemeOverride { - .content { - .setting { - background: darken($darkModeGameBackground, 10); - - .value.enum { - // dirty but works - filter: invert(0.85); - color: #222; - } - - .value.checkbox { - background-color: #74767b; - - &.checked { - background-color: $colorBlueBright; - } - } - } - } - } -} +#state_SettingsState { + $colorCategoryButton: #eee; + $colorCategoryButtonSelected: #5f748b; + + .container .content { + display: flex; + overflow-y: scroll; + + .categoryContainer { + width: 100%; + + .category { + display: none; + + &.active { + display: block; + } + + .setting { + @include S(padding, 10px); + background: #eeeff5; + @include S(border-radius, $globalBorderRadius); + @include S(margin-bottom, 5px); + + .desc { + @include S(margin-top, 5px); + @include SuperSmallText; + color: #aaadb2; + } + + > .row { + display: grid; + align-items: center; + grid-template-columns: 1fr auto; + + > label { + text-transform: uppercase; + @include Text; + } + } + + &.disabled { + // opacity: 0.3; + pointer-events: none; + * { + pointer-events: none !important; + cursor: default !important; + } + position: relative; + .standaloneOnlyHint { + @include PlainText; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + pointer-events: all; + display: flex; + align-items: center; + justify-content: center; + background: rgba(#fff, 0.5); + text-transform: uppercase; + color: $colorRedBright; + } + } + + .value.enum { + background: #fff; + @include PlainText; + display: flex; + align-items: flex-start; + pointer-events: all; + cursor: pointer; + justify-content: center; + @include S(min-width, 100px); + @include S(border-radius, $globalBorderRadius); + @include S(padding, 4px); + @include S(padding-right, 15px); + + background: #fff uiResource("icons/enum_selector.png") calc(100% - #{D(5px)}) + calc(50% + #{D(1px)}) / #{D(15px)} no-repeat; + + transition: background-color 0.12s ease-in-out; + &:hover { + background-color: #fafafa; + } + } + } + } + } + + .sidebar { + display: flex; + flex-direction: column; + @include S(min-width, 210px); + @include S(max-width, 320px); + width: 30%; + height: 100%; + position: sticky; + top: 0; + @include S(margin-left, 20px); + @include S(margin-right, 32px); + + .other { + margin-top: auto; + } + + button { + @include S(margin-top, 4px); + width: calc(100% - #{D(20px)}); + text-align: start; + + &::after { + content: unset; + } + } + + button.categoryButton, + button.about { + background-color: $colorCategoryButton; + color: #777a7f; + + &.active { + background-color: $colorCategoryButtonSelected; + color: #fff; + + &:hover { + opacity: 1; + } + } + + &.pressed { + transform: none !important; + } + } + + .versionbar { + @include S(margin-top, 20px); + @include SuperSmallText; + display: grid; + align-items: center; + grid-template-columns: 1fr auto; + .buildVersion { + display: flex; + flex-direction: column; + color: #aaadaf; + } + } + } + } + + @include DarkThemeOverride { + .container .content { + .sidebar { + button.categoryButton, + button.about { + background-color: #3f3f47; + + &.active { + background-color: $colorBlueBright; + } + } + } + + .categoryContainer { + .category { + .setting { + background: darken($darkModeGameBackground, 10); + + .value.enum { + // dirty but works + filter: invert(0.78) sepia(40%) hue-rotate(190deg); + color: #222; + } + + .value.checkbox { + background-color: #74767b; + + &.checked { + background-color: $colorBlueBright; + } + } + } + } + } + } + } +} diff --git a/src/css/textual_game_state.scss b/src/css/textual_game_state.scss index a8d7a31f..54c5dbb3 100644 --- a/src/css/textual_game_state.scss +++ b/src/css/textual_game_state.scss @@ -1,24 +1,18 @@ .gameState.textualState { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - $padding: 15px; - - .headerBar, - > .container .content { - @include S(width, 500px); - } + display: grid; + grid-template-rows: auto 1fr; + box-sizing: border-box; + @include S(padding, 32px); + height: 100vh; .headerBar { display: flex; - align-items: center; - justify-content: flex-start; h1 { - display: flex; - pointer-events: all; + display: grid; + grid-template-columns: auto 1fr; align-items: center; + pointer-events: all; cursor: pointer; @include SuperHeading; text-transform: uppercase; @@ -39,11 +33,17 @@ } > .container { + display: flex; + justify-content: center; + width: 100%; + overflow-y: auto; + > .content { + width: 100%; background: #fff; @include S(border-radius, $globalBorderRadius); @include S(padding, 10px); - height: calc(80vh - #{D(60px)}); + height: 100%; overflow-y: auto; box-sizing: border-box; pointer-events: all; diff --git a/src/css/variables.scss b/src/css/variables.scss index c1c69371..7646e471 100644 --- a/src/css/variables.scss +++ b/src/css/variables.scss @@ -1,4 +1,4 @@ -$globalBorderRadius: 0px; +$globalBorderRadius: 2px; // When to reduce control elements size for small devices $layoutExpandMinWidth: 340px; diff --git a/src/js/application.js b/src/js/application.js index 1726bd2d..e5e22b60 100644 --- a/src/js/application.js +++ b/src/js/application.js @@ -14,13 +14,9 @@ import { AdProviderInterface } from "./platform/ad_provider"; import { NoAdProvider } from "./platform/ad_providers/no_ad_provider"; import { AnalyticsInterface } from "./platform/analytics"; import { GoogleAnalyticsImpl } from "./platform/browser/google_analytics"; -import { NoGameAnalytics } from "./platform/browser/no_game_analytics"; import { SoundImplBrowser } from "./platform/browser/sound"; import { PlatformWrapperImplBrowser } from "./platform/browser/wrapper"; import { PlatformWrapperImplElectron } from "./platform/electron/wrapper"; -import { GameAnalyticsInterface } from "./platform/game_analytics"; -import { SoundInterface } from "./platform/sound"; -import { StorageInterface } from "./platform/storage"; import { PlatformWrapperInterface } from "./platform/wrapper"; import { ApplicationSettings } from "./profile/application_settings"; import { SavegameManager } from "./savegame/savegame_manager"; @@ -34,6 +30,12 @@ import { PreloadState } from "./states/preload"; import { SettingsState } from "./states/settings"; import { ShapezGameAnalytics } from "./platform/browser/game_analytics"; +/** + * @typedef {import("./platform/game_analytics").GameAnalyticsInterface} GameAnalyticsInterface + * @typedef {import("./platform/sound").SoundInterface} SoundInterface + * @typedef {import("./platform/storage").StorageInterface} StorageInterface + */ + const logger = createLogger("application"); // Set the name of the hidden property and the change event for visibility @@ -385,7 +387,7 @@ export class Application { } const scale = this.getEffectiveUiScale(); - waitNextFrame().then(() => document.documentElement.style.setProperty("--ui-scale", scale)); + waitNextFrame().then(() => document.documentElement.style.setProperty("--ui-scale", `${scale}`)); window.focus(); } } diff --git a/src/js/changelog.js b/src/js/changelog.js index 16a9d692..bbc4a4fa 100644 --- a/src/js/changelog.js +++ b/src/js/changelog.js @@ -1,298 +1,312 @@ -export const CHANGELOG = [ - { - version: "1.2.0", - date: "unreleased", - entries: [ - "WIRES", - "Allow holding ALT in belt planner to reverse direction (by jakobhellermann)", - "Clear cursor when trying to pipette the same building twice (by hexy)", - "Allow binding TAB (by swtw7466)", - "Added keybinding to close menus (by isaisstillalive / Sandwichs-del)", - "Fix rare crash regarding the buildings toolbar (by isaisstillalive)", - "Fixed some phrases (by EnderDoom77)", - "Zoom towards mouse cursor (by Dimava)", - "Updated the soundtrack again, it is now 20 minutes in total!", - "Updated and added new translations (Thanks to all contributors!)", - "Allow editing waypoints (by isaisstillalive)", - "Show confirmation when cutting area which is too expensive to get pasted again (by isaisstillalive)", - "Show mouse and camera tile on debug overlay (F4) (by dengr)", - "Fix tunnels entrances connecting to exits sometimes when they shouldn't", - "The initial belt planner direction is now based on the cursor movement (by MizardX)", - "Fix preferred variant not getting saved when clicking on the hud (by Danacus)", - ], - }, - { - version: "1.1.19", - date: "02.07.2020", - entries: [ - "There are now notifications every 15 minutes in the demo version to buy the full version (For further details and the reason, check the #surveys channel in the discord)", - "I'm still working on the wires update, I hope to release it mid july!", - ], - }, - { - version: "1.1.18", - date: "27.06.2020", - entries: [ - "Huge performance improvements - up to double fps and tick-rate! This will wipe out all current items on belts.", - "Reduce story shapes required until unlocking blueprints", - "Allow clicking on variants to select them", - "Add 'copy key' button to shape viewer", - "Add more FPS to the belt animation and fix belt animation seeming to go 'backwards' on high belt speeds", - "Fix deconstruct sound being played when right clicking hub", - "Allow clicking 'Q' over a shape or color patch to automatically select the miner building (by Gerdon262)", - "Update belt placement performance on huge factories (by Phlosioneer)", - "Fix duplicate waypoints with a shape not rendering (by hexy)", - "Fix smart tunnel placement deleting wrong tunnels (by mordof)", - "Add setting (on by default) to store the last used rotation per building instead of globally storing it (by Magos)", - "Added chinese (traditional) translation", - "Updated translations", - ], - }, - { - version: "1.1.17", - date: "22.06.2020", - entries: [ - "Color blind mode! You can now activate it in the settings and it will show you which color is below your cursor (Either resource or on the belt)", - "Add info buttons to all shapes so you can figure out how they are built! (And also, which colors they have)", - "Allow configuring autosave interval and disabling it in the settings", - "The smart-tunnel placement has been reworked to properly replace belts. Thus the setting has been turned on again by default", - "The soundtrack now has a higher quality on the standalone version than the web version", - "Add setting to disable cut/delete warnings (by hexy)", - "Fix bug where belts in blueprints don't orient correctly (by hexy)", - "Fix camera moving weird after dragging and holding (by hexy)", - "Fix keybinding for pipette showing while pasting blueprints", - "Improve visibility of shape background in dark mode", - "Added sound when destroying a building", - "Added swedish translation", - "Update tutorial image for tier 2 tunnels to explain mix/match (by jimmyshadow1)", - ], - }, - { - version: "1.1.16", - date: "21.06.2020", - entries: [ - "You can now pickup buildings below your cursor with 'Q'!", - "The game soundtrack has been extended! There are now 4 songs with over 13 minutes of playtime from Peppsen!", - "Refactor keybindings overlay to show more appropriate keybindings", - "Show keybindings for area-select in the upper left instead", - "Automatically deselect area when selecting a new building", - "Raise markers limit from 14 characters to 71 (by Joker-vD)", - "Optimize performance by caching extractor items (by Phlosioneer)", - "Added setting to enable compact building infos, which only show ratios and hide the image / description", - "Apply dark theme to menu as well (by dengr1065)", - "Fix belt planner not placing the last belt", - "Fix buildings getting deleted when right clicking while placing a blueprint", - "Fix for exporting screenshots for huge bases (It was showing an empty file) (by xSparfuchs)", - "Fix buttons not responding when using right click directly after left click (by davidburhans)", - "Fix hub marker being hidden by building info panel", - "Disable dialog background blur since it can cause performance issues", - "Added simplified chinese translations", - "Update translations (Thanks to all translators!)", - ], - }, - { - version: "1.1.15", - date: "17.06.2020", - entries: [ - "You can now place straight belts (and tunnels) by holding SHIFT! (For you, @giantwaffle ❤️)", - "Added continue button to main menu and add seperate 'New game' button (by jaysc)", - "Added setting to disable smart tunnel placement introduced with the last update", - "Added setting to disable vignette", - "Update translations", - ], - }, - { - version: "1.1.14", - date: "16.06.2020", - entries: [ - "There is now an indicator (compass) to the HUB for the HUB Marker!", - "You can now include shape short keys in markers to render shape icons instead of text!", - "Added mirrored variant of the painter", - "When placing tunnels, unnecessary belts inbetween are now removed!", - "You can now drag tunnels and they will automatically expand! (Just try it out, its intuitive)", - ], - }, - { - version: "1.1.13", - date: "15.06.2020", - entries: [ - "Added shift modifier for faster pan (by jaysc)", - "Added Japanese translations", - "Added Portuguese (Portugal) translations", - "Updated icon for Spanish (Latin America) - It was showing a Spanish flag before", - "Updated existing translations", - ], - }, - { - version: "1.1.12", - date: "14.06.2020", - entries: [ - "Huge performance improvements! The game should now run up to 60% faster!", - "Added norwegian translation", - ], - }, - { - version: "1.1.11", - date: "13.06.2020", - entries: [ - "Pinned shapes are now smart, they dynamically update their goal and also unpin when no longer required. Completed objectives are now rendered transparent.", - "You can now cut areas, and also paste the last blueprint again! (by hexy)", - "You can now export your whole base as an image by pressing F3!", - "Improve upgrade number rounding, so there are no goals like '37.4k', instead it will now be '35k'", - "You can now configure the camera movement speed when using WASD (by mini-bomba)", - "Selecting an area now is relative to the world and thus does not move when moving the screen (by Dimava)", - "Allow higher tick-rates up to 500hz (This will burn your PC!)", - "Fix bug regarding number rounding", - "Fix dialog text being hardly readable in dark theme", - "Fix app not starting when the savegames were corrupted - there is now a better error message as well.", - "Further translation updates - Big thanks to all contributors!", - ], - }, - { - version: "1.1.10", - date: "12.06.2020", - entries: [ - "There are now linux builds on steam! Please report any issues in the discord!", - "Steam cloud saves are now available!", - "Added and update more translations (Big thank you to all translators!)", - "Prevent invalid connection if existing underground tunnel entrance exists (by jaysc)", - ], - }, - { - version: "1.1.9", - date: "11.06.2020", - entries: [ - "Support for translations! Interested in helping out? Check out the translation guide!", - "Update stacker artwork to clarify how it works", - "Update keybinding hints on the top left to be more accurate", - "Make it more clear when blueprints are unlocked when trying to use them", - "Fix pinned shape icons not being visible in dark mode", - "Fix being able to select buildings via hotkeys in map overview mode", - "Make shapes unpinnable in the upgrades tab (By hexy)", - ], - }, - { - version: "1.1.8", - date: "07.06.2020", - entries: [ - "You can now purchase the standalone on steam! View steam page", - "Added ability to create markers in the demo, but only two.", - "Contest #01 has ended! I'll now work through the entries, select the 5 I like most and present them to the community to vote for!", - ], - }, - { - version: "1.1.7", - date: "04.06.2020", - entries: ["HOTFIX: Fix savegames not showing up on the standalone version"], - }, - { - version: "1.1.6", - date: "04.06.2020", - entries: [ - "The steam release will happen on the 7th of June - Be sure to add it to your wishlist! View on steam", - "Fixed level complete dialog being blurred when the shop was opened before", - "Standalone: Increased icon visibility for windows builds", - "Web version: Fixed firefox not loading the game when browsing in private mode", - ], - }, - - { - version: "1.1.5", - date: "03.06.2020", - entries: ["Added weekly contests!"], - }, - { - version: "1.1.4", - date: "01.06.2020", - entries: ["Add 'interactive' tutorial for the first level to improve onboarding experience"], - }, - { - version: "1.1.3", - date: "01.06.2020", - entries: [ - "Added setting to configure zoom / mouse wheel / touchpad sensitivity", - "Fix belts being too slow when copied via blueprint (by Dimava)", - "Allow binding mouse buttons to actions (by Dimava)", - "Increase readability of certain HUD elements", - ], - }, - { - version: "1.1.2", - date: "30.05.2020", - entries: [ - "The official trailer is now ready! Check it out here!", - "The steam page is now live!", - "Experimental linux builds are now available! Please give me feedback on them in the discord", - "Allow hovering pinned shapes to enlarge them", - "Allow deselecting blueprints with right click and 'Q'", - "Move default key for deleting from 'X' to 'DEL'", - "Show confirmation when deleting more than 100 buildings", - "Reintroduce 'SPACE' keybinding to center on map", - "Improved keybinding hints", - "Fixed some keybindings showing as 'undefined'", - ], - }, - { - version: "1.1.1", - date: "28.05.2020", - entries: ["Fix crash when 'Show Hints' setting was turned off"], - }, - { - version: "1.1.0", - date: "28.05.2020", - entries: [ - "BLUEPRINTS! They are unlocked at level 12 and cost a special shape to build.", - "MAP MARKERS! Press 'M' to create a waypoint and be able to jump to it", - "Savegame levels are now shown in the main menu. For existing games, save them again to make the level show up.", - "Allow holding SHIFT to rotate counter clockwise", - "Added confirmation when deleting more than 500 buildings at a time", - "Added background to toolbar to increase contrast", - "Further decerase requirements of first levels", - "Pinned shapes now are saved", - "Allow placing extractors anywhere again, but they don't work at all if not placed on a resource", - "Show dialog explaining some keybindings after completing level 4", - "Fix keys being stuck when opening a dialog", - "Swapped shape order for painting upgrades", - "Allow changing all keybindings, including CTRL, ALT and SHIFT (by Dimava)", - "Fix cycling through keybindings selecting locked buildings as well (by Dimava)", - "There is now a github action, checking all pull requests with eslint. (by mrHedgehog)", - ], - }, - { - version: "1.0.4", - date: "26.05.2020", - entries: [ - "Reduce cost of first painting upgrade, and change 'Shape Processing' to 'Cutting, Rotating & Stacking'", - "Add dialog after completing level 2 to check out the upgrades tab.", - "Allow changing the keybindings in the demo version", - ], - }, - { - version: "1.0.3", - date: "24.05.2020", - entries: [ - "Reduced the amount of shapes required for the first 5 levels to make it easier to get into the game.", - ], - }, - { - version: "1.0.2", - date: "23.05.2020", - entries: [ - "Introduced changelog", - "Removed 'early access' label because the game isn't actually early access - its in a pretty good state already! (No worries, a lot more updates will follow!)", - "Added a 'Show hint' button which shows a small video for almost all levels to help out", - "Now showing proper descriptions when completing levels, with instructions on what the gained reward does.", - "Show a landing page on mobile devices about the game not being ready to be played on mobile yet", - "Fix painters and mixers being affected by the shape processors upgrade and not the painter one", - "Added 'multiplace' setting which is equivalent to holding SHIFT all the time", - "Added keybindings to zoom in / zoom out", - "Tunnels now also show connection lines to tunnel exits, instead of just tunnel entries", - "Lots of minor fixes and improvements", - ], - }, - { - version: "1.0.1", - date: "21.05.2020", - entries: ["Initial release!"], - }, -]; +export const CHANGELOG = [ + { + version: "1.2.0", + date: "unreleased", + entries: [ + "WIRES", + "Reworked menu UI design (by dengr1605)", + "Allow holding ALT in belt planner to reverse direction (by jakobhellermann)", + "Clear cursor when trying to pipette the same building twice (by hexy)", + "Fixed level 18 stacker bug: If you experienced it already, you know it, if not, I don't want to spoiler (by hexy)", + "Added keybinding to close menus (by isaisstillalive / Sandwichs-del)", + "Fix rare crash regarding the buildings toolbar (by isaisstillalive)", + "Fixed some phrases (by EnderDoom77)", + "Zoom towards mouse cursor (by Dimava)", + "Added multiple settings to optimize the performance", + "Updated the soundtrack again, it is now 40 minutes in total!", + "Added a button to the statistics dialog to disable the sorting (by squeek502)", + "Tier 2 tunnels are now 9 tiles wide, so the gap between is 8 tiles (double the tier 1 range)", + "Updated and added new translations (Thanks to all contributors!)", + "Show connected chained miners on hover", + "Added setting to be able to delete buildings while placing (inspired by hexy)", + "You can now adjust the sound and music volumes! (inspired by Yoshie2000)", + "Some hud elements now have reduced opacity when hovering, so you can see through (inspired by mvb005)", + "Mark pinned shapes in statistics dialog and show them first (inspired by davidburhans)", + "Added setting to show chunk borders", + "Quad painters have been reworked! They now are integrated with the wires, and only paint the shape when the value is 1 (inspired by dengr1605)", + "There are now compact 1x1 splitters available to be unlocked!", + "Replaced level completion sound to be less distracting", + "Allow editing waypoints (by isaisstillalive)", + "Show confirmation when cutting area which is too expensive to get pasted again (by isaisstillalive)", + "Show mouse and camera tile on debug overlay (F4) (by dengr)", + "Fixed tunnels entrances connecting to exits sometimes when they shouldn't", + "Added setting to auto select the extractor when pipetting a resource patch (by Exund)", + "The initial belt planner direction is now based on the cursor movement (by MizardX)", + "Fix preferred variant not getting saved when clicking on the hud (by Danacus)", + ], + }, + { + version: "1.1.19", + date: "02.07.2020", + entries: [ + "There are now notifications every 15 minutes in the demo version to buy the full version (For further details and the reason, check the #surveys channel in the Discord)", + "I'm still working on the wires update, I hope to release it mid july!", + ], + }, + { + version: "1.1.18", + date: "27.06.2020", + entries: [ + "Huge performance improvements - up to double fps and tick-rate! This will wipe out all current items on belts.", + "Reduce story shapes required until unlocking blueprints", + "Allow clicking on variants to select them", + "Add 'copy key' button to shape viewer", + "Add more FPS to the belt animation and fix belt animation seeming to go 'backwards' on high belt speeds", + "Fix deconstruct sound being played when right clicking hub", + "Allow clicking 'Q' over a shape or color patch to automatically select the miner building (by Gerdon262)", + "Update belt placement performance on huge factories (by Phlosioneer)", + "Fix duplicate waypoints with a shape not rendering (by hexy)", + "Fix smart tunnel placement deleting wrong tunnels (by mordof)", + "Add setting (on by default) to store the last used rotation per building instead of globally storing it (by Magos)", + "Added chinese (traditional) translation", + "Updated translations", + ], + }, + { + version: "1.1.17", + date: "22.06.2020", + entries: [ + "Color blind mode! You can now activate it in the settings and it will show you which color is below your cursor (Either resource or on the belt)", + "Add info buttons to all shapes so you can figure out how they are built! (And also, which colors they have)", + "Allow configuring autosave interval and disabling it in the settings", + "The smart-tunnel placement has been reworked to properly replace belts. Thus the setting has been turned on again by default", + "The soundtrack now has a higher quality on the standalone version than the web version", + "Add setting to disable cut/delete warnings (by hexy)", + "Fix bug where belts in blueprints don't orient correctly (by hexy)", + "Fix camera moving weird after dragging and holding (by hexy)", + "Fix keybinding for pipette showing while pasting blueprints", + "Improve visibility of shape background in dark mode", + "Added sound when destroying a building", + "Added swedish translation", + "Update tutorial image for tier 2 tunnels to explain mix/match (by jimmyshadow1)", + ], + }, + { + version: "1.1.16", + date: "21.06.2020", + entries: [ + "You can now pickup buildings below your cursor with 'Q'!", + "The game soundtrack has been extended! There are now 4 songs with over 13 minutes of playtime from Peppsen!", + "Refactor keybindings overlay to show more appropriate keybindings", + "Show keybindings for area-select in the upper left instead", + "Automatically deselect area when selecting a new building", + "Raise markers limit from 14 characters to 71 (by Joker-vD)", + "Optimize performance by caching extractor items (by Phlosioneer)", + "Added setting to enable compact building infos, which only show ratios and hide the image / description", + "Apply dark theme to menu as well (by dengr1065)", + "Fix belt planner not placing the last belt", + "Fix buildings getting deleted when right clicking while placing a blueprint", + "Fix for exporting screenshots for huge bases (It was showing an empty file) (by xSparfuchs)", + "Fix buttons not responding when using right click directly after left click (by davidburhans)", + "Fix hub marker being hidden by building info panel", + "Disable dialog background blur since it can cause performance issues", + "Added simplified chinese translations", + "Update translations (Thanks to all translators!)", + ], + }, + { + version: "1.1.15", + date: "17.06.2020", + entries: [ + "You can now place straight belts (and tunnels) by holding SHIFT! (For you, @giantwaffle ❤️)", + "Added continue button to main menu and add seperate 'New game' button (by jaysc)", + "Added setting to disable smart tunnel placement introduced with the last update", + "Added setting to disable vignette", + "Update translations", + ], + }, + { + version: "1.1.14", + date: "16.06.2020", + entries: [ + "There is now an indicator (compass) to the HUB for the HUB Marker!", + "You can now include shape short keys in markers to render shape icons instead of text!", + "Added mirrored variant of the painter", + "When placing tunnels, unnecessary belts inbetween are now removed!", + "You can now drag tunnels and they will automatically expand! (Just try it out, its intuitive)", + ], + }, + { + version: "1.1.13", + date: "15.06.2020", + entries: [ + "Added shift modifier for faster pan (by jaysc)", + "Added Japanese translations", + "Added Portuguese (Portugal) translations", + "Updated icon for Spanish (Latin America) - It was showing a Spanish flag before", + "Updated existing translations", + ], + }, + { + version: "1.1.12", + date: "14.06.2020", + entries: [ + "Huge performance improvements! The game should now run up to 60% faster!", + "Added norwegian translation", + ], + }, + { + version: "1.1.11", + date: "13.06.2020", + entries: [ + "Pinned shapes are now smart, they dynamically update their goal and also unpin when no longer required. Completed objectives are now rendered transparent.", + "You can now cut areas, and also paste the last blueprint again! (by hexy)", + "You can now export your whole base as an image by pressing F3!", + "Improve upgrade number rounding, so there are no goals like '37.4k', instead it will now be '35k'", + "You can now configure the camera movement speed when using WASD (by mini-bomba)", + "Selecting an area now is relative to the world and thus does not move when moving the screen (by Dimava)", + "Allow higher tick-rates up to 500hz (This will burn your PC!)", + "Fix bug regarding number rounding", + "Fix dialog text being hardly readable in dark theme", + "Fix app not starting when the savegames were corrupted - there is now a better error message as well.", + "Further translation updates - Big thanks to all contributors!", + ], + }, + { + version: "1.1.10", + date: "12.06.2020", + entries: [ + "There are now linux builds on steam! Please report any issues in the Discord!", + "Steam cloud saves are now available!", + "Added and update more translations (Big thank you to all translators!)", + "Prevent invalid connection if existing underground tunnel entrance exists (by jaysc)", + ], + }, + { + version: "1.1.9", + date: "11.06.2020", + entries: [ + "Support for translations! Interested in helping out? Check out the translation guide!", + "Update stacker artwork to clarify how it works", + "Update keybinding hints on the top left to be more accurate", + "Make it more clear when blueprints are unlocked when trying to use them", + "Fix pinned shape icons not being visible in dark mode", + "Fix being able to select buildings via hotkeys in map overview mode", + "Make shapes unpinnable in the upgrades tab (By hexy)", + ], + }, + { + version: "1.1.8", + date: "07.06.2020", + entries: [ + "You can now purchase the standalone on steam! View steam page", + "Added ability to create markers in the demo, but only two.", + "Contest #01 has ended! I'll now work through the entries, select the 5 I like most and present them to the community to vote for!", + ], + }, + { + version: "1.1.7", + date: "04.06.2020", + entries: ["HOTFIX: Fix savegames not showing up on the standalone version"], + }, + { + version: "1.1.6", + date: "04.06.2020", + entries: [ + "The steam release will happen on the 7th of June - Be sure to add it to your wishlist! View on steam", + "Fixed level complete dialog being blurred when the shop was opened before", + "Standalone: Increased icon visibility for windows builds", + "Web version: Fixed firefox not loading the game when browsing in private mode", + ], + }, + + { + version: "1.1.5", + date: "03.06.2020", + entries: ["Added weekly contests!"], + }, + { + version: "1.1.4", + date: "01.06.2020", + entries: ["Add 'interactive' tutorial for the first level to improve onboarding experience"], + }, + { + version: "1.1.3", + date: "01.06.2020", + entries: [ + "Added setting to configure zoom / mouse wheel / touchpad sensitivity", + "Fix belts being too slow when copied via blueprint (by Dimava)", + "Allow binding mouse buttons to actions (by Dimava)", + "Increase readability of certain HUD elements", + ], + }, + { + version: "1.1.2", + date: "30.05.2020", + entries: [ + "The official trailer is now ready! Check it out here!", + "The steam page is now live!", + "Experimental linux builds are now available! Please give me feedback on them in the Discord", + "Allow hovering pinned shapes to enlarge them", + "Allow deselecting blueprints with right click and 'Q'", + "Move default key for deleting from 'X' to 'DEL'", + "Show confirmation when deleting more than 100 buildings", + "Reintroduce 'SPACE' keybinding to center on map", + "Improved keybinding hints", + "Fixed some keybindings showing as 'undefined'", + ], + }, + { + version: "1.1.1", + date: "28.05.2020", + entries: ["Fix crash when 'Show Hints' setting was turned off"], + }, + { + version: "1.1.0", + date: "28.05.2020", + entries: [ + "BLUEPRINTS! They are unlocked at level 12 and cost a special shape to build.", + "MAP MARKERS! Press 'M' to create a waypoint and be able to jump to it", + "Savegame levels are now shown in the main menu. For existing games, save them again to make the level show up.", + "Allow holding SHIFT to rotate counter clockwise", + "Added confirmation when deleting more than 500 buildings at a time", + "Added background to toolbar to increase contrast", + "Further decerase requirements of first levels", + "Pinned shapes now are saved", + "Allow placing extractors anywhere again, but they don't work at all if not placed on a resource", + "Show dialog explaining some keybindings after completing level 4", + "Fix keys being stuck when opening a dialog", + "Swapped shape order for painting upgrades", + "Allow changing all keybindings, including CTRL, ALT and SHIFT (by Dimava)", + "Fix cycling through keybindings selecting locked buildings as well (by Dimava)", + "There is now a github action, checking all pull requests with eslint. (by mrHedgehog)", + ], + }, + { + version: "1.0.4", + date: "26.05.2020", + entries: [ + "Reduce cost of first painting upgrade, and change 'Shape Processing' to 'Cutting, Rotating & Stacking'", + "Add dialog after completing level 2 to check out the upgrades tab.", + "Allow changing the keybindings in the demo version", + ], + }, + { + version: "1.0.3", + date: "24.05.2020", + entries: [ + "Reduced the amount of shapes required for the first 5 levels to make it easier to get into the game.", + ], + }, + { + version: "1.0.2", + date: "23.05.2020", + entries: [ + "Introduced changelog", + "Removed 'early access' label because the game isn't actually early access - its in a pretty good state already! (No worries, a lot more updates will follow!)", + "Added a 'Show hint' button which shows a small video for almost all levels to help out", + "Now showing proper descriptions when completing levels, with instructions on what the gained reward does.", + "Show a landing page on mobile devices about the game not being ready to be played on mobile yet", + "Fix painters and mixers being affected by the shape processors upgrade and not the painter one", + "Added 'multiplace' setting which is equivalent to holding SHIFT all the time", + "Added keybindings to zoom in / zoom out", + "Tunnels now also show connection lines to tunnel exits, instead of just tunnel entries", + "Lots of minor fixes and improvements", + ], + }, + { + version: "1.0.1", + date: "21.05.2020", + entries: ["Initial release!"], + }, +]; diff --git a/src/js/core/animation_frame.js b/src/js/core/animation_frame.js index 0e921174..eeefb4b0 100644 --- a/src/js/core/animation_frame.js +++ b/src/js/core/animation_frame.js @@ -14,12 +14,11 @@ export class AnimationFrame { this.frameEmitted = new Signal(); this.bgFrameEmitted = new Signal(); - this.lastTime = null; - this.bgLastTime = null; + this.lastTime = performance.now(); + this.bgLastTime = performance.now(); this.boundMethod = this.handleAnimationFrame.bind(this); - /** @type {Worker} */ this.backgroundWorker = new BackgroundAnimationFrameEmitterWorker(); this.backgroundWorker.addEventListener("error", err => { logger.error("Error in background fps worker:", err); @@ -27,22 +26,16 @@ export class AnimationFrame { this.backgroundWorker.addEventListener("message", this.handleBackgroundTick.bind(this)); } - /** - * - * @param {MessageEvent} event - */ - handleBackgroundTick(event) { + handleBackgroundTick() { const time = performance.now(); - if (!this.bgLastTime) { - // First update, first delta is always 16ms - this.bgFrameEmitted.dispatch(1000 / 60); - } else { - let dt = time - this.bgLastTime; - if (dt > maxDtMs) { - dt = resetDtMs; - } - this.bgFrameEmitted.dispatch(dt); + + let dt = time - this.bgLastTime; + + if (dt > maxDtMs) { + dt = resetDtMs; } + + this.bgFrameEmitted.dispatch(dt); this.bgLastTime = time; } @@ -52,18 +45,15 @@ export class AnimationFrame { } handleAnimationFrame(time) { - if (!this.lastTime) { - // First update, first delta is always 16ms - this.frameEmitted.dispatch(1000 / 60); - } else { - let dt = time - this.lastTime; - if (dt > maxDtMs) { - // warn(this, "Clamping", dt, "to", resetDtMs); - dt = resetDtMs; - } - this.frameEmitted.dispatch(dt); + let dt = time - this.lastTime; + + if (dt > maxDtMs) { + dt = resetDtMs; } + + this.frameEmitted.dispatch(dt); this.lastTime = time; + window.requestAnimationFrame(this.boundMethod); } } diff --git a/src/js/core/async_compression.js b/src/js/core/async_compression.js index b11f8fd5..ddc780cc 100644 --- a/src/js/core/async_compression.js +++ b/src/js/core/async_compression.js @@ -1,7 +1,9 @@ // @ts-ignore import CompressionWorker from "../webworkers/compression.worker"; + import { createLogger } from "./logging"; -import { compressX64 } from "./lzstring"; +import { round2Digits } from "./utils"; + const logger = createLogger("async_compression"); export let compressionPrefix = String.fromCodePoint(1); @@ -35,7 +37,6 @@ if (!checkCryptPrefix(compressionPrefix)) { class AsynCompression { constructor() { - /** @type {Worker} */ this.worker = new CompressionWorker(); this.currentJobId = 1000; @@ -52,7 +53,15 @@ class AsynCompression { } const duration = performance.now() - jobData.startTime; - // log(this, "Got response from worker within", duration.toFixed(2), "ms"); + logger.log( + "Got job", + jobId, + "response within", + round2Digits(duration), + "ms: ", + result.length, + "bytes" + ); const resolver = jobData.resolver; delete this.currentJobs[jobId]; resolver(result); @@ -72,12 +81,13 @@ class AsynCompression { } /** - * Compresses file - * @param {string} text + * Compresses any object + * @param {any} obj */ - compressFileAsync(text) { - return this.internalQueueJob("compressFile", { - text, + compressObjectAsync(obj) { + logger.log("Compressing object async (optimized)"); + return this.internalQueueJob("compressObject", { + obj, compressionPrefix, }); } @@ -100,6 +110,8 @@ class AsynCompression { resolver: resolve, startTime: performance.now(), }; + + logger.log("Posting job", job, "/", jobId); this.worker.postMessage({ jobId, job, data }); }); } diff --git a/src/js/core/atlas_definitions.js b/src/js/core/atlas_definitions.js index 42cd2bce..38d36b59 100644 --- a/src/js/core/atlas_definitions.js +++ b/src/js/core/atlas_definitions.js @@ -1,20 +1,38 @@ /** + * @typedef {{ w: number, h: number }} Size + * @typedef {{ x: number, y: number }} Position * @typedef {{ - * frame: { x: number, y: number, w: number, h: number }, - * rotated: false, - * spriteSourceSize: { x: number, y: number, w: number, h: number }, - * sourceSize: { w: number, h: number}, - * trimmed: true + * frame: Position & Size, + * rotated: boolean, + * spriteSourceSize: Position & Size, + * sourceSize: Size, + * trimmed: boolean * }} SpriteDefinition + * + * @typedef {{ + * app: string, + * version: string, + * image: string, + * format: string, + * size: Size, + * scale: string, + * smartupdate: string + * }} AtlasMeta + * + * @typedef {{ + * frames: Object., + * meta: AtlasMeta + * }} SourceData */ export class AtlasDefinition { - constructor(sourceData) { - this.sourceFileName = sourceData.meta.image; - this.meta = sourceData.meta; - - /** @type {Object.} */ - this.sourceData = sourceData.frames; + /** + * @param {SourceData} sourceData + */ + constructor({ frames, meta }) { + this.meta = meta; + this.sourceData = frames; + this.sourceFileName = meta.image; } getFullSourcePath() { @@ -22,6 +40,7 @@ export class AtlasDefinition { } } +/** @type {AtlasDefinition[]} **/ export const atlasFiles = require // @ts-ignore .context("../../../res_built/atlas/", false, /.*\.json/i) diff --git a/src/js/core/background_resources_loader.js b/src/js/core/background_resources_loader.js index ff99d23c..b3a7671b 100644 --- a/src/js/core/background_resources_loader.js +++ b/src/js/core/background_resources_loader.js @@ -7,6 +7,7 @@ import { createLogger } from "./logging"; import { Signal } from "./signal"; import { SOUNDS, MUSIC } from "../platform/sound"; import { AtlasDefinition, atlasFiles } from "./atlas_definitions"; +import { initBuildingCodesAfterResourcesLoaded } from "../game/meta_building_registry"; const logger = createLogger("background_loader"); @@ -114,8 +115,8 @@ export class BackgroundResourcesLoader { }) .then(() => { logger.log("⏰ Finish load: bare game"); - Loader.createAtlasLinks(); this.bareGameReady = true; + initBuildingCodesAfterResourcesLoaded(); this.signalBareGameLoaded.dispatch(); this.internalStartLoadingAdditionalGameAssets(); }); diff --git a/src/js/core/buffer_maintainer.js b/src/js/core/buffer_maintainer.js index c92a92a5..3d466f14 100644 --- a/src/js/core/buffer_maintainer.js +++ b/src/js/core/buffer_maintainer.js @@ -13,7 +13,7 @@ import { round1Digit } from "./utils"; const logger = createLogger("buffers"); -const bufferGcDurationSeconds = 10; +const bufferGcDurationSeconds = 5; export class BufferMaintainer { /** @@ -27,6 +27,31 @@ export class BufferMaintainer { this.iterationIndex = 1; this.lastIteration = 0; + + this.root.signals.gameFrameStarted.add(this.update, this); + } + + /** + * Returns the buffer stats + */ + getStats() { + let stats = { + rootKeys: 0, + subKeys: 0, + vramBytes: 0, + }; + this.cache.forEach((subCache, key) => { + ++stats.rootKeys; + + subCache.forEach((cacheEntry, subKey) => { + ++stats.subKeys; + + const canvas = cacheEntry.canvas; + stats.vramBytes += canvas.width * canvas.height * 4; + }); + }); + + return stats; } /** @@ -95,15 +120,18 @@ export class BufferMaintainer { } /** - * - * @param {string} key - * @param {string} subKey - * @param {function(HTMLCanvasElement, CanvasRenderingContext2D, number, number, number, object?) : void} redrawMethod - * @param {object=} additionalParams + * @param {object} param0 + * @param {string} param0.key + * @param {string} param0.subKey + * @param {number} param0.w + * @param {number} param0.h + * @param {number} param0.dpi + * @param {function(HTMLCanvasElement, CanvasRenderingContext2D, number, number, number, object?) : void} param0.redrawMethod + * @param {object=} param0.additionalParams * @returns {HTMLCanvasElement} * */ - getForKey(key, subKey, w, h, dpi, redrawMethod, additionalParams) { + getForKey({ key, subKey, w, h, dpi, redrawMethod, additionalParams }) { // First, create parent key let parent = this.cache.get(key); if (!parent) { diff --git a/src/js/core/config.js b/src/js/core/config.js index e06f9422..a6d6ed63 100644 --- a/src/js/core/config.js +++ b/src/js/core/config.js @@ -1,135 +1,136 @@ -import { queryParamOptions } from "./query_parameters"; - -export const IS_DEBUG = - G_IS_DEV && - typeof window !== "undefined" && - window.location.port === "3005" && - (window.location.host.indexOf("localhost:") >= 0 || window.location.host.indexOf("192.168.0.") >= 0) && - window.location.search.indexOf("nodebug") < 0; - -export const IS_DEMO = queryParamOptions.fullVersion - ? false - : (!G_IS_DEV && !G_IS_STANDALONE) || - (typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0); - -export const SUPPORT_TOUCH = false; - -const smoothCanvas = true; - -export const THIRDPARTY_URLS = { - discord: "https://discord.gg/HN7EVzV", - github: "https://github.com/tobspr/shapez.io", - reddit: "https://www.reddit.com/r/shapezio", - - standaloneStorePage: "https://store.steampowered.com/app/1318690/shapezio/", -}; - -export const globalConfig = { - // Size of a single tile in Pixels. - // NOTICE: Update webpack.production.config too! - tileSize: 32, - halfTileSize: 16, - - // Which dpi the assets have - assetsDpi: 192 / 32, - assetsSharpness: 1.2, - shapesSharpness: 1.4, - - // Production analytics - statisticsGraphDpi: 2.5, - statisticsGraphSlices: 100, - analyticsSliceDurationSeconds: G_IS_DEV ? 1 : 10, - - minimumTickRate: 25, - maximumTickRate: 500, - - // Map - mapChunkSize: 16, - mapChunkPrerenderMinZoom: -1, - mapChunkOverviewMinZoom: 0.7, - - // Belt speeds - // NOTICE: Update webpack.production.config too! - beltSpeedItemsPerSecond: 2, - minerSpeedItemsPerSecond: 0, // COMPUTED - - beltItemSpacingByLayer: { - regular: 0.63, - wires: 0.4, - }, - - wiresSpeedItemsPerSecond: 6, - - undergroundBeltMaxTilesByTier: [5, 8], - - buildingSpeeds: { - cutter: 1 / 4, - cutterQuad: 1 / 4, - rotater: 1 / 1, - rotaterCCW: 1 / 1, - painter: 1 / 6, - painterDouble: 1 / 8, - painterQuad: 1 / 8, - mixer: 1 / 5, - stacker: 1 / 6, - advancedProcessor: 1 / 3, - }, - - // Zooming - initialZoom: 1.9, - minZoomLevel: 0.1, - maxZoomLevel: 3, - - // Global game speed - gameSpeed: 1, - - warmupTimeSecondsFast: 0.1, - warmupTimeSecondsRegular: 1, - - smoothing: { - smoothMainCanvas: smoothCanvas && true, - quality: "low", // Low is CRUCIAL for mobile performance! - }, - - rendering: {}, - debug: require("./config.local").default, - - // Secret vars - info: { - // Binary file salt - file: "Ec'])@^+*9zMevK3uMV4432x9%iK'=", - - // Savegame salt - sgSalt: "}95Q3%8/.837Lqym_BJx%q7)pAHJbF", - - // Analytics key - analyticsApiKey: "baf6a50f0cc7dfdec5a0e21c88a1c69a4b34bc4a", - }, -}; - -export const IS_MOBILE = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); - -// Automatic calculations -globalConfig.minerSpeedItemsPerSecond = globalConfig.beltSpeedItemsPerSecond / 5; - -// Dynamic calculations -if (globalConfig.debug.disableMapOverview) { - globalConfig.mapChunkOverviewMinZoom = 0; - globalConfig.mapChunkPrerenderMinZoom = 0; -} - -// Stuff for making the trailer -if (G_IS_DEV && globalConfig.debug.renderForTrailer) { - globalConfig.debug.framePausesBetweenTicks = 32; - // globalConfig.mapChunkOverviewMinZoom = 0.0; - // globalConfig.mapChunkPrerenderMinZoom = globalConfig.mapChunkOverviewMinZoom; - // globalConfig.debug.instantBelts = true; - // globalConfig.debug.instantProcessors = true; - // globalConfig.debug.instantMiners = true; - globalConfig.debug.disableSavegameWrite = true; - // globalConfig.beltSpeedItemsPerSecond *= 2; -} - -if (globalConfig.debug.fastGameEnter) { - globalConfig.debug.noArtificalDelays = true; -} +import { queryParamOptions } from "./query_parameters"; + +export const IS_DEBUG = + G_IS_DEV && + typeof window !== "undefined" && + window.location.port === "3005" && + (window.location.host.indexOf("localhost:") >= 0 || window.location.host.indexOf("192.168.0.") >= 0) && + window.location.search.indexOf("nodebug") < 0; + +export const IS_DEMO = queryParamOptions.fullVersion + ? false + : (!G_IS_DEV && !G_IS_STANDALONE) || + (typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0); + +export const SUPPORT_TOUCH = false; + +const smoothCanvas = true; + +export const THIRDPARTY_URLS = { + discord: "https://discord.gg/HN7EVzV", + github: "https://github.com/tobspr/shapez.io", + reddit: "https://www.reddit.com/r/shapezio", + + standaloneStorePage: "https://store.steampowered.com/app/1318690/shapezio/", +}; + +export const globalConfig = { + // Size of a single tile in Pixels. + // NOTICE: Update webpack.production.config too! + tileSize: 32, + halfTileSize: 16, + + // Which dpi the assets have + assetsDpi: 192 / 32, + assetsSharpness: 1.5, + shapesSharpness: 1.4, + + // Production analytics + statisticsGraphDpi: 2.5, + statisticsGraphSlices: 100, + analyticsSliceDurationSeconds: G_IS_DEV ? 1 : 10, + + minimumTickRate: 25, + maximumTickRate: 500, + + // Map + mapChunkSize: 16, + mapChunkOverviewMinZoom: 0.9, + mapChunkWorldSize: null, // COMPUTED + + // Belt speeds + // NOTICE: Update webpack.production.config too! + beltSpeedItemsPerSecond: 2, + minerSpeedItemsPerSecond: 0, // COMPUTED + + defaultItemDiameter: 20, + + itemSpacingOnBelts: 0.63, + + wiresSpeedItemsPerSecond: 6, + + undergroundBeltMaxTilesByTier: [5, 9], + + readerAnalyzeIntervalSeconds: G_IS_DEV ? 3 : 10, + + buildingSpeeds: { + cutter: 1 / 4, + cutterQuad: 1 / 4, + rotater: 1 / 1, + rotaterCCW: 1 / 1, + rotaterFL: 1 / 1, + painter: 1 / 6, + painterDouble: 1 / 8, + painterQuad: 1 / 8, + mixer: 1 / 5, + stacker: 1 / 6, + }, + + // Zooming + initialZoom: 1.9, + minZoomLevel: 0.1, + maxZoomLevel: 3, + + // Global game speed + gameSpeed: 1, + + warmupTimeSecondsFast: 0.1, + warmupTimeSecondsRegular: 1, + + smoothing: { + smoothMainCanvas: smoothCanvas && true, + quality: "low", // Low is CRUCIAL for mobile performance! + }, + + rendering: {}, + debug: require("./config.local").default, + + // Secret vars + info: { + // Binary file salt + file: "Ec'])@^+*9zMevK3uMV4432x9%iK'=", + + // Savegame salt + sgSalt: "}95Q3%8/.837Lqym_BJx%q7)pAHJbF", + + // Analytics key + analyticsApiKey: "baf6a50f0cc7dfdec5a0e21c88a1c69a4b34bc4a", + }, +}; + +export const IS_MOBILE = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); + +// Automatic calculations +globalConfig.minerSpeedItemsPerSecond = globalConfig.beltSpeedItemsPerSecond / 5; + +globalConfig.mapChunkWorldSize = globalConfig.mapChunkSize * globalConfig.tileSize; + +// Dynamic calculations +if (globalConfig.debug.disableMapOverview) { + globalConfig.mapChunkOverviewMinZoom = 0; +} + +// Stuff for making the trailer +if (G_IS_DEV && globalConfig.debug.renderForTrailer) { + globalConfig.debug.framePausesBetweenTicks = 32; + // globalConfig.mapChunkOverviewMinZoom = 0.0; + // globalConfig.debug.instantBelts = true; + // globalConfig.debug.instantProcessors = true; + // globalConfig.debug.instantMiners = true; + globalConfig.debug.disableSavegameWrite = true; + // globalConfig.beltSpeedItemsPerSecond *= 2; +} + +if (globalConfig.debug.fastGameEnter) { + globalConfig.debug.noArtificalDelays = true; +} diff --git a/src/js/core/config.local.js b/src/js/core/config.local.js index e76c2f0e..b75c5650 100644 --- a/src/js/core/config.local.js +++ b/src/js/core/config.local.js @@ -1,99 +1,114 @@ -export default { - // You can set any debug options here! - /* dev:start */ - // ----------------------------------------------------------------------------------- - // Quickly enters the game and skips the main menu - good for fast iterating - fastGameEnter: true, - // ----------------------------------------------------------------------------------- - // Skips any delays like transitions between states and such - // noArtificialDelays: true, - // ----------------------------------------------------------------------------------- - // Disables writing of savegames, useful for testing the same savegame over and over - // disableSavegameWrite: true, - // ----------------------------------------------------------------------------------- - // Shows bounds of all entities - // showEntityBounds: true, - // ----------------------------------------------------------------------------------- - // Shows arrows for every ejector / acceptor - // showAcceptorEjectors: true, - // ----------------------------------------------------------------------------------- - // Disables the music (Overrides any setting, can cause weird behaviour) - // disableMusic: true, - // ----------------------------------------------------------------------------------- - // Do not render static map entities (=most buildings) - // doNotRenderStatics: true, - // ----------------------------------------------------------------------------------- - // Allow to zoom freely without limits - // disableZoomLimits: true, - // ----------------------------------------------------------------------------------- - // Shows a border arround every chunk - // showChunkBorders: true, - // ----------------------------------------------------------------------------------- - // All rewards can be unlocked by passing just 1 of any shape - // rewardsInstant: true, - // ----------------------------------------------------------------------------------- - // Unlocks all buildings - allBuildingsUnlocked: true, - // ----------------------------------------------------------------------------------- - // Disables cost of blueprints - blueprintsNoCost: true, - // ----------------------------------------------------------------------------------- - // Disables cost of upgrades - upgradesNoCost: true, - // ----------------------------------------------------------------------------------- - // Disables the dialog when completing a level - // disableUnlockDialog: true, - // ----------------------------------------------------------------------------------- - // Disables the simulation - This effectively pauses the game. - // disableLogicTicks: true, - // ----------------------------------------------------------------------------------- - // Test the rendering if everything is clipped out properly - // testClipping: true, - // ----------------------------------------------------------------------------------- - // Allows to render slower, useful for recording at half speed to avoid stuttering - // framePausesBetweenTicks: 1, - // ----------------------------------------------------------------------------------- - // Replace all translations with emojis to see which texts are translateable - // testTranslations: true, - // ----------------------------------------------------------------------------------- - // Enables an inspector which shows information about the entity below the curosr - // enableEntityInspector: true, - // ----------------------------------------------------------------------------------- - // Enables ads in the local build (normally they are deactivated there) - // testAds: true, - // ----------------------------------------------------------------------------------- - // Disables the automatic switch to an overview when zooming out - // disableMapOverview: true, - // ----------------------------------------------------------------------------------- - // Disables the notification when there are new entries in the changelog since last played - // disableUpgradeNotification: true, - // ----------------------------------------------------------------------------------- - // Makes belts almost infinitely fast - // instantBelts: true, - // ----------------------------------------------------------------------------------- - // Makes item processors almost infinitely fast - // instantProcessors: true, - // ----------------------------------------------------------------------------------- - // Makes miners almost infinitely fast - // instantMiners: true, - // ----------------------------------------------------------------------------------- - // When using fastGameEnter, controls whether a new game is started or the last one is resumed - resumeGameOnFastEnter: true, - // ----------------------------------------------------------------------------------- - // Special option used to render the trailer - // renderForTrailer: true, - // ----------------------------------------------------------------------------------- - // Whether to render changes - // renderChanges: true, - // ----------------------------------------------------------------------------------- - // Whether to render belt paths - // renderBeltPaths: true, - // ----------------------------------------------------------------------------------- - // Whether to check belt paths - // checkBeltPaths: true, - // ----------------------------------------------------------------------------------- - // Whether to items / s instead of items / m in stats - // detailedStatistics: true, - // ----------------------------------------------------------------------------------- - /* dev:end */ -}; +export default { + // You can set any debug options here! + /* dev:start */ + // ----------------------------------------------------------------------------------- + // Quickly enters the game and skips the main menu - good for fast iterating + // fastGameEnter: true, + // ----------------------------------------------------------------------------------- + // Skips any delays like transitions between states and such + // noArtificialDelays: true, + // ----------------------------------------------------------------------------------- + // Disables writing of savegames, useful for testing the same savegame over and over + // disableSavegameWrite: true, + // ----------------------------------------------------------------------------------- + // Shows bounds of all entities + // showEntityBounds: true, + // ----------------------------------------------------------------------------------- + // Shows arrows for every ejector / acceptor + // showAcceptorEjectors: true, + // ----------------------------------------------------------------------------------- + // Disables the music (Overrides any setting, can cause weird behaviour) + // disableMusic: true, + // ----------------------------------------------------------------------------------- + // Do not render static map entities (=most buildings) + // doNotRenderStatics: true, + // ----------------------------------------------------------------------------------- + // Allow to zoom freely without limits + // disableZoomLimits: true, + // ----------------------------------------------------------------------------------- + // Shows a border arround every chunk + // showChunkBorders: true, + // ----------------------------------------------------------------------------------- + // All rewards can be unlocked by passing just 1 of any shape + // rewardsInstant: true, + // ----------------------------------------------------------------------------------- + // Unlocks all buildings + // allBuildingsUnlocked: true, + // ----------------------------------------------------------------------------------- + // Disables cost of blueprints + // blueprintsNoCost: true, + // ----------------------------------------------------------------------------------- + // Disables cost of upgrades + // upgradesNoCost: true, + // ----------------------------------------------------------------------------------- + // Disables the dialog when completing a level + // disableUnlockDialog: true, + // ----------------------------------------------------------------------------------- + // Disables the simulation - This effectively pauses the game. + // disableLogicTicks: true, + // ----------------------------------------------------------------------------------- + // Test the rendering if everything is clipped out properly + // testClipping: true, + // ----------------------------------------------------------------------------------- + // Allows to render slower, useful for recording at half speed to avoid stuttering + // framePausesBetweenTicks: 250, + // ----------------------------------------------------------------------------------- + // Replace all translations with emojis to see which texts are translateable + // testTranslations: true, + // ----------------------------------------------------------------------------------- + // Enables an inspector which shows information about the entity below the curosr + // enableEntityInspector: true, + // ----------------------------------------------------------------------------------- + // Enables ads in the local build (normally they are deactivated there) + // testAds: true, + // ----------------------------------------------------------------------------------- + // Disables the automatic switch to an overview when zooming out + // disableMapOverview: true, + // ----------------------------------------------------------------------------------- + // Disables the notification when there are new entries in the changelog since last played + // disableUpgradeNotification: true, + // ----------------------------------------------------------------------------------- + // Makes belts almost infinitely fast + // instantBelts: true, + // ----------------------------------------------------------------------------------- + // Makes item processors almost infinitely fast + // instantProcessors: true, + // ----------------------------------------------------------------------------------- + // Makes miners almost infinitely fast + // instantMiners: true, + // ----------------------------------------------------------------------------------- + // When using fastGameEnter, controls whether a new game is started or the last one is resumed + // resumeGameOnFastEnter: true, + // ----------------------------------------------------------------------------------- + // Special option used to render the trailer + // renderForTrailer: true, + // ----------------------------------------------------------------------------------- + // Whether to render changes + // renderChanges: true, + // ----------------------------------------------------------------------------------- + // Whether to render belt paths + // renderBeltPaths: true, + // ----------------------------------------------------------------------------------- + // Whether to check belt paths + // checkBeltPaths: true, + // ----------------------------------------------------------------------------------- + // Whether to items / s instead of items / m in stats + // detailedStatistics: true, + // ----------------------------------------------------------------------------------- + // Shows detailed information about which atlas is used + // showAtlasInfo: true, + // ----------------------------------------------------------------------------------- + // Renders the rotation of all wires + // renderWireRotations: true, + // ----------------------------------------------------------------------------------- + // Renders information about wire networks + // renderWireNetworkInfos: true, + // ----------------------------------------------------------------------------------- + // Disables ejector animations and processing + // disableEjectorProcessing: true, + // ----------------------------------------------------------------------------------- + // Allows manual ticking + // manualTickOnly: true, + // ----------------------------------------------------------------------------------- + /* dev:end */ +}; diff --git a/src/js/core/dpi_manager.js b/src/js/core/dpi_manager.js index 0388c5f9..b944d155 100644 --- a/src/js/core/dpi_manager.js +++ b/src/js/core/dpi_manager.js @@ -15,8 +15,8 @@ export function getDeviceDPI() { * @returns {number} Smoothed dpi */ export function smoothenDpi(dpi) { - if (dpi < 0.05) { - return 0.05; + if (dpi < 0.02) { + return 0.02; } else if (dpi < 0.1) { return round2Digits(dpi); } else if (dpi < 1) { diff --git a/src/js/core/draw_parameters.js b/src/js/core/draw_parameters.js index dcdf6d13..71971ed1 100644 --- a/src/js/core/draw_parameters.js +++ b/src/js/core/draw_parameters.js @@ -1,9 +1,9 @@ -import { Rectangle } from "./rectangle"; import { globalConfig } from "./config"; -/* typehints:start */ -import { GameRoot } from "../game/root"; -/* typehints:end */ +/** + * @typedef {import("../game/root").GameRoot} GameRoot + * @typedef {import("./rectangle").Rectangle} Rectangle + */ export class DrawParameters { constructor({ context, visibleRect, desiredAtlasScale, zoomLevel, root }) { @@ -13,7 +13,7 @@ export class DrawParameters { /** @type {Rectangle} */ this.visibleRect = visibleRect; - /** @type {number} */ + /** @type {string} */ this.desiredAtlasScale = desiredAtlasScale; /** @type {number} */ @@ -22,9 +22,5 @@ export class DrawParameters { // FIXME: Not really nice /** @type {GameRoot} */ this.root = root; - - if (G_IS_DEV && globalConfig.debug.testClipping) { - this.visibleRect = this.visibleRect.expandedInAllDirections(-100); - } } } diff --git a/src/js/core/draw_utils.js b/src/js/core/draw_utils.js index 1b37b929..d5183cfb 100644 --- a/src/js/core/draw_utils.js +++ b/src/js/core/draw_utils.js @@ -1,18 +1,19 @@ -/* typehints:start */ -import { AtlasSprite } from "./sprites"; -import { DrawParameters } from "./draw_parameters"; -/* typehints:end */ +/** + * @typedef {import("./sprites").AtlasSprite} AtlasSprite + * @typedef {import("./draw_parameters").DrawParameters} DrawParameters + */ -import { Vector } from "./vector"; -import { Rectangle } from "./rectangle"; +import { globalConfig } from "./config"; import { createLogger } from "./logging"; +import { Rectangle } from "./rectangle"; const logger = createLogger("draw_utils"); export function initDrawUtils() { CanvasRenderingContext2D.prototype.beginRoundedRect = function (x, y, w, h, r) { + this.beginPath(); + if (r < 0.05) { - this.beginPath(); this.rect(x, y, w, h); return; } @@ -20,25 +21,26 @@ export function initDrawUtils() { if (w < 2 * r) { r = w / 2; } + if (h < 2 * r) { r = h / 2; } - this.beginPath(); + this.moveTo(x + r, y); this.arcTo(x + w, y, x + w, y + h, r); this.arcTo(x + w, y + h, x, y + h, r); this.arcTo(x, y + h, x, y, r); this.arcTo(x, y, x + w, y, r); - // this.closePath(); }; CanvasRenderingContext2D.prototype.beginCircle = function (x, y, r) { + this.beginPath(); + if (r < 0.05) { - this.beginPath(); this.rect(x, y, 1, 1); return; } - this.beginPath(); + this.arc(x, y, r, 0, 2.0 * Math.PI); }; } @@ -56,6 +58,11 @@ export function initDrawUtils() { * @param {number=} param0.offsetY */ export function drawRotatedSprite({ parameters, sprite, x, y, angle, size, offsetX = 0, offsetY = 0 }) { + if (angle === 0) { + sprite.drawCachedCentered(parameters, x + offsetX, y + offsetY, size); + return; + } + parameters.context.translate(x, y); parameters.context.rotate(angle); sprite.drawCachedCentered(parameters, offsetX, offsetY, size, false); @@ -63,258 +70,52 @@ export function drawRotatedSprite({ parameters, sprite, x, y, angle, size, offse parameters.context.translate(-x, -y); } -export function drawLineFast(context, { x1, x2, y1, y2, color = null, lineSize = 1 }) { - const dX = x2 - x1; - const dY = y2 - y1; +let warningsShown = 0; - const angle = Math.atan2(dY, dX) + 0.0 * Math.PI; - const len = Math.hypot(dX, dY); - - context.translate(x1, y1); - context.rotate(angle); - - if (color) { - context.fillStyle = color; - } - - context.fillRect(0, -lineSize / 2, len, lineSize); - - context.rotate(-angle); - context.translate(-x1, -y1); -} - -const INSIDE = 0; -const LEFT = 1; -const RIGHT = 2; -const BOTTOM = 4; -const TOP = 8; - -// https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm - -function computeOutCode(x, y, xmin, xmax, ymin, ymax) { - let code = INSIDE; - - if (x < xmin) - // to the left of clip window - code |= LEFT; - else if (x > xmax) - // to the right of clip window - code |= RIGHT; - if (y < ymin) - // below the clip window - code |= BOTTOM; - else if (y > ymax) - // above the clip window - code |= TOP; - - return code; -} - -// Cohen–Sutherland clipping algorithm clips a line from -// P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with -// diagonal from (xmin, ymin) to (xmax, ymax). /** - * - * @param {CanvasRenderingContext2D} context + * Draws a sprite with clipping + * @param {object} param0 + * @param {DrawParameters} param0.parameters + * @param {HTMLCanvasElement} param0.sprite + * @param {number} param0.x + * @param {number} param0.y + * @param {number} param0.w + * @param {number} param0.h + * @param {number} param0.originalW + * @param {number} param0.originalH */ -export function drawLineFastClipped(context, rect, { x0, y0, x1, y1, color = null, lineSize = 1 }) { - const xmin = rect.x; - const ymin = rect.y; - const xmax = rect.right(); - const ymax = rect.bottom(); - - // compute outcodes for P0, P1, and whatever point lies outside the clip rectangle - let outcode0 = computeOutCode(x0, y0, xmin, xmax, ymin, ymax); - let outcode1 = computeOutCode(x1, y1, xmin, xmax, ymin, ymax); - let accept = false; - - // eslint-disable-next-line no-constant-condition - while (true) { - if (!(outcode0 | outcode1)) { - // bitwise OR is 0: both points inside window; trivially accept and exit loop - accept = true; - break; - } else if (outcode0 & outcode1) { - // bitwise AND is not 0: both points share an outside zone (LEFT, RIGHT, TOP, - // or BOTTOM), so both must be outside window; exit loop (accept is false) - break; - } else { - // failed both tests, so calculate the line segment to clip - // from an outside point to an intersection with clip edge - let x, y; - - // At least one endpoint is outside the clip rectangle; pick it. - let outcodeOut = outcode0 ? outcode0 : outcode1; - - // Now find the intersection point; - // use formulas: - // slope = (y1 - y0) / (x1 - x0) - // x = x0 + (1 / slope) * (ym - y0), where ym is ymin or ymax - // y = y0 + slope * (xm - x0), where xm is xmin or xmax - // No need to worry about divide-by-zero because, in each case, the - // outcode bit being tested guarantees the denominator is non-zero - if (outcodeOut & TOP) { - // point is above the clip window - x = x0 + ((x1 - x0) * (ymax - y0)) / (y1 - y0); - y = ymax; - } else if (outcodeOut & BOTTOM) { - // point is below the clip window - x = x0 + ((x1 - x0) * (ymin - y0)) / (y1 - y0); - y = ymin; - } else if (outcodeOut & RIGHT) { - // point is to the right of clip window - y = y0 + ((y1 - y0) * (xmax - x0)) / (x1 - x0); - x = xmax; - } else if (outcodeOut & LEFT) { - // point is to the left of clip window - y = y0 + ((y1 - y0) * (xmin - x0)) / (x1 - x0); - x = xmin; - } - - // Now we move outside point to intersection point to clip - // and get ready for next pass. - if (outcodeOut == outcode0) { - x0 = x; - y0 = y; - outcode0 = computeOutCode(x0, y0, xmin, xmax, ymin, ymax); - } else { - x1 = x; - y1 = y; - outcode1 = computeOutCode(x1, y1, xmin, xmax, ymin, ymax); - } +export function drawSpriteClipped({ parameters, sprite, x, y, w, h, originalW, originalH }) { + const rect = new Rectangle(x, y, w, h); + const intersection = rect.getIntersection(parameters.visibleRect); + if (!intersection) { + // Clipped + if (++warningsShown % 200 === 1) { + logger.warn( + "Sprite drawn clipped but it's not on screen - perform culling before (", + warningsShown, + "warnings)" + ); } - } - if (accept) { - // Following functions are left for implementation by user based on - // their platform (OpenGL/graphics.h etc.) - // DrawRectangle(xmin, ymin, xmax, ymax); - // LineSegment(x0, y0, x1, y1); - drawLineFast(context, { - x1: x0, - y1: y0, - x2: x1, - y2: y1, - color, - lineSize, - }); - } -} - -/** - * Converts an HSL color value to RGB. Conversion formula - * adapted from http://en.wikipedia.org/wiki/HSL_color_space. - * Assumes h, s, and l are contained in the set [0, 1] and - * returns r, g, and b in the set [0, 255]. - * - * @param {number} h The hue - * @param {number} s The saturation - * @param {number} l The lightness - * @return {Array} The RGB representation - */ -export function hslToRgb(h, s, l) { - let r; - let g; - let b; - - if (s === 0) { - r = g = b = l; // achromatic - } else { - // tslint:disable-next-line:no-shadowed-variable - const hue2rgb = function (p, q, t) { - if (t < 0) { - t += 1; - } - if (t > 1) { - t -= 1; - } - if (t < 1 / 6) { - return p + (q - p) * 6 * t; - } - if (t < 1 / 2) { - return q; - } - if (t < 2 / 3) { - return p + (q - p) * (2 / 3 - t) * 6; - } - return p; - }; - - let q = l < 0.5 ? l * (1 + s) : l + s - l * s; - let p = 2 * l - q; - r = hue2rgb(p, q, h + 1 / 3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1 / 3); - } - - return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; -} - -export function wrapText(context, text, x, y, maxWidth, lineHeight, stroke = false) { - var words = text.split(" "); - var line = ""; - - for (var n = 0; n < words.length; n++) { - var testLine = line + words[n] + " "; - var metrics = context.measureText(testLine); - var testWidth = metrics.width; - if (testWidth > maxWidth && n > 0) { - if (stroke) { - context.strokeText(line, x, y); - } else { - context.fillText(line, x, y); - } - line = words[n] + " "; - y += lineHeight; - } else { - line = testLine; + if (G_IS_DEV && globalConfig.debug.testClipping) { + parameters.context.fillStyle = "yellow"; + parameters.context.fillRect(x, y, w, h); } + return; } - if (stroke) { - context.strokeText(line, x, y); - } else { - context.fillText(line, x, y); - } -} + parameters.context.drawImage( + sprite, -/** - * Returns a rotated trapez, used for spotlight culling - * @param {number} x - * @param {number} y - * @param {number} w - * @param {number} h - * @param {number} leftHeight - * @param {number} angle - */ -export function rotateTrapezRightFaced(x, y, w, h, leftHeight, angle) { - const halfY = y + h / 2; - const points = [ - new Vector(x, halfY - leftHeight / 2), - new Vector(x + w, y), - new Vector(x, halfY + leftHeight / 2), - new Vector(x + w, y + h), - ]; + // src pos and size + ((intersection.x - x) / w) * originalW, + ((intersection.y - y) / h) * originalH, + (originalW * intersection.w) / w, + (originalH * intersection.h) / h, - return Rectangle.getAroundPointsRotated(points, angle); -} - -/** - * Converts values from 0 .. 255 to values like 07, 7f, 5d etc - * @param {number} value - * @returns {string} - */ -export function mapClampedColorValueToHex(value) { - const hex = "0123456789abcdef"; - return hex[Math.floor(value / 16)] + hex[value % 16]; -} - -/** - * Converts rgb to a hex string - * @param {number} r - * @param {number} g - * @param {number} b - * @returns {string} - */ -export function rgbToHex(r, g, b) { - return mapClampedColorValueToHex(r) + mapClampedColorValueToHex(g) + mapClampedColorValueToHex(b); + // dest pos and size + intersection.x, + intersection.y, + intersection.w, + intersection.h + ); } diff --git a/src/js/core/global_registries.js b/src/js/core/global_registries.js index 321732e0..ad45850c 100644 --- a/src/js/core/global_registries.js +++ b/src/js/core/global_registries.js @@ -1,19 +1,19 @@ import { SingletonFactory } from "./singleton_factory"; import { Factory } from "./factory"; -/* typehints:start */ -import { BaseGameSpeed } from "../game/time/base_game_speed"; -import { Component } from "../game/component"; -import { BaseItem } from "../game/base_item"; -import { MetaBuilding } from "../game/meta_building"; -/* typehints:end */ +/** + * @typedef {import("../game/time/base_game_speed").BaseGameSpeed} BaseGameSpeed + * @typedef {import("../game/component").Component} Component + * @typedef {import("../game/base_item").BaseItem} BaseItem + * @typedef {import("../game/meta_building").MetaBuilding} MetaBuilding + // These factories are here to remove circular dependencies /** @type {SingletonFactoryTemplate} */ export let gMetaBuildingRegistry = new SingletonFactory(); -/** @type {Object.>} */ +/** @type {Object.>>} */ export let gBuildingsByCategory = null; /** @type {FactoryTemplate} */ @@ -28,7 +28,7 @@ export let gItemRegistry = new Factory("item"); // Helpers /** - * @param {Object.>} buildings + * @param {Object.>>} buildings */ export function initBuildingsByCategory(buildings) { gBuildingsByCategory = buildings; diff --git a/src/js/core/loader.js b/src/js/core/loader.js index 8888ecbf..d7f544e3 100644 --- a/src/js/core/loader.js +++ b/src/js/core/loader.js @@ -1,20 +1,19 @@ -/* typehints:start */ -import { Application } from "../application"; -/* typehints:end */ - -import { AtlasDefinition } from "./atlas_definitions"; import { makeOffscreenBuffer } from "./buffer_utils"; import { AtlasSprite, BaseSprite, RegularSprite, SpriteAtlasLink } from "./sprites"; import { cachebust } from "./cachebust"; import { createLogger } from "./logging"; +/** + * @typedef {import("../application").Application} Application + * @typedef {import("./atlas_definitions").AtlasDefinition} AtlasDefinition; + */ + const logger = createLogger("loader"); const missingSpriteIds = {}; class LoaderImpl { constructor() { - /** @type {Application} */ this.app = null; /** @type {Map} */ @@ -23,6 +22,9 @@ class LoaderImpl { this.rawImages = []; } + /** + * @param {Application} app + */ linkAppAfterBoot(app) { this.app = app; this.makeSpriteNotFoundCanvas(); @@ -58,7 +60,7 @@ class LoaderImpl { } /** - * Retursn a regular sprite from the cache + * Returns a regular sprite from the cache * @param {string} key * @returns {RegularSprite} */ @@ -155,44 +157,34 @@ class LoaderImpl { * @param {AtlasDefinition} atlas * @param {HTMLImageElement} loadedImage */ - internalParseAtlas(atlas, loadedImage) { + internalParseAtlas({ meta: { scale }, sourceData }, loadedImage) { this.rawImages.push(loadedImage); - for (const spriteKey in atlas.sourceData) { - const spriteData = atlas.sourceData[spriteKey]; + for (const spriteName in sourceData) { + const { frame, sourceSize, spriteSourceSize } = sourceData[spriteName]; - let sprite = /** @type {AtlasSprite} */ (this.sprites.get(spriteKey)); + let sprite = /** @type {AtlasSprite} */ (this.sprites.get(spriteName)); if (!sprite) { - sprite = new AtlasSprite({ - spriteName: spriteKey, - }); - this.sprites.set(spriteKey, sprite); + sprite = new AtlasSprite(spriteName); + this.sprites.set(spriteName, sprite); } const link = new SpriteAtlasLink({ - packedX: spriteData.frame.x, - packedY: spriteData.frame.y, - packedW: spriteData.frame.w, - packedH: spriteData.frame.h, - packOffsetX: spriteData.spriteSourceSize.x, - packOffsetY: spriteData.spriteSourceSize.y, + packedX: frame.x, + packedY: frame.y, + packedW: frame.w, + packedH: frame.h, + packOffsetX: spriteSourceSize.x, + packOffsetY: spriteSourceSize.y, atlas: loadedImage, - w: spriteData.sourceSize.w, - h: spriteData.sourceSize.h, + w: sourceSize.w, + h: sourceSize.h, }); - sprite.linksByResolution[atlas.meta.scale] = link; + sprite.linksByResolution[scale] = link; } } - /** - * Creates the links for the sprites after the atlas has been loaded. Used so we - * don't have to store duplicate sprites. - */ - createAtlasLinks() { - // NOT USED - } - /** * Makes the canvas which shows the question mark, shown when a sprite was not found */ @@ -216,14 +208,9 @@ class LoaderImpl { // @ts-ignore canvas.src = "not-found"; - const resolutions = ["0.1", "0.25", "0.5", "0.75", "1"]; - const sprite = new AtlasSprite({ - spriteName: "not-found", - }); - - for (let i = 0; i < resolutions.length; ++i) { - const res = resolutions[i]; - const link = new SpriteAtlasLink({ + const sprite = new AtlasSprite("not-found"); + ["0.1", "0.25", "0.5", "0.75", "1"].forEach(resolution => { + sprite.linksByResolution[resolution] = new SpriteAtlasLink({ packedX: 0, packedY: 0, w: dims, @@ -234,8 +221,8 @@ class LoaderImpl { packedH: dims, atlas: canvas, }); - sprite.linksByResolution[res] = link; - } + }); + this.spriteNotFoundSprite = sprite; } } diff --git a/src/js/core/modal_dialog_elements.js b/src/js/core/modal_dialog_elements.js index 8252487a..54b69402 100644 --- a/src/js/core/modal_dialog_elements.js +++ b/src/js/core/modal_dialog_elements.js @@ -1,434 +1,443 @@ -/* typehints:start */ -import { Application } from "../application"; -/* typehints:end */ - -import { Signal, STOP_PROPAGATION } from "./signal"; -import { arrayDeleteValue, waitNextFrame } from "./utils"; -import { ClickDetector } from "./click_detector"; -import { SOUNDS } from "../platform/sound"; -import { InputReceiver } from "./input_receiver"; -import { FormElement } from "./modal_dialog_forms"; -import { globalConfig } from "./config"; -import { getStringForKeyCode } from "../game/key_action_mapper"; -import { createLogger } from "./logging"; -import { T } from "../translations"; - -const kbEnter = 13; -const kbCancel = 27; - -const logger = createLogger("dialogs"); - -/** - * Basic text based dialog - */ -export class Dialog { - /** - * - * Constructs a new dialog with the given options - * @param {object} param0 - * @param {Application} param0.app - * @param {string} param0.title Title of the dialog - * @param {string} param0.contentHTML Inner dialog html - * @param {Array} param0.buttons - * Button list, each button contains of up to 3 parts seperated by ':'. - * Part 0: The id, one of the one defined in dialog_buttons.yaml - * Part 1: The style, either good, bad or misc - * Part 2 (optional): Additional parameters seperated by '/', available are: - * timeout: This button is only available after some waiting time - * kb_enter: This button is triggered by the enter key - * kb_escape This button is triggered by the escape key - * @param {string=} param0.type The dialog type, either "info" or "warn" - * @param {boolean=} param0.closeButton Whether this dialog has a close button - */ - constructor({ app, title, contentHTML, buttons, type = "info", closeButton = false }) { - this.app = app; - this.title = title; - this.contentHTML = contentHTML; - this.type = type; - this.buttonIds = buttons; - this.closeButton = closeButton; - - this.closeRequested = new Signal(); - this.buttonSignals = {}; - - for (let i = 0; i < buttons.length; ++i) { - if (G_IS_DEV && globalConfig.debug.disableTimedButtons) { - this.buttonIds[i] = this.buttonIds[i].replace(":timeout", ""); - } - - const buttonId = this.buttonIds[i].split(":")[0]; - this.buttonSignals[buttonId] = new Signal(); - } - - this.timeouts = []; - this.clickDetectors = []; - - this.inputReciever = new InputReceiver("dialog-" + this.title); - - this.inputReciever.keydown.add(this.handleKeydown, this); - - this.enterHandler = null; - this.escapeHandler = null; - } - - /** - * Internal keydown handler - * @param {object} param0 - * @param {number} param0.keyCode - * @param {boolean} param0.shift - * @param {boolean} param0.alt - */ - handleKeydown({ keyCode, shift, alt }) { - if (keyCode === kbEnter && this.enterHandler) { - this.internalButtonHandler(this.enterHandler); - return STOP_PROPAGATION; - } - - if (keyCode === kbCancel && this.escapeHandler) { - this.internalButtonHandler(this.escapeHandler); - return STOP_PROPAGATION; - } - } - - internalButtonHandler(id, ...payload) { - this.app.inputMgr.popReciever(this.inputReciever); - - if (id !== "close-button") { - this.buttonSignals[id].dispatch(...payload); - } - this.closeRequested.dispatch(); - } - - createElement() { - const elem = document.createElement("div"); - elem.classList.add("ingameDialog"); - - this.dialogElem = document.createElement("div"); - this.dialogElem.classList.add("dialogInner"); - - if (this.type) { - this.dialogElem.classList.add(this.type); - } - elem.appendChild(this.dialogElem); - - const title = document.createElement("h1"); - title.innerText = this.title; - title.classList.add("title"); - this.dialogElem.appendChild(title); - - if (this.closeButton) { - this.dialogElem.classList.add("hasCloseButton"); - - const closeBtn = document.createElement("button"); - closeBtn.classList.add("closeButton"); - - this.trackClicks(closeBtn, () => this.internalButtonHandler("close-button"), { - applyCssClass: "pressedSmallElement", - }); - - title.appendChild(closeBtn); - this.inputReciever.backButton.add(() => this.internalButtonHandler("close-button")); - } - - const content = document.createElement("div"); - content.classList.add("content"); - content.innerHTML = this.contentHTML; - this.dialogElem.appendChild(content); - - if (this.buttonIds.length > 0) { - const buttons = document.createElement("div"); - buttons.classList.add("buttons"); - - // Create buttons - for (let i = 0; i < this.buttonIds.length; ++i) { - const [buttonId, buttonStyle, rawParams] = this.buttonIds[i].split(":"); - - const button = document.createElement("button"); - button.classList.add("button"); - button.classList.add("styledButton"); - button.classList.add(buttonStyle); - button.innerText = T.dialogs.buttons[buttonId]; - - const params = (rawParams || "").split("/"); - const useTimeout = params.indexOf("timeout") >= 0; - - const isEnter = params.indexOf("enter") >= 0; - const isEscape = params.indexOf("escape") >= 0; - - if (isEscape && this.closeButton) { - logger.warn("Showing dialog with close button, and additional cancel button"); - } - - if (useTimeout) { - button.classList.add("timedButton"); - const timeout = setTimeout(() => { - button.classList.remove("timedButton"); - arrayDeleteValue(this.timeouts, timeout); - }, 5000); - this.timeouts.push(timeout); - } - if (isEnter || isEscape) { - // if (this.app.settings.getShowKeyboardShortcuts()) { - // Show keybinding - const spacer = document.createElement("code"); - spacer.classList.add("keybinding"); - spacer.innerHTML = getStringForKeyCode(isEnter ? kbEnter : kbCancel); - button.appendChild(spacer); - // } - - if (isEnter) { - this.enterHandler = buttonId; - } - if (isEscape) { - this.escapeHandler = buttonId; - } - } - - this.trackClicks(button, () => this.internalButtonHandler(buttonId)); - buttons.appendChild(button); - } - - this.dialogElem.appendChild(buttons); - } else { - this.dialogElem.classList.add("buttonless"); - } - - this.element = elem; - this.app.inputMgr.pushReciever(this.inputReciever); - - return this.element; - } - - setIndex(index) { - this.element.style.zIndex = index; - } - - destroy() { - if (!this.element) { - assert(false, "Tried to destroy dialog twice"); - return; - } - // We need to do this here, because if the backbutton event gets - // dispatched to the modal dialogs, it will not call the internalButtonHandler, - // and thus our receiver stays attached the whole time - this.app.inputMgr.destroyReceiver(this.inputReciever); - - for (let i = 0; i < this.clickDetectors.length; ++i) { - this.clickDetectors[i].cleanup(); - } - this.clickDetectors = []; - - this.element.remove(); - this.element = null; - - for (let i = 0; i < this.timeouts.length; ++i) { - clearTimeout(this.timeouts[i]); - } - this.timeouts = []; - } - - hide() { - this.element.classList.remove("visible"); - } - - show() { - this.element.classList.add("visible"); - } - - /** - * Helper method to track clicks on an element - * @param {Element} elem - * @param {function():void} handler - * @param {import("./click_detector").ClickDetectorConstructorArgs=} args - * @returns {ClickDetector} - */ - trackClicks(elem, handler, args = {}) { - const detector = new ClickDetector(elem, args); - detector.click.add(handler, this); - this.clickDetectors.push(detector); - return detector; - } -} - -/** - * Dialog which simply shows a loading spinner - */ -export class DialogLoading extends Dialog { - constructor(app) { - super({ - app, - title: "", - contentHTML: "", - buttons: [], - type: "loading", - }); - - // Loading dialog can not get closed with back button - this.inputReciever.backButton.removeAll(); - this.inputReciever.context = "dialog-loading"; - } - - createElement() { - const elem = document.createElement("div"); - elem.classList.add("ingameDialog"); - elem.classList.add("loadingDialog"); - this.element = elem; - - const loader = document.createElement("div"); - loader.classList.add("prefab_LoadingTextWithAnim"); - loader.classList.add("loadingIndicator"); - loader.innerText = T.global.loading; - elem.appendChild(loader); - - this.app.inputMgr.pushReciever(this.inputReciever); - - return elem; - } -} - -export class DialogOptionChooser extends Dialog { - constructor({ app, title, options }) { - let html = "
"; - - options.options.forEach(({ value, text, desc = null, iconPrefix = null }) => { - const descHtml = desc ? `${desc}` : ""; - let iconHtml = iconPrefix ? `` : ""; - html += ` -
- ${iconHtml} - ${text} - ${descHtml} -
- `; - }); - - html += "
"; - super({ - app, - title, - contentHTML: html, - buttons: [], - type: "info", - closeButton: true, - }); - - this.options = options; - this.initialOption = options.active; - - this.buttonSignals.optionSelected = new Signal(); - } - - createElement() { - const div = super.createElement(); - this.dialogElem.classList.add("optionChooserDialog"); - - div.querySelectorAll("[data-optionvalue]").forEach(handle => { - const value = handle.getAttribute("data-optionvalue"); - if (!handle) { - logger.error("Failed to bind option value in dialog:", value); - return; - } - // Need click detector here to forward elements, otherwise scrolling does not work - const detector = new ClickDetector(handle, { - consumeEvents: false, - preventDefault: false, - clickSound: null, - applyCssClass: "pressedOption", - targetOnly: true, - }); - this.clickDetectors.push(detector); - - if (value !== this.initialOption) { - detector.click.add(() => { - const selected = div.querySelector(".option.active"); - if (selected) { - selected.classList.remove("active"); - } else { - logger.warn("No selected option"); - } - handle.classList.add("active"); - this.app.sound.playUiSound(SOUNDS.uiClick); - this.internalButtonHandler("optionSelected", value); - }); - } - }); - return div; - } -} - -export class DialogWithForm extends Dialog { - /** - * - * @param {object} param0 - * @param {Application} param0.app - * @param {string} param0.title - * @param {string} param0.desc - * @param {array=} param0.buttons - * @param {string=} param0.confirmButtonId - * @param {string=} param0.extraButton - * @param {Array} param0.formElements - */ - constructor({ app, title, desc, formElements, buttons = ["cancel", "ok:good"], confirmButtonId = "ok" }) { - let html = ""; - html += desc + "
"; - for (let i = 0; i < formElements.length; ++i) { - html += formElements[i].getHtml(); - } - - super({ - app, - title: title, - contentHTML: html, - buttons: buttons, - type: "info", - closeButton: true, - }); - this.confirmButtonId = confirmButtonId; - this.formElements = formElements; - - this.enterHandler = confirmButtonId; - } - - internalButtonHandler(id, ...payload) { - if (id === this.confirmButtonId) { - if (this.hasAnyInvalid()) { - this.dialogElem.classList.remove("errorShake"); - waitNextFrame().then(() => { - if (this.dialogElem) { - this.dialogElem.classList.add("errorShake"); - } - }); - this.app.sound.playUiSound(SOUNDS.uiError); - return; - } - } - - super.internalButtonHandler(id, payload); - } - - hasAnyInvalid() { - for (let i = 0; i < this.formElements.length; ++i) { - if (!this.formElements[i].isValid()) { - return true; - } - } - return false; - } - - createElement() { - const div = super.createElement(); - - for (let i = 0; i < this.formElements.length; ++i) { - const elem = this.formElements[i]; - elem.bindEvents(div, this.clickDetectors); - } - - waitNextFrame().then(() => { - this.formElements[0].focus(); - }); - - return div; - } -} +/* typehints:start */ +import { Application } from "../application"; +/* typehints:end */ + +import { Signal, STOP_PROPAGATION } from "./signal"; +import { arrayDeleteValue, waitNextFrame } from "./utils"; +import { ClickDetector } from "./click_detector"; +import { SOUNDS } from "../platform/sound"; +import { InputReceiver } from "./input_receiver"; +import { FormElement } from "./modal_dialog_forms"; +import { globalConfig } from "./config"; +import { getStringForKeyCode } from "../game/key_action_mapper"; +import { createLogger } from "./logging"; +import { T } from "../translations"; + +const kbEnter = 13; +const kbCancel = 27; + +const logger = createLogger("dialogs"); + +/** + * Basic text based dialog + */ +export class Dialog { + /** + * + * Constructs a new dialog with the given options + * @param {object} param0 + * @param {Application} param0.app + * @param {string} param0.title Title of the dialog + * @param {string} param0.contentHTML Inner dialog html + * @param {Array} param0.buttons + * Button list, each button contains of up to 3 parts seperated by ':'. + * Part 0: The id, one of the one defined in dialog_buttons.yaml + * Part 1: The style, either good, bad or misc + * Part 2 (optional): Additional parameters seperated by '/', available are: + * timeout: This button is only available after some waiting time + * kb_enter: This button is triggered by the enter key + * kb_escape This button is triggered by the escape key + * @param {string=} param0.type The dialog type, either "info" or "warn" + * @param {boolean=} param0.closeButton Whether this dialog has a close button + */ + constructor({ app, title, contentHTML, buttons, type = "info", closeButton = false }) { + this.app = app; + this.title = title; + this.contentHTML = contentHTML; + this.type = type; + this.buttonIds = buttons; + this.closeButton = closeButton; + + this.closeRequested = new Signal(); + this.buttonSignals = {}; + + for (let i = 0; i < buttons.length; ++i) { + if (G_IS_DEV && globalConfig.debug.disableTimedButtons) { + this.buttonIds[i] = this.buttonIds[i].replace(":timeout", ""); + } + + const buttonId = this.buttonIds[i].split(":")[0]; + this.buttonSignals[buttonId] = new Signal(); + } + + this.timeouts = []; + this.clickDetectors = []; + + this.inputReciever = new InputReceiver("dialog-" + this.title); + + this.inputReciever.keydown.add(this.handleKeydown, this); + + this.enterHandler = null; + this.escapeHandler = null; + } + + /** + * Internal keydown handler + * @param {object} param0 + * @param {number} param0.keyCode + * @param {boolean} param0.shift + * @param {boolean} param0.alt + */ + handleKeydown({ keyCode, shift, alt }) { + if (keyCode === kbEnter && this.enterHandler) { + this.internalButtonHandler(this.enterHandler); + return STOP_PROPAGATION; + } + + if (keyCode === kbCancel && this.escapeHandler) { + this.internalButtonHandler(this.escapeHandler); + return STOP_PROPAGATION; + } + } + + internalButtonHandler(id, ...payload) { + this.app.inputMgr.popReciever(this.inputReciever); + + if (id !== "close-button") { + this.buttonSignals[id].dispatch(...payload); + } + this.closeRequested.dispatch(); + } + + createElement() { + const elem = document.createElement("div"); + elem.classList.add("ingameDialog"); + + this.dialogElem = document.createElement("div"); + this.dialogElem.classList.add("dialogInner"); + + if (this.type) { + this.dialogElem.classList.add(this.type); + } + elem.appendChild(this.dialogElem); + + const title = document.createElement("h1"); + title.innerText = this.title; + title.classList.add("title"); + this.dialogElem.appendChild(title); + + if (this.closeButton) { + this.dialogElem.classList.add("hasCloseButton"); + + const closeBtn = document.createElement("button"); + closeBtn.classList.add("closeButton"); + + this.trackClicks(closeBtn, () => this.internalButtonHandler("close-button"), { + applyCssClass: "pressedSmallElement", + }); + + title.appendChild(closeBtn); + this.inputReciever.backButton.add(() => this.internalButtonHandler("close-button")); + } + + const content = document.createElement("div"); + content.classList.add("content"); + content.innerHTML = this.contentHTML; + this.dialogElem.appendChild(content); + + if (this.buttonIds.length > 0) { + const buttons = document.createElement("div"); + buttons.classList.add("buttons"); + + // Create buttons + for (let i = 0; i < this.buttonIds.length; ++i) { + const [buttonId, buttonStyle, rawParams] = this.buttonIds[i].split(":"); + + const button = document.createElement("button"); + button.classList.add("button"); + button.classList.add("styledButton"); + button.classList.add(buttonStyle); + button.innerText = T.dialogs.buttons[buttonId]; + + const params = (rawParams || "").split("/"); + const useTimeout = params.indexOf("timeout") >= 0; + + const isEnter = params.indexOf("enter") >= 0; + const isEscape = params.indexOf("escape") >= 0; + + if (isEscape && this.closeButton) { + logger.warn("Showing dialog with close button, and additional cancel button"); + } + + if (useTimeout) { + button.classList.add("timedButton"); + const timeout = setTimeout(() => { + button.classList.remove("timedButton"); + arrayDeleteValue(this.timeouts, timeout); + }, 5000); + this.timeouts.push(timeout); + } + if (isEnter || isEscape) { + // if (this.app.settings.getShowKeyboardShortcuts()) { + // Show keybinding + const spacer = document.createElement("code"); + spacer.classList.add("keybinding"); + spacer.innerHTML = getStringForKeyCode(isEnter ? kbEnter : kbCancel); + button.appendChild(spacer); + // } + + if (isEnter) { + this.enterHandler = buttonId; + } + if (isEscape) { + this.escapeHandler = buttonId; + } + } + + this.trackClicks(button, () => this.internalButtonHandler(buttonId)); + buttons.appendChild(button); + } + + this.dialogElem.appendChild(buttons); + } else { + this.dialogElem.classList.add("buttonless"); + } + + this.element = elem; + this.app.inputMgr.pushReciever(this.inputReciever); + + return this.element; + } + + setIndex(index) { + this.element.style.zIndex = index; + } + + destroy() { + if (!this.element) { + assert(false, "Tried to destroy dialog twice"); + return; + } + // We need to do this here, because if the backbutton event gets + // dispatched to the modal dialogs, it will not call the internalButtonHandler, + // and thus our receiver stays attached the whole time + this.app.inputMgr.destroyReceiver(this.inputReciever); + + for (let i = 0; i < this.clickDetectors.length; ++i) { + this.clickDetectors[i].cleanup(); + } + this.clickDetectors = []; + + this.element.remove(); + this.element = null; + + for (let i = 0; i < this.timeouts.length; ++i) { + clearTimeout(this.timeouts[i]); + } + this.timeouts = []; + } + + hide() { + this.element.classList.remove("visible"); + } + + show() { + this.element.classList.add("visible"); + } + + /** + * Helper method to track clicks on an element + * @param {Element} elem + * @param {function():void} handler + * @param {import("./click_detector").ClickDetectorConstructorArgs=} args + * @returns {ClickDetector} + */ + trackClicks(elem, handler, args = {}) { + const detector = new ClickDetector(elem, args); + detector.click.add(handler, this); + this.clickDetectors.push(detector); + return detector; + } +} + +/** + * Dialog which simply shows a loading spinner + */ +export class DialogLoading extends Dialog { + constructor(app) { + super({ + app, + title: "", + contentHTML: "", + buttons: [], + type: "loading", + }); + + // Loading dialog can not get closed with back button + this.inputReciever.backButton.removeAll(); + this.inputReciever.context = "dialog-loading"; + } + + createElement() { + const elem = document.createElement("div"); + elem.classList.add("ingameDialog"); + elem.classList.add("loadingDialog"); + this.element = elem; + + const loader = document.createElement("div"); + loader.classList.add("prefab_LoadingTextWithAnim"); + loader.classList.add("loadingIndicator"); + loader.innerText = T.global.loading; + elem.appendChild(loader); + + this.app.inputMgr.pushReciever(this.inputReciever); + + return elem; + } +} + +export class DialogOptionChooser extends Dialog { + constructor({ app, title, options }) { + let html = "
"; + + options.options.forEach(({ value, text, desc = null, iconPrefix = null }) => { + const descHtml = desc ? `${desc}` : ""; + let iconHtml = iconPrefix ? `` : ""; + html += ` +
+ ${iconHtml} + ${text} + ${descHtml} +
+ `; + }); + + html += "
"; + super({ + app, + title, + contentHTML: html, + buttons: [], + type: "info", + closeButton: true, + }); + + this.options = options; + this.initialOption = options.active; + + this.buttonSignals.optionSelected = new Signal(); + } + + createElement() { + const div = super.createElement(); + this.dialogElem.classList.add("optionChooserDialog"); + + div.querySelectorAll("[data-optionvalue]").forEach(handle => { + const value = handle.getAttribute("data-optionvalue"); + if (!handle) { + logger.error("Failed to bind option value in dialog:", value); + return; + } + // Need click detector here to forward elements, otherwise scrolling does not work + const detector = new ClickDetector(handle, { + consumeEvents: false, + preventDefault: false, + clickSound: null, + applyCssClass: "pressedOption", + targetOnly: true, + }); + this.clickDetectors.push(detector); + + if (value !== this.initialOption) { + detector.click.add(() => { + const selected = div.querySelector(".option.active"); + if (selected) { + selected.classList.remove("active"); + } else { + logger.warn("No selected option"); + } + handle.classList.add("active"); + this.app.sound.playUiSound(SOUNDS.uiClick); + this.internalButtonHandler("optionSelected", value); + }); + } + }); + return div; + } +} + +export class DialogWithForm extends Dialog { + /** + * + * @param {object} param0 + * @param {Application} param0.app + * @param {string} param0.title + * @param {string} param0.desc + * @param {array=} param0.buttons + * @param {string=} param0.confirmButtonId + * @param {string=} param0.extraButton + * @param {boolean=} param0.closeButton + * @param {Array} param0.formElements + */ + constructor({ + app, + title, + desc, + formElements, + buttons = ["cancel", "ok:good"], + confirmButtonId = "ok", + closeButton = true, + }) { + let html = ""; + html += desc + "
"; + for (let i = 0; i < formElements.length; ++i) { + html += formElements[i].getHtml(); + } + + super({ + app, + title: title, + contentHTML: html, + buttons: buttons, + type: "info", + closeButton, + }); + this.confirmButtonId = confirmButtonId; + this.formElements = formElements; + + this.enterHandler = confirmButtonId; + } + + internalButtonHandler(id, ...payload) { + if (id === this.confirmButtonId) { + if (this.hasAnyInvalid()) { + this.dialogElem.classList.remove("errorShake"); + waitNextFrame().then(() => { + if (this.dialogElem) { + this.dialogElem.classList.add("errorShake"); + } + }); + this.app.sound.playUiSound(SOUNDS.uiError); + return; + } + } + + super.internalButtonHandler(id, payload); + } + + hasAnyInvalid() { + for (let i = 0; i < this.formElements.length; ++i) { + if (!this.formElements[i].isValid()) { + return true; + } + } + return false; + } + + createElement() { + const div = super.createElement(); + + for (let i = 0; i < this.formElements.length; ++i) { + const elem = this.formElements[i]; + elem.bindEvents(div, this.clickDetectors); + } + + waitNextFrame().then(() => { + this.formElements[0].focus(); + }); + + return div; + } +} diff --git a/src/js/core/read_write_proxy.js b/src/js/core/read_write_proxy.js index 5474467a..74b13efa 100644 --- a/src/js/core/read_write_proxy.js +++ b/src/js/core/read_write_proxy.js @@ -1,342 +1,347 @@ -/* typehints:start */ -import { Application } from "../application"; -/* typehints:end */ - -import { sha1 } from "./sensitive_utils.encrypt"; -import { createLogger } from "./logging"; -import { FILE_NOT_FOUND } from "../platform/storage"; -import { accessNestedPropertyReverse } from "./utils"; -import { IS_DEBUG, globalConfig } from "./config"; -import { ExplainedResult } from "./explained_result"; -import { decompressX64, compressX64 } from ".//lzstring"; -import { asyncCompressor, compressionPrefix } from "./async_compression"; -import { compressObject, decompressObject } from "../savegame/savegame_compressor"; - -const logger = createLogger("read_write_proxy"); - -const salt = accessNestedPropertyReverse(globalConfig, ["file", "info"]); - -// Helper which only writes / reads if verify() works. Also performs migration -export class ReadWriteProxy { - constructor(app, filename) { - /** @type {Application} */ - this.app = app; - - this.filename = filename; - - /** @type {object} */ - this.currentData = null; - - // TODO: EXTREMELY HACKY! To verify we need to do this a step later - if (G_IS_DEV && IS_DEBUG) { - setTimeout(() => { - assert( - this.verify(this.getDefaultData()).result, - "Verify() failed for default data: " + this.verify(this.getDefaultData()).reason - ); - }); - } - } - - // -- Methods to override - - /** @returns {ExplainedResult} */ - verify(data) { - abstract; - return ExplainedResult.bad(); - } - - // Should return the default data - getDefaultData() { - abstract; - return {}; - } - - // Should return the current version as an integer - getCurrentVersion() { - abstract; - return 0; - } - - // Should migrate the data (Modify in place) - /** @returns {ExplainedResult} */ - migrate(data) { - abstract; - return ExplainedResult.bad(); - } - - // -- / Methods - - // Resets whole data, returns promise - resetEverythingAsync() { - logger.warn("Reset data to default"); - this.currentData = this.getDefaultData(); - return this.writeAsync(); - } - - getCurrentData() { - return this.currentData; - } - - /** - * - * @param {object} obj - */ - static serializeObject(obj) { - const jsonString = JSON.stringify(compressObject(obj)); - const checksum = sha1(jsonString + salt); - return compressionPrefix + compressX64(checksum + jsonString); - } - - /** - * - * @param {object} text - */ - static deserializeObject(text) { - const decompressed = decompressX64(text.substr(compressionPrefix.length)); - if (!decompressed) { - // LZ string decompression failure - throw new Error("bad-content / decompression-failed"); - } - if (decompressed.length < 40) { - // String too short - throw new Error("bad-content / payload-too-small"); - } - - // Compare stored checksum with actual checksum - const checksum = decompressed.substring(0, 40); - const jsonString = decompressed.substr(40); - const desiredChecksum = sha1(jsonString + salt); - if (desiredChecksum !== checksum) { - // Checksum mismatch - throw new Error("bad-content / checksum-mismatch"); - } - - const parsed = JSON.parse(jsonString); - const decoded = decompressObject(parsed); - return decoded; - } - - /** - * Writes the data asychronously, fails if verify() fails - * @returns {Promise} - */ - writeAsync() { - const verifyResult = this.internalVerifyEntry(this.currentData); - - if (!verifyResult.result) { - logger.error("Tried to write invalid data to", this.filename, "reason:", verifyResult.reason); - return Promise.reject(verifyResult.reason); - } - const jsonString = JSON.stringify(compressObject(this.currentData)); - - // if (!this.app.pageVisible || this.app.unloaded) { - // logger.log("Saving file sync because in unload handler"); - // const checksum = sha1(jsonString + salt); - // let compressed = compressionPrefix + compressX64(checksum + jsonString); - // if (G_IS_DEV && IS_DEBUG) { - // compressed = jsonString; - // } - - // if (!this.app.storage.writeFileSyncIfSupported(this.filename, compressed)) { - // return Promise.reject("Failed to write " + this.filename + " sync!"); - // } else { - // logger.log("📄 Wrote (sync!)", this.filename); - // return Promise.resolve(compressed); - // } - // } - - return asyncCompressor - .compressFileAsync(jsonString) - .then(compressed => { - if (G_IS_DEV && IS_DEBUG) { - compressed = jsonString; - } - return this.app.storage.writeFileAsync(this.filename, compressed); - }) - .then(() => { - logger.log("📄 Wrote", this.filename); - return jsonString; - }) - .catch(err => { - logger.error("Failed to write", this.filename, ":", err); - throw err; - }); - } - - // Reads the data asynchronously, fails if verify() fails - readAsync() { - // Start read request - return ( - this.app.storage - .readFileAsync(this.filename) - - // Check for errors during read - .catch(err => { - if (err === FILE_NOT_FOUND) { - logger.log("File not found, using default data"); - - // File not found or unreadable, assume default file - return Promise.resolve(null); - } - - return Promise.reject("file-error: " + err); - }) - - // Decrypt data (if its encrypted) - // @ts-ignore - .then(rawData => { - if (rawData == null) { - // So, the file has not been found, use default data - return JSON.stringify(compressObject(this.getDefaultData())); - } - - if (rawData.startsWith(compressionPrefix)) { - const decompressed = decompressX64(rawData.substr(compressionPrefix.length)); - if (!decompressed) { - // LZ string decompression failure - return Promise.reject("bad-content / decompression-failed"); - } - if (decompressed.length < 40) { - // String too short - return Promise.reject("bad-content / payload-too-small"); - } - - // Compare stored checksum with actual checksum - const checksum = decompressed.substring(0, 40); - const jsonString = decompressed.substr(40); - const desiredChecksum = sha1(jsonString + salt); - if (desiredChecksum !== checksum) { - // Checksum mismatch - return Promise.reject("bad-content / checksum-mismatch"); - } - return jsonString; - } else { - if (!G_IS_DEV) { - return Promise.reject("bad-content / missing-compression"); - } - } - return rawData; - }) - - // Parse JSON, this could throw but thats fine - .then(res => { - try { - return JSON.parse(res); - } catch (ex) { - logger.error( - "Failed to parse file content of", - this.filename, - ":", - ex, - "(content was:", - res, - ")" - ); - throw new Error("invalid-serialized-data"); - } - }) - - // Decompress - .then(compressed => decompressObject(compressed)) - - // Verify basic structure - .then(contents => { - const result = this.internalVerifyBasicStructure(contents); - if (!result.isGood()) { - return Promise.reject("verify-failed: " + result.reason); - } - return contents; - }) - - // Check version and migrate if required - .then(contents => { - if (contents.version > this.getCurrentVersion()) { - return Promise.reject("stored-data-is-newer"); - } - - if (contents.version < this.getCurrentVersion()) { - logger.log( - "Trying to migrate data object from version", - contents.version, - "to", - this.getCurrentVersion() - ); - const migrationResult = this.migrate(contents); // modify in place - if (migrationResult.isBad()) { - return Promise.reject("migration-failed: " + migrationResult.reason); - } - } - return contents; - }) - - // Verify - .then(contents => { - const verifyResult = this.internalVerifyEntry(contents); - if (!verifyResult.result) { - logger.error( - "Read invalid data from", - this.filename, - "reason:", - verifyResult.reason, - "contents:", - contents - ); - return Promise.reject("invalid-data: " + verifyResult.reason); - } - return contents; - }) - - // Store - .then(contents => { - this.currentData = contents; - logger.log("📄 Read data with version", this.currentData.version, "from", this.filename); - return contents; - }) - - // Catchall - .catch(err => { - return Promise.reject("Failed to read " + this.filename + ": " + err); - }) - ); - } - - /** - * Deletes the file - * @returns {Promise} - */ - deleteAsync() { - return this.app.storage.deleteFileAsync(this.filename); - } - - // Internal - - /** @returns {ExplainedResult} */ - internalVerifyBasicStructure(data) { - if (!data) { - return ExplainedResult.bad("Data is empty"); - } - if (!Number.isInteger(data.version) || data.version < 0) { - return ExplainedResult.bad( - `Data has invalid version: ${data.version} (expected ${this.getCurrentVersion()})` - ); - } - - return ExplainedResult.good(); - } - - /** @returns {ExplainedResult} */ - internalVerifyEntry(data) { - if (data.version !== this.getCurrentVersion()) { - return ExplainedResult.bad( - "Version mismatch, got " + data.version + " and expected " + this.getCurrentVersion() - ); - } - - const verifyStructureError = this.internalVerifyBasicStructure(data); - if (!verifyStructureError.isGood()) { - return verifyStructureError; - } - return this.verify(data); - } -} +/* typehints:start */ +import { Application } from "../application"; +/* typehints:end */ + +import { sha1, CRC_PREFIX, computeCrc } from "./sensitive_utils.encrypt"; +import { createLogger } from "./logging"; +import { FILE_NOT_FOUND } from "../platform/storage"; +import { accessNestedPropertyReverse } from "./utils"; +import { IS_DEBUG, globalConfig } from "./config"; +import { ExplainedResult } from "./explained_result"; +import { decompressX64, compressX64 } from "./lzstring"; +import { asyncCompressor, compressionPrefix } from "./async_compression"; +import { compressObject, decompressObject } from "../savegame/savegame_compressor"; + +const debounce = require("debounce-promise"); + +const logger = createLogger("read_write_proxy"); + +const salt = accessNestedPropertyReverse(globalConfig, ["file", "info"]); + +// Helper which only writes / reads if verify() works. Also performs migration +export class ReadWriteProxy { + constructor(app, filename) { + /** @type {Application} */ + this.app = app; + + this.filename = filename; + + /** @type {object} */ + this.currentData = null; + + // TODO: EXTREMELY HACKY! To verify we need to do this a step later + if (G_IS_DEV && IS_DEBUG) { + setTimeout(() => { + assert( + this.verify(this.getDefaultData()).result, + "Verify() failed for default data: " + this.verify(this.getDefaultData()).reason + ); + }); + } + + /** + * Store a debounced handler to prevent double writes + */ + this.debouncedWrite = debounce(this.doWriteAsync.bind(this), 50); + } + + // -- Methods to override + + /** @returns {ExplainedResult} */ + verify(data) { + abstract; + return ExplainedResult.bad(); + } + + // Should return the default data + getDefaultData() { + abstract; + return {}; + } + + // Should return the current version as an integer + getCurrentVersion() { + abstract; + return 0; + } + + // Should migrate the data (Modify in place) + /** @returns {ExplainedResult} */ + migrate(data) { + abstract; + return ExplainedResult.bad(); + } + + // -- / Methods + + // Resets whole data, returns promise + resetEverythingAsync() { + logger.warn("Reset data to default"); + this.currentData = this.getDefaultData(); + return this.writeAsync(); + } + + getCurrentData() { + return this.currentData; + } + + /** + * + * @param {object} obj + */ + static serializeObject(obj) { + const jsonString = JSON.stringify(compressObject(obj)); + const checksum = computeCrc(jsonString + salt); + return compressionPrefix + compressX64(checksum + jsonString); + } + + /** + * + * @param {object} text + */ + static deserializeObject(text) { + const decompressed = decompressX64(text.substr(compressionPrefix.length)); + if (!decompressed) { + // LZ string decompression failure + throw new Error("bad-content / decompression-failed"); + } + if (decompressed.length < 40) { + // String too short + throw new Error("bad-content / payload-too-small"); + } + + // Compare stored checksum with actual checksum + const checksum = decompressed.substring(0, 40); + const jsonString = decompressed.substr(40); + + const desiredChecksum = checksum.startsWith(CRC_PREFIX) + ? computeCrc(jsonString + salt) + : sha1(jsonString + salt); + + if (desiredChecksum !== checksum) { + // Checksum mismatch + throw new Error("bad-content / checksum-mismatch"); + } + + const parsed = JSON.parse(jsonString); + const decoded = decompressObject(parsed); + return decoded; + } + + /** + * Writes the data asychronously, fails if verify() fails. + * Debounces the operation by up to 50ms + * @returns {Promise} + */ + writeAsync() { + const verifyResult = this.internalVerifyEntry(this.currentData); + + if (!verifyResult.result) { + logger.error("Tried to write invalid data to", this.filename, "reason:", verifyResult.reason); + return Promise.reject(verifyResult.reason); + } + + return this.debouncedWrite(); + } + + /** + * Actually writes the data asychronously + * @returns {Promise} + */ + doWriteAsync() { + return asyncCompressor + .compressObjectAsync(this.currentData) + .then(compressed => { + return this.app.storage.writeFileAsync(this.filename, compressed); + }) + .then(() => { + logger.log("📄 Wrote", this.filename); + }) + .catch(err => { + logger.error("Failed to write", this.filename, ":", err); + throw err; + }); + } + + // Reads the data asynchronously, fails if verify() fails + readAsync() { + // Start read request + return ( + this.app.storage + .readFileAsync(this.filename) + + // Check for errors during read + .catch(err => { + if (err === FILE_NOT_FOUND) { + logger.log("File not found, using default data"); + + // File not found or unreadable, assume default file + return Promise.resolve(null); + } + + return Promise.reject("file-error: " + err); + }) + + // Decrypt data (if its encrypted) + // @ts-ignore + .then(rawData => { + if (rawData == null) { + // So, the file has not been found, use default data + return JSON.stringify(compressObject(this.getDefaultData())); + } + + if (rawData.startsWith(compressionPrefix)) { + const decompressed = decompressX64(rawData.substr(compressionPrefix.length)); + if (!decompressed) { + // LZ string decompression failure + return Promise.reject("bad-content / decompression-failed"); + } + if (decompressed.length < 40) { + // String too short + return Promise.reject("bad-content / payload-too-small"); + } + + // Compare stored checksum with actual checksum + const checksum = decompressed.substring(0, 40); + const jsonString = decompressed.substr(40); + + const desiredChecksum = checksum.startsWith(CRC_PREFIX) + ? computeCrc(jsonString + salt) + : sha1(jsonString + salt); + + if (desiredChecksum !== checksum) { + // Checksum mismatch + return Promise.reject( + "bad-content / checksum-mismatch: " + desiredChecksum + " vs " + checksum + ); + } + return jsonString; + } else { + if (!G_IS_DEV) { + return Promise.reject("bad-content / missing-compression"); + } + } + return rawData; + }) + + // Parse JSON, this could throw but thats fine + .then(res => { + try { + return JSON.parse(res); + } catch (ex) { + logger.error( + "Failed to parse file content of", + this.filename, + ":", + ex, + "(content was:", + res, + ")" + ); + throw new Error("invalid-serialized-data"); + } + }) + + // Decompress + .then(compressed => decompressObject(compressed)) + + // Verify basic structure + .then(contents => { + const result = this.internalVerifyBasicStructure(contents); + if (!result.isGood()) { + return Promise.reject("verify-failed: " + result.reason); + } + return contents; + }) + + // Check version and migrate if required + .then(contents => { + if (contents.version > this.getCurrentVersion()) { + return Promise.reject("stored-data-is-newer"); + } + + if (contents.version < this.getCurrentVersion()) { + logger.log( + "Trying to migrate data object from version", + contents.version, + "to", + this.getCurrentVersion() + ); + const migrationResult = this.migrate(contents); // modify in place + if (migrationResult.isBad()) { + return Promise.reject("migration-failed: " + migrationResult.reason); + } + } + return contents; + }) + + // Verify + .then(contents => { + const verifyResult = this.internalVerifyEntry(contents); + if (!verifyResult.result) { + logger.error( + "Read invalid data from", + this.filename, + "reason:", + verifyResult.reason, + "contents:", + contents + ); + return Promise.reject("invalid-data: " + verifyResult.reason); + } + return contents; + }) + + // Store + .then(contents => { + this.currentData = contents; + logger.log("📄 Read data with version", this.currentData.version, "from", this.filename); + return contents; + }) + + // Catchall + .catch(err => { + return Promise.reject("Failed to read " + this.filename + ": " + err); + }) + ); + } + + /** + * Deletes the file + * @returns {Promise} + */ + deleteAsync() { + return this.app.storage.deleteFileAsync(this.filename); + } + + // Internal + + /** @returns {ExplainedResult} */ + internalVerifyBasicStructure(data) { + if (!data) { + return ExplainedResult.bad("Data is empty"); + } + if (!Number.isInteger(data.version) || data.version < 0) { + return ExplainedResult.bad( + `Data has invalid version: ${data.version} (expected ${this.getCurrentVersion()})` + ); + } + + return ExplainedResult.good(); + } + + /** @returns {ExplainedResult} */ + internalVerifyEntry(data) { + if (data.version !== this.getCurrentVersion()) { + return ExplainedResult.bad( + "Version mismatch, got " + data.version + " and expected " + this.getCurrentVersion() + ); + } + + const verifyStructureError = this.internalVerifyBasicStructure(data); + if (!verifyStructureError.isGood()) { + return verifyStructureError; + } + return this.verify(data); + } +} diff --git a/src/js/core/rectangle.js b/src/js/core/rectangle.js index 75279e58..f17825ca 100644 --- a/src/js/core/rectangle.js +++ b/src/js/core/rectangle.js @@ -1,5 +1,5 @@ import { globalConfig } from "./config"; -import { clamp, epsilonCompare, round2Digits } from "./utils"; +import { epsilonCompare, round2Digits } from "./utils"; import { Vector } from "./vector"; export class Rectangle { @@ -53,27 +53,6 @@ export class Rectangle { return a.left <= b.right && b.left <= a.right && a.top <= b.bottom && b.top <= a.bottom; } - /** - * Returns a rectangle arround a rotated point - * @param {Array} points - * @param {number} angle - * @returns {Rectangle} - */ - static getAroundPointsRotated(points, angle) { - let minX = 1e10; - let minY = 1e10; - let maxX = -1e10; - let maxY = -1e10; - for (let i = 0; i < points.length; ++i) { - const rotated = points[i].rotated(angle); - minX = Math.min(minX, rotated.x); - minY = Math.min(minY, rotated.y); - maxX = Math.max(maxX, rotated.x); - maxY = Math.max(maxY, rotated.y); - } - return new Rectangle(minX, minY, maxX - minX, maxY - minY); - } - /** * Copies this instance * @returns {Rectangle} @@ -82,28 +61,6 @@ export class Rectangle { return new Rectangle(this.x, this.y, this.w, this.h); } - /** - * Ensures the rectangle contains the given square - * @param {number} centerX - * @param {number} centerY - * @param {number} halfWidth - * @param {number} halfHeight - */ - extendBySquare(centerX, centerY, halfWidth, halfHeight) { - if (this.isEmpty()) { - // Just assign values since this rectangle is empty - this.x = centerX - halfWidth; - this.y = centerY - halfHeight; - this.w = halfWidth * 2; - this.h = halfHeight * 2; - } else { - this.setLeft(Math.min(this.x, centerX - halfWidth)); - this.setRight(Math.max(this.right(), centerX + halfWidth)); - this.setTop(Math.min(this.y, centerY - halfHeight)); - this.setBottom(Math.max(this.bottom(), centerY + halfHeight)); - } - } - /** * Returns if this rectangle is empty * @returns {boolean} @@ -259,14 +216,6 @@ export class Rectangle { return new Rectangle(this.x - amount, this.y - amount, this.w + 2 * amount, this.h + 2 * amount); } - /** - * Helper for computing a culling area. Returns the top left tile - * @returns {Vector} - */ - getMinStartTile() { - return new Vector(this.x, this.y).snapWorldToTile(); - } - /** * Returns if the given rectangle is contained * @param {Rectangle} rect @@ -377,23 +326,32 @@ export class Rectangle { } /** - * Returns a new recangle in tile space which includes all tiles which are visible in this rect - * @param {boolean=} includeHalfTiles + * Good for printing stuff + */ + toString() { + return ( + "[x:" + + round2Digits(this.x) + + "| y:" + + round2Digits(this.y) + + "| w:" + + round2Digits(this.w) + + "| h:" + + round2Digits(this.h) + + "]" + ); + } + + /** + * Returns a new rectangle in tile space which includes all tiles which are visible in this rect * @returns {Rectangle} */ - toTileCullRectangle(includeHalfTiles = true) { - let scaled = this.allScaled(1.0 / globalConfig.tileSize); - - if (includeHalfTiles) { - // Increase rectangle size - scaled = Rectangle.fromTRBL( - Math.floor(scaled.y), - Math.ceil(scaled.right()), - Math.ceil(scaled.bottom()), - Math.floor(scaled.x) - ); - } - - return scaled; + toTileCullRectangle() { + return new Rectangle( + Math.floor(this.x / globalConfig.tileSize), + Math.floor(this.y / globalConfig.tileSize), + Math.ceil(this.w / globalConfig.tileSize), + Math.ceil(this.h / globalConfig.tileSize) + ); } } diff --git a/src/js/core/sensitive_utils.encrypt.js b/src/js/core/sensitive_utils.encrypt.js index 710de478..5a83bf76 100644 --- a/src/js/core/sensitive_utils.encrypt.js +++ b/src/js/core/sensitive_utils.encrypt.js @@ -1,19 +1,23 @@ -import { globalConfig } from "./config"; -import { decompressX64, compressX64 } from "./lzstring"; - -const Rusha = require("rusha"); - -const encryptKey = globalConfig.info.sgSalt; - -export function decodeHashedString(s) { - return decompressX64(s); -} +import { createHash } from "rusha"; +import crc32 from "crc/crc32"; +import { decompressX64 } from "./lzstring"; export function sha1(str) { - return Rusha.createHash().update(str).digest("hex"); + return createHash().update(str).digest("hex"); } // Window.location.host export function getNameOfProvider() { - return window[decodeHashedString("DYewxghgLgliB2Q")][decodeHashedString("BYewzgLgdghgtgUyA")]; + return window[decompressX64("DYewxghgLgliB2Q")][decompressX64("BYewzgLgdghgtgUyA")]; +} + +// Distinguish legacy crc prefixes +export const CRC_PREFIX = "crc32".padEnd(32, "-"); + +/** + * Computes the crc for a given string + * @param {string} str + */ +export function computeCrc(str) { + return CRC_PREFIX + crc32(str).toString(16).padStart(8, "0"); } diff --git a/src/js/core/sprites.js b/src/js/core/sprites.js index 26cd65b2..bdcc65b4 100644 --- a/src/js/core/sprites.js +++ b/src/js/core/sprites.js @@ -1,10 +1,10 @@ import { DrawParameters } from "./draw_parameters"; import { Rectangle } from "./rectangle"; -import { epsilonCompare, round3Digits } from "./utils"; +import { round3Digits } from "./utils"; const floorSpriteCoordinates = false; -const ORIGINAL_SCALE = "1"; +export const ORIGINAL_SPRITE_SCALE = "0.75"; export class BaseSprite { /** @@ -63,10 +63,9 @@ export class SpriteAtlasLink { export class AtlasSprite extends BaseSprite { /** * - * @param {object} param0 - * @param {string} param0.spriteName + * @param {string} spriteName */ - constructor({ spriteName = "sprite" }) { + constructor(spriteName = "sprite") { super(); /** @type {Object.} */ this.linksByResolution = {}; @@ -74,7 +73,7 @@ export class AtlasSprite extends BaseSprite { } getRawTexture() { - return this.linksByResolution[ORIGINAL_SCALE].atlas; + return this.linksByResolution[ORIGINAL_SPRITE_SCALE].atlas; } /** @@ -86,11 +85,15 @@ export class AtlasSprite extends BaseSprite { assert(context instanceof CanvasRenderingContext2D, "Not a valid context"); } - const link = this.linksByResolution[ORIGINAL_SCALE]; + const link = this.linksByResolution[ORIGINAL_SPRITE_SCALE]; assert( link, - "Link not known: " + ORIGINAL_SCALE + " (having " + Object.keys(this.linksByResolution) + ")" + "Link not known: " + + ORIGINAL_SPRITE_SCALE + + " (having " + + Object.keys(this.linksByResolution) + + ")" ); const width = w || link.w; @@ -158,7 +161,9 @@ export class AtlasSprite extends BaseSprite { const scale = parameters.desiredAtlasScale; const link = this.linksByResolution[scale]; - assert(link, "Link not known: " + scale + " (having " + Object.keys(this.linksByResolution) + ")"); + if (!link) { + assert(false, `Link not known: ${scale} (having ${Object.keys(this.linksByResolution)})`); + } const scaleW = w / link.w; const scaleH = h / link.h; @@ -195,8 +200,6 @@ export class AtlasSprite extends BaseSprite { destH = intersection.h; } - // assert(epsilonCompare(scaleW, scaleH), "Sprite should be square for cached rendering"); - if (floorSpriteCoordinates) { parameters.context.drawImage( link.atlas, diff --git a/src/js/core/stale_area_detector.js b/src/js/core/stale_area_detector.js new file mode 100644 index 00000000..f8e77f0c --- /dev/null +++ b/src/js/core/stale_area_detector.js @@ -0,0 +1,50 @@ +import { createLogger } from "./logging"; +import { Rectangle } from "./rectangle"; +import { globalConfig } from "./config"; + +const logger = createLogger("stale_areas"); + +export class StaleAreaDetector { + /** + * + * @param {object} param0 + * @param {import("../game/root").GameRoot} param0.root + * @param {string} param0.name The name for reference + * @param {(Rectangle) => void} param0.recomputeMethod Method which recomputes the given area + */ + constructor({ root, name, recomputeMethod }) { + this.root = root; + this.name = name; + this.recomputeMethod = recomputeMethod; + + /** @type {Rectangle} */ + this.staleArea = null; + } + + /** + * Invalidates the given area + * @param {Rectangle} area + */ + invalidate(area) { + // logger.log(this.name, "invalidated", area.toString()); + if (this.staleArea) { + this.staleArea = this.staleArea.getUnion(area); + } else { + this.staleArea = area.clone(); + } + } + + /** + * Updates the stale area + */ + update() { + if (this.staleArea) { + logger.log(this.name, "is recomputing", this.staleArea.toString()); + if (G_IS_DEV && globalConfig.debug.renderChanges) { + this.root.hud.parts.changesDebugger.renderChange(this.name, this.staleArea, "#fd145b"); + } + this.recomputeMethod(this.staleArea); + this.staleArea = null; + } + } +} diff --git a/src/js/core/utils.js b/src/js/core/utils.js index 8f5a1dc6..a469a7a0 100644 --- a/src/js/core/utils.js +++ b/src/js/core/utils.js @@ -1,963 +1,672 @@ -import { globalConfig, IS_DEBUG } from "./config"; -import { Vector } from "./vector"; -import { T } from "../translations"; - -// Constants -export const TOP = new Vector(0, -1); -export const RIGHT = new Vector(1, 0); -export const BOTTOM = new Vector(0, 1); -export const LEFT = new Vector(-1, 0); -export const ALL_DIRECTIONS = [TOP, RIGHT, BOTTOM, LEFT]; - -const bigNumberSuffixTranslationKeys = ["thousands", "millions", "billions", "trillions"]; - -/** - * Returns the build id - * @returns {string} - */ -export function getBuildId() { - if (G_IS_DEV && IS_DEBUG) { - return "local-dev"; - } else if (G_IS_DEV) { - return "dev-" + getPlatformName() + "-" + G_BUILD_COMMIT_HASH; - } else { - return "prod-" + getPlatformName() + "-" + G_BUILD_COMMIT_HASH; - } -} - -/** - * Returns the environment id (dev, prod, etc) - * @returns {string} - */ -export function getEnvironmentId() { - if (G_IS_DEV && IS_DEBUG) { - return "local-dev"; - } else if (G_IS_DEV) { - return "dev-" + getPlatformName(); - } else if (G_IS_RELEASE) { - return "release-" + getPlatformName(); - } else { - return "staging-" + getPlatformName(); - } -} - -/** - * Returns if this platform is android - * @returns {boolean} - */ -export function isAndroid() { - if (!G_IS_MOBILE_APP) { - return false; - } - const platform = window.device.platform; - return platform === "Android" || platform === "amazon-fireos"; -} - -/** - * Returns if this platform is iOs - * @returns {boolean} - */ -export function isIos() { - if (!G_IS_MOBILE_APP) { - return false; - } - return window.device.platform === "iOS"; -} - -/** - * Returns a platform name - * @returns {string} - */ -export function getPlatformName() { - if (G_IS_STANDALONE) { - return "standalone"; - } else if (G_IS_BROWSER) { - return "browser"; - } else if (G_IS_MOBILE_APP && isAndroid()) { - return "android"; - } else if (G_IS_MOBILE_APP && isIos()) { - return "ios"; - } - return "unknown"; -} - -/** - * Returns the IPC renderer, or null if not within the standalone - * @returns {object|null} - */ -let ipcRenderer = null; -export function getIPCRenderer() { - if (!G_IS_STANDALONE) { - return null; - } - if (!ipcRenderer) { - ipcRenderer = eval("require")("electron").ipcRenderer; - } - return ipcRenderer; -} - -/** - * Formats a sensitive token by only displaying the first digits of it. Use for - * stuff like savegame keys etc which should not appear in the log. - * @param {string} key - */ -export function formatSensitive(key) { - if (!key) { - return ""; - } - key = key || ""; - return "[" + key.substr(0, 8) + "...]"; -} - -/** - * Creates a new 2D array with the given fill method - * @param {number} w Width - * @param {number} h Height - * @param {(function(number, number) : any) | number | boolean | string | null | undefined} filler Either Fill method, which should return the content for each cell, or static content - * @param {string=} context Optional context for memory tracking - * @returns {Array>} - */ -export function make2DArray(w, h, filler, context = null) { - if (typeof filler === "function") { - const tiles = new Array(w); - for (let x = 0; x < w; ++x) { - const row = new Array(h); - for (let y = 0; y < h; ++y) { - row[y] = filler(x, y); - } - tiles[x] = row; - } - return tiles; - } else { - const tiles = new Array(w); - const row = new Array(h); - for (let y = 0; y < h; ++y) { - row[y] = filler; - } - - for (let x = 0; x < w; ++x) { - tiles[x] = row.slice(); - } - return tiles; - } -} - -/** - * Makes a new 2D array with undefined contents - * @param {number} w - * @param {number} h - * @param {string=} context - * @returns {Array>} - */ -export function make2DUndefinedArray(w, h, context = null) { - const result = new Array(w); - for (let x = 0; x < w; ++x) { - result[x] = new Array(h); - } - return result; -} - -/** - * Clears a given 2D array with the given fill method - * @param {Array>} array - * @param {number} w Width - * @param {number} h Height - * @param {(function(number, number) : any) | number | boolean | string | null | undefined} filler Either Fill method, which should return the content for each cell, or static content - */ -export function clear2DArray(array, w, h, filler) { - assert(array.length === w, "Array dims mismatch w"); - assert(array[0].length === h, "Array dims mismatch h"); - if (typeof filler === "function") { - for (let x = 0; x < w; ++x) { - const row = array[x]; - for (let y = 0; y < h; ++y) { - row[y] = filler(x, y); - } - } - } else { - for (let x = 0; x < w; ++x) { - const row = array[x]; - for (let y = 0; y < h; ++y) { - row[y] = filler; - } - } - } -} - -/** - * Creates a new map (an empty object without any props) - */ -export function newEmptyMap() { - return Object.create(null); -} - -/** - * Returns a random integer in the range [start,end] - * @param {number} start - * @param {number} end - */ -export function randomInt(start, end) { - return start + Math.round(Math.random() * (end - start)); -} - -/** - * Access an object in a very annoying way, used for obsfuscation. - * @param {any} obj - * @param {Array} keys - */ -export function accessNestedPropertyReverse(obj, keys) { - let result = obj; - for (let i = keys.length - 1; i >= 0; --i) { - result = result[keys[i]]; - } - return result; -} - -/** - * Chooses a random entry of an array - * @param {Array | string} arr - */ -export function randomChoice(arr) { - return arr[Math.floor(Math.random() * arr.length)]; -} - -/** - * Deletes from an array by swapping with the last element - * @param {Array} array - * @param {number} index - */ -export function fastArrayDelete(array, index) { - if (index < 0 || index >= array.length) { - throw new Error("Out of bounds"); - } - // When the element is not the last element - if (index !== array.length - 1) { - // Get the last element, and swap it with the one we want to delete - const last = array[array.length - 1]; - array[index] = last; - } - - // Finally remove the last element - array.length -= 1; -} - -/** - * Deletes from an array by swapping with the last element. Searches - * for the value in the array first - * @param {Array} array - * @param {any} value - */ -export function fastArrayDeleteValue(array, value) { - if (array == null) { - throw new Error("Tried to delete from non array!"); - } - const index = array.indexOf(value); - if (index < 0) { - console.error("Value", value, "not contained in array:", array, "!"); - return value; - } - return fastArrayDelete(array, index); -} - -/** - * @see fastArrayDeleteValue - * @param {Array} array - * @param {any} value - */ -export function fastArrayDeleteValueIfContained(array, value) { - if (array == null) { - throw new Error("Tried to delete from non array!"); - } - const index = array.indexOf(value); - if (index < 0) { - return value; - } - return fastArrayDelete(array, index); -} - -/** - * Deletes from an array at the given index - * @param {Array} array - * @param {number} index - */ -export function arrayDelete(array, index) { - if (index < 0 || index >= array.length) { - throw new Error("Out of bounds"); - } - array.splice(index, 1); -} - -/** - * Deletes the given value from an array - * @param {Array} array - * @param {any} value - */ -export function arrayDeleteValue(array, value) { - if (array == null) { - throw new Error("Tried to delete from non array!"); - } - const index = array.indexOf(value); - if (index < 0) { - console.error("Value", value, "not contained in array:", array, "!"); - return value; - } - return arrayDelete(array, index); -} - -// Converts a direction into a 0 .. 7 index -/** - * Converts a direction into a index from 0 .. 7, used for miners, zombies etc which have 8 sprites - * @param {Vector} offset direction - * @param {boolean} inverse if inverse, the direction is reversed - * @returns {number} in range [0, 7] - */ -export function angleToSpriteIndex(offset, inverse = false) { - const twoPi = 2.0 * Math.PI; - const factor = inverse ? -1 : 1; - const offs = inverse ? 2.5 : 3.5; - const angle = (factor * Math.atan2(offset.y, offset.x) + offs * Math.PI) % twoPi; - - const index = Math.round((angle / twoPi) * 8) % 8; - return index; -} - -/** - * Compare two floats for epsilon equality - * @param {number} a - * @param {number} b - * @returns {boolean} - */ -export function epsilonCompare(a, b, epsilon = 1e-5) { - return Math.abs(a - b) < epsilon; -} - -/** - * Compare a float for epsilon equal to 0 - * @param {number} a - * @returns {boolean} - */ -export function epsilonIsZero(a) { - return epsilonCompare(a, 0); -} - -/** - * Interpolates two numbers - * @param {number} a - * @param {number} b - * @param {number} x Mix factor, 0 means 100% a, 1 means 100%b, rest is interpolated - */ -export function lerp(a, b, x) { - return a * (1 - x) + b * x; -} - -/** - * Finds a value which is nice to display, e.g. 15669 -> 15000. Also handles fractional stuff - * @param {number} num - */ -export function findNiceValue(num) { - if (num > 1e8) { - return num; - } - if (num < 0.00001) { - return 0; - } - - let roundAmount = 1; - if (num > 50000) { - roundAmount = 10000; - } else if (num > 20000) { - roundAmount = 5000; - } else if (num > 5000) { - roundAmount = 1000; - } else if (num > 2000) { - roundAmount = 500; - } else if (num > 1000) { - roundAmount = 100; - } else if (num > 100) { - roundAmount = 20; - } else if (num > 20) { - roundAmount = 5; - } - - const niceValue = Math.floor(num / roundAmount) * roundAmount; - if (num >= 10) { - return Math.round(niceValue); - } - if (num >= 1) { - return Math.round(niceValue * 10) / 10; - } - - return Math.round(niceValue * 100) / 100; -} - -/** - * Finds a nice integer value - * @see findNiceValue - * @param {number} num - */ -export function findNiceIntegerValue(num) { - return Math.ceil(findNiceValue(num)); -} - -/** - * Smart rounding + fractional handling - * @param {number} n - */ -function roundSmart(n) { - if (n < 100) { - return n.toFixed(1); - } - return Math.round(n); -} - -/** - * Formats a big number - * @param {number} num - * @param {string=} divider THe divider for numbers like 50,000 (divider=',') - * @returns {string} - */ -export function formatBigNumber(num, divider = ".") { - const sign = num < 0 ? "-" : ""; - num = Math.abs(num); - - if (num > 1e54) { - return sign + T.global.infinite; - } - - if (num < 10 && !Number.isInteger(num)) { - return sign + num.toFixed(2); - } - if (num < 50 && !Number.isInteger(num)) { - return sign + num.toFixed(1); - } - num = Math.floor(num); - - if (num < 1000) { - return sign + "" + num; - } else { - let leadingDigits = num; - let suffix = ""; - for (let suffixIndex = 0; suffixIndex < bigNumberSuffixTranslationKeys.length; ++suffixIndex) { - leadingDigits = leadingDigits / 1000; - suffix = T.global.suffix[bigNumberSuffixTranslationKeys[suffixIndex]]; - if (leadingDigits < 1000) { - break; - } - } - const leadingDigitsRounded = round1Digit(leadingDigits); - const leadingDigitsNoTrailingDecimal = leadingDigitsRounded.toString().replace(".0", ""); - return sign + leadingDigitsNoTrailingDecimal + suffix; - } -} - -/** - * Formats a big number, but does not add any suffix and instead uses its full representation - * @param {number} num - * @param {string=} divider THe divider for numbers like 50,000 (divider=',') - * @returns {string} - */ -export function formatBigNumberFull(num, divider = T.global.thousandsDivider) { - if (num < 1000) { - return num + ""; - } - if (num > 1e54) { - return T.global.infinite; - } - let rest = num; - let out = ""; - while (rest >= 1000) { - out = (rest % 1000).toString().padStart(3, "0") + divider + out; - rest = Math.floor(rest / 1000); - } - out = rest + divider + out; - - return out.substring(0, out.length - 1); -} - -/** - * Delayes a promise so that it will resolve after a *minimum* amount of time only - * @param {Promise} promise The promise to delay - * @param {number} minTimeMs The time to make it run at least - * @returns {Promise} The delayed promise - */ -export function artificialDelayedPromise(promise, minTimeMs = 500) { - if (G_IS_DEV && globalConfig.debug.noArtificialDelays) { - return promise; - } - - const startTime = performance.now(); - return promise.then( - result => { - const timeTaken = performance.now() - startTime; - const waitTime = Math.floor(minTimeMs - timeTaken); - if (waitTime > 0) { - return new Promise(resolve => { - setTimeout(() => { - resolve(result); - }, waitTime); - }); - } else { - return result; - } - }, - error => { - const timeTaken = performance.now() - startTime; - const waitTime = Math.floor(minTimeMs - timeTaken); - if (waitTime > 0) { - // @ts-ignore - return new Promise((resolve, reject) => { - setTimeout(() => { - reject(error); - }, waitTime); - }); - } else { - throw error; - } - } - ); -} - -/** - * Computes a sine-based animation which pulsates from 0 .. 1 .. 0 - * @param {number} time Current time in seconds - * @param {number} duration Duration of the full pulse in seconds - * @param {number} seed Seed to offset the animation - */ -export function pulseAnimation(time, duration = 1.0, seed = 0.0) { - return Math.sin((time * Math.PI * 2.0) / duration + seed * 5642.86729349) * 0.5 + 0.5; -} - -/** - * Returns the smallest angle between two angles - * @param {number} a - * @param {number} b - * @returns {number} 0 .. 2 PI - */ -export function smallestAngle(a, b) { - return safeMod(a - b + Math.PI, 2.0 * Math.PI) - Math.PI; -} - -/** - * Modulo which works for negative numbers - * @param {number} n - * @param {number} m - */ -export function safeMod(n, m) { - return ((n % m) + m) % m; -} - -/** - * Wraps an angle between 0 and 2 pi - * @param {number} angle - */ -export function wrapAngle(angle) { - return safeMod(angle, 2.0 * Math.PI); -} - -/** - * Waits two frames so the ui is updated - * @returns {Promise} - */ -export function waitNextFrame() { - return new Promise(function (resolve, reject) { - window.requestAnimationFrame(function () { - window.requestAnimationFrame(function () { - resolve(); - }); - }); - }); -} - -/** - * Rounds 1 digit - * @param {number} n - * @returns {number} - */ -export function round1Digit(n) { - return Math.floor(n * 10.0) / 10.0; -} - -/** - * Rounds 2 digits - * @param {number} n - * @returns {number} - */ -export function round2Digits(n) { - return Math.floor(n * 100.0) / 100.0; -} - -/** - * Rounds 3 digits - * @param {number} n - * @returns {number} - */ -export function round3Digits(n) { - return Math.floor(n * 1000.0) / 1000.0; -} - -/** - * Rounds 4 digits - * @param {number} n - * @returns {number} - */ -export function round4Digits(n) { - return Math.floor(n * 10000.0) / 10000.0; -} - -/** - * Clamps a value between [min, max] - * @param {number} v - * @param {number=} minimum Default 0 - * @param {number=} maximum Default 1 - */ -export function clamp(v, minimum = 0, maximum = 1) { - return Math.max(minimum, Math.min(maximum, v)); -} - -/** - * Measures how long a function took - * @param {string} name - * @param {function():void} target - */ -export function measure(name, target) { - const now = performance.now(); - for (let i = 0; i < 25; ++i) { - target(); - } - const dur = (performance.now() - now) / 25.0; - console.warn("->", name, "took", dur.toFixed(2), "ms"); -} - -/** - * Helper method to create a new div element - * @param {string=} id - * @param {Array=} classes - * @param {string=} innerHTML - */ -export function makeDivElement(id = null, classes = [], innerHTML = "") { - const div = document.createElement("div"); - if (id) { - div.id = id; - } - for (let i = 0; i < classes.length; ++i) { - div.classList.add(classes[i]); - } - div.innerHTML = innerHTML; - return div; -} - -/** - * Helper method to create a new div - * @param {Element} parent - * @param {string=} id - * @param {Array=} classes - * @param {string=} innerHTML - */ -export function makeDiv(parent, id = null, classes = [], innerHTML = "") { - const div = makeDivElement(id, classes, innerHTML); - parent.appendChild(div); - return div; -} - -/** - * Helper method to create a new div and place before reference Node - * @param {Element} parent - * @param {Element} referenceNode - * @param {string=} id - * @param {Array=} classes - * @param {string=} innerHTML - */ -export function makeDivBefore(parent, referenceNode, id = null, classes = [], innerHTML = "") { - const div = makeDivElement(id, classes, innerHTML); - parent.insertBefore(div, referenceNode); - return div; -} - -/** - * Helper method to create a new button element - * @param {Array=} classes - * @param {string=} innerHTML - */ -export function makeButtonElement(classes = [], innerHTML = "") { - const element = document.createElement("button"); - for (let i = 0; i < classes.length; ++i) { - element.classList.add(classes[i]); - } - element.classList.add("styledButton"); - element.innerHTML = innerHTML; - return element; -} - -/** - * Helper method to create a new button - * @param {Element} parent - * @param {Array=} classes - * @param {string=} innerHTML - */ -export function makeButton(parent, classes = [], innerHTML = "") { - const element = makeButtonElement(classes, innerHTML); - parent.appendChild(element); - return element; -} - -/** - * Helper method to create a new button and place before reference Node - * @param {Element} parent - * @param {Element} referenceNode - * @param {Array=} classes - * @param {string=} innerHTML - */ -export function makeButtonBefore(parent, referenceNode, classes = [], innerHTML = "") { - const element = makeButtonElement(classes, innerHTML); - parent.insertBefore(element, referenceNode); - return element; -} - -/** - * Removes all children of the given element - * @param {Element} elem - */ -export function removeAllChildren(elem) { - if (elem) { - var range = document.createRange(); - range.selectNodeContents(elem); - range.deleteContents(); - } -} - -export function smartFadeNumber(current, newOne, minFade = 0.01, maxFade = 0.9) { - const tolerance = Math.min(current, newOne) * 0.5 + 10; - let fade = minFade; - if (Math.abs(current - newOne) < tolerance) { - fade = maxFade; - } - - return current * fade + newOne * (1 - fade); -} - -/** - * Fixes lockstep simulation by converting times like 34.0000000003 to 34.00. - * We use 3 digits of precision, this allows to store sufficient precision of 1 ms without - * the risk to simulation errors due to resync issues - * @param {number} value - */ -export function quantizeFloat(value) { - return Math.round(value * 1000.0) / 1000.0; -} - -/** - * Safe check to check if a timer is expired. quantizes numbers - * @param {number} now Current time - * @param {number} lastTick Last tick of the timer - * @param {number} tickRate Interval of the timer - */ -export function checkTimerExpired(now, lastTick, tickRate) { - if (G_IS_DEV) { - if (quantizeFloat(now) !== now) { - console.error("Got non-quantizied time:" + now + " vs " + quantizeFloat(now)); - now = quantizeFloat(now); - } - if (quantizeFloat(lastTick) !== lastTick) { - // FIXME: REENABLE - // console.error("Got non-quantizied timer:" + lastTick + " vs " + quantizeFloat(lastTick)); - lastTick = quantizeFloat(lastTick); - } - } else { - // just to be safe - now = quantizeFloat(now); - lastTick = quantizeFloat(lastTick); - } - /* - Ok, so heres the issue (Died a bit while debugging it): - - In multiplayer lockstep simulation, client A will simulate everything at T, but client B - will simulate it at T + 3. So we are running into the following precision issue: - Lets say on client A the time is T = 30. Then on clientB the time is T = 33. - Now, our timer takes 0.1 seconds and ticked at 29.90 - What does happen now? - Client A computes the timer and checks T > lastTick + interval. He computes - - 30 >= 29.90 + 0.1 <=> 30 >= 30.0000 <=> True <=> Tick performed - - However, this is what it looks on client B: - - 33 >= 32.90 + 0.1 <=> 33 >= 32.999999999999998 <=> False <=> No tick performed! - - This means that Client B will only tick at the *next* frame, which means it from now is out - of sync by one tick, which means the game will resync further or later and be not able to recover, - since it will run into the same issue over and over. - */ - - // The next tick, in our example it would be 30.0000 / 32.99999999998. In order to fix it, we quantize - // it, so its now 30.0000 / 33.0000 - const nextTick = quantizeFloat(lastTick + tickRate); - - // This check is safe, but its the only check where you may compare times. You always need to use - // this method! - return now >= nextTick; -} - -/** - * Returns if the game supports this browser - */ -export function isSupportedBrowser() { - // please note, - // that IE11 now returns undefined again for window.chrome - // and new Opera 30 outputs true for window.chrome - // but needs to check if window.opr is not undefined - // and new IE Edge outputs to true now for window.chrome - // and if not iOS Chrome check - // so use the below updated condition - - if (G_IS_MOBILE_APP || G_IS_STANDALONE) { - return true; - } - - // @ts-ignore - var isChromium = window.chrome; - var winNav = window.navigator; - var vendorName = winNav.vendor; - // @ts-ignore - var isIEedge = winNav.userAgent.indexOf("Edge") > -1; - var isIOSChrome = winNav.userAgent.match("CriOS"); - - if (isIOSChrome) { - // is Google Chrome on IOS - return false; - } else if ( - isChromium !== null && - typeof isChromium !== "undefined" && - vendorName === "Google Inc." && - isIEedge === false - ) { - // is Google Chrome - return true; - } else { - // not Google Chrome - return false; - } -} - -/** - * Helper function to create a json schema object - * @param {any} properties - */ -export function schemaObject(properties) { - return { - type: "object", - required: Object.keys(properties).slice(), - additionalProperties: false, - properties, - }; -} - -/** - * Quickly - * @param {number} x - * @param {number} y - * @param {number} deg - * @returns {Vector} - */ -export function fastRotateMultipleOf90(x, y, deg) { - switch (deg) { - case 0: { - return new Vector(x, y); - } - case 90: { - return new Vector(x, y); - } - } -} - -/** - * Formats an amount of seconds into something like "5s ago" - * @param {number} secs Seconds - * @returns {string} - */ -export function formatSecondsToTimeAgo(secs) { - const seconds = Math.floor(secs); - const minutes = Math.floor(seconds / 60); - const hours = Math.floor(minutes / 60); - const days = Math.floor(hours / 24); - - if (seconds < 60) { - if (seconds === 1) { - return T.global.time.oneSecondAgo; - } - return T.global.time.xSecondsAgo.replace("", "" + seconds); - } else if (minutes < 60) { - if (minutes === 1) { - return T.global.time.oneMinuteAgo; - } - return T.global.time.xMinutesAgo.replace("", "" + minutes); - } else if (hours < 24) { - if (hours === 1) { - return T.global.time.oneHourAgo; - } - return T.global.time.xHoursAgo.replace("", "" + hours); - } else { - if (days === 1) { - return T.global.time.oneDayAgo; - } - return T.global.time.xDaysAgo.replace("", "" + days); - } -} - -/** - * Formats seconds into a readable string like "5h 23m" - * @param {number} secs Seconds - * @returns {string} - */ -export function formatSeconds(secs) { - const trans = T.global.time; - secs = Math.ceil(secs); - if (secs < 60) { - return trans.secondsShort.replace("", "" + secs); - } else if (secs < 60 * 60) { - const minutes = Math.floor(secs / 60); - const seconds = secs % 60; - return trans.minutesAndSecondsShort - .replace("", "" + seconds) - .replace("", "" + minutes); - } else { - const hours = Math.floor(secs / 3600); - const minutes = Math.floor(secs / 60) % 60; - return trans.hoursAndMinutesShort.replace("", "" + minutes).replace("", "" + hours); - } -} - -/** - * Generates a file download - * @param {string} filename - * @param {string} text - */ -export function generateFileDownload(filename, text) { - var element = document.createElement("a"); - element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text)); - element.setAttribute("download", filename); - - element.style.display = "none"; - document.body.appendChild(element); - - element.click(); - document.body.removeChild(element); -} - -/** - * Capitalizes the first letter - * @param {string} str - */ -export function capitalizeFirstLetter(str) { - return str.substr(0, 1).toUpperCase() + str.substr(1).toLowerCase(); -} - -/** - * Formats a number like 2.5 to "2.5 items / s" - * @param {number} speed - * @param {boolean=} double - */ -export function formatItemsPerSecond(speed, double = false) { - return speed === 1.0 - ? T.ingame.buildingPlacement.infoTexts.oneItemPerSecond - : T.ingame.buildingPlacement.infoTexts.itemsPerSecond.replace("", "" + round2Digits(speed)) + - (double ? " " + T.ingame.buildingPlacement.infoTexts.itemsPerSecondDouble : ""); -} +import { T } from "../translations"; + +const bigNumberSuffixTranslationKeys = ["thousands", "millions", "billions", "trillions"]; + +/** + * Returns if this platform is android + * @returns {boolean} + */ +export function isAndroid() { + if (!G_IS_MOBILE_APP) { + return false; + } + const platform = window.device.platform; + return platform === "Android" || platform === "amazon-fireos"; +} + +/** + * Returns if this platform is iOs + * @returns {boolean} + */ +export function isIos() { + if (!G_IS_MOBILE_APP) { + return false; + } + return window.device.platform === "iOS"; +} + +/** + * Returns a platform name + * @returns {"android" | "browser" | "ios" | "standalone" | "unknown"} + */ +export function getPlatformName() { + if (G_IS_STANDALONE) { + return "standalone"; + } else if (G_IS_BROWSER) { + return "browser"; + } else if (G_IS_MOBILE_APP && isAndroid()) { + return "android"; + } else if (G_IS_MOBILE_APP && isIos()) { + return "ios"; + } + return "unknown"; +} + +/** + * Returns the IPC renderer, or null if not within the standalone + * @returns {object|null} + */ +let ipcRenderer = null; +export function getIPCRenderer() { + if (!G_IS_STANDALONE) { + return null; + } + if (!ipcRenderer) { + ipcRenderer = eval("require")("electron").ipcRenderer; + } + return ipcRenderer; +} + +/** + * Makes a new 2D array with undefined contents + * @param {number} w + * @param {number} h + * @returns {Array>} + */ +export function make2DUndefinedArray(w, h) { + const result = new Array(w); + for (let x = 0; x < w; ++x) { + result[x] = new Array(h); + } + return result; +} + +/** + * Creates a new map (an empty object without any props) + */ +export function newEmptyMap() { + return Object.create(null); +} + +/** + * Returns a random integer in the range [start,end] + * @param {number} start + * @param {number} end + */ +export function randomInt(start, end) { + return start + Math.round(Math.random() * (end - start)); +} + +/** + * Access an object in a very annoying way, used for obsfuscation. + * @param {any} obj + * @param {Array} keys + */ +export function accessNestedPropertyReverse(obj, keys) { + let result = obj; + for (let i = keys.length - 1; i >= 0; --i) { + result = result[keys[i]]; + } + return result; +} + +/** + * Chooses a random entry of an array + * @template T + * @param {T[]} arr + * @returns {T} + */ +export function randomChoice(arr) { + return arr[Math.floor(Math.random() * arr.length)]; +} + +/** + * Deletes from an array by swapping with the last element + * @param {Array} array + * @param {number} index + */ +export function fastArrayDelete(array, index) { + if (index < 0 || index >= array.length) { + throw new Error("Out of bounds"); + } + // When the element is not the last element + if (index !== array.length - 1) { + // Get the last element, and swap it with the one we want to delete + const last = array[array.length - 1]; + array[index] = last; + } + + // Finally remove the last element + array.length -= 1; +} + +/** + * Deletes from an array by swapping with the last element. Searches + * for the value in the array first + * @param {Array} array + * @param {any} value + */ +export function fastArrayDeleteValue(array, value) { + if (array == null) { + throw new Error("Tried to delete from non array!"); + } + const index = array.indexOf(value); + if (index < 0) { + console.error("Value", value, "not contained in array:", array, "!"); + return value; + } + return fastArrayDelete(array, index); +} + +/** + * @see fastArrayDeleteValue + * @param {Array} array + * @param {any} value + */ +export function fastArrayDeleteValueIfContained(array, value) { + if (array == null) { + throw new Error("Tried to delete from non array!"); + } + const index = array.indexOf(value); + if (index < 0) { + return value; + } + return fastArrayDelete(array, index); +} + +/** + * Deletes from an array at the given index + * @param {Array} array + * @param {number} index + */ +export function arrayDelete(array, index) { + if (index < 0 || index >= array.length) { + throw new Error("Out of bounds"); + } + array.splice(index, 1); +} + +/** + * Deletes the given value from an array + * @param {Array} array + * @param {any} value + */ +export function arrayDeleteValue(array, value) { + if (array == null) { + throw new Error("Tried to delete from non array!"); + } + const index = array.indexOf(value); + if (index < 0) { + console.error("Value", value, "not contained in array:", array, "!"); + return value; + } + return arrayDelete(array, index); +} + +/** + * Compare two floats for epsilon equality + * @param {number} a + * @param {number} b + * @returns {boolean} + */ +export function epsilonCompare(a, b, epsilon = 1e-5) { + return Math.abs(a - b) < epsilon; +} + +/** + * Interpolates two numbers + * @param {number} a + * @param {number} b + * @param {number} x Mix factor, 0 means 100% a, 1 means 100%b, rest is interpolated + */ +export function lerp(a, b, x) { + return a * (1 - x) + b * x; +} + +/** + * Finds a value which is nice to display, e.g. 15669 -> 15000. Also handles fractional stuff + * @param {number} num + */ +export function findNiceValue(num) { + if (num > 1e8) { + return num; + } + if (num < 0.00001) { + return 0; + } + + let roundAmount = 1; + if (num > 50000) { + roundAmount = 10000; + } else if (num > 20000) { + roundAmount = 5000; + } else if (num > 5000) { + roundAmount = 1000; + } else if (num > 2000) { + roundAmount = 500; + } else if (num > 1000) { + roundAmount = 100; + } else if (num > 100) { + roundAmount = 20; + } else if (num > 20) { + roundAmount = 5; + } + + const niceValue = Math.floor(num / roundAmount) * roundAmount; + if (num >= 10) { + return Math.round(niceValue); + } + if (num >= 1) { + return Math.round(niceValue * 10) / 10; + } + + return Math.round(niceValue * 100) / 100; +} + +/** + * Finds a nice integer value + * @see findNiceValue + * @param {number} num + */ +export function findNiceIntegerValue(num) { + return Math.ceil(findNiceValue(num)); +} + +/** + * Formats a big number + * @param {number} num + * @param {string=} separator The decimal separator for numbers like 50.1 (separator='.') + * @returns {string} + */ +export function formatBigNumber(num, separator = T.global.decimalSeparator) { + const sign = num < 0 ? "-" : ""; + num = Math.abs(num); + + if (num > 1e54) { + return sign + T.global.infinite; + } + + if (num < 10 && !Number.isInteger(num)) { + return sign + num.toFixed(2); + } + if (num < 50 && !Number.isInteger(num)) { + return sign + num.toFixed(1); + } + num = Math.floor(num); + + if (num < 1000) { + return sign + "" + num; + } else { + let leadingDigits = num; + let suffix = ""; + for (let suffixIndex = 0; suffixIndex < bigNumberSuffixTranslationKeys.length; ++suffixIndex) { + leadingDigits = leadingDigits / 1000; + suffix = T.global.suffix[bigNumberSuffixTranslationKeys[suffixIndex]]; + if (leadingDigits < 1000) { + break; + } + } + const leadingDigitsRounded = round1Digit(leadingDigits); + const leadingDigitsNoTrailingDecimal = leadingDigitsRounded + .toString() + .replace(".0", "") + .replace(".", separator); + return sign + leadingDigitsNoTrailingDecimal + suffix; + } +} + +/** + * Formats a big number, but does not add any suffix and instead uses its full representation + * @param {number} num + * @param {string=} divider The divider for numbers like 50,000 (divider=',') + * @returns {string} + */ +export function formatBigNumberFull(num, divider = T.global.thousandsDivider) { + if (num < 1000) { + return num + ""; + } + if (num > 1e54) { + return T.global.infinite; + } + let rest = num; + let out = ""; + while (rest >= 1000) { + out = (rest % 1000).toString().padStart(3, "0") + divider + out; + rest = Math.floor(rest / 1000); + } + out = rest + divider + out; + + return out.substring(0, out.length - 1); +} + +/** + * Waits two frames so the ui is updated + * @returns {Promise} + */ +export function waitNextFrame() { + return new Promise(function (resolve) { + window.requestAnimationFrame(function () { + window.requestAnimationFrame(function () { + resolve(); + }); + }); + }); +} + +/** + * Rounds 1 digit + * @param {number} n + * @returns {number} + */ +export function round1Digit(n) { + return Math.floor(n * 10.0) / 10.0; +} + +/** + * Rounds 2 digits + * @param {number} n + * @returns {number} + */ +export function round2Digits(n) { + return Math.floor(n * 100.0) / 100.0; +} + +/** + * Rounds 3 digits + * @param {number} n + * @returns {number} + */ +export function round3Digits(n) { + return Math.floor(n * 1000.0) / 1000.0; +} + +/** + * Rounds 4 digits + * @param {number} n + * @returns {number} + */ +export function round4Digits(n) { + return Math.floor(n * 10000.0) / 10000.0; +} + +/** + * Clamps a value between [min, max] + * @param {number} v + * @param {number=} minimum Default 0 + * @param {number=} maximum Default 1 + */ +export function clamp(v, minimum = 0, maximum = 1) { + return Math.max(minimum, Math.min(maximum, v)); +} + +/** + * Helper method to create a new div element + * @param {string=} id + * @param {Array=} classes + * @param {string=} innerHTML + */ +function makeDivElement(id = null, classes = [], innerHTML = "") { + const div = document.createElement("div"); + if (id) { + div.id = id; + } + for (let i = 0; i < classes.length; ++i) { + div.classList.add(classes[i]); + } + div.innerHTML = innerHTML; + return div; +} + +/** + * Helper method to create a new div + * @param {Element} parent + * @param {string=} id + * @param {Array=} classes + * @param {string=} innerHTML + */ +export function makeDiv(parent, id = null, classes = [], innerHTML = "") { + const div = makeDivElement(id, classes, innerHTML); + parent.appendChild(div); + return div; +} + +/** + * Helper method to create a new button element + * @param {Array=} classes + * @param {string=} innerHTML + */ +export function makeButtonElement(classes = [], innerHTML = "") { + const element = document.createElement("button"); + for (let i = 0; i < classes.length; ++i) { + element.classList.add(classes[i]); + } + element.classList.add("styledButton"); + element.innerHTML = innerHTML; + return element; +} + +/** + * Helper method to create a new button + * @param {Element} parent + * @param {Array=} classes + * @param {string=} innerHTML + */ +export function makeButton(parent, classes = [], innerHTML = "") { + const element = makeButtonElement(classes, innerHTML); + parent.appendChild(element); + return element; +} + +/** + * Removes all children of the given element + * @param {Element} elem + */ +export function removeAllChildren(elem) { + if (elem) { + var range = document.createRange(); + range.selectNodeContents(elem); + range.deleteContents(); + } +} + +/** + * Returns if the game supports this browser + */ +export function isSupportedBrowser() { + // please note, + // that IE11 now returns undefined again for window.chrome + // and new Opera 30 outputs true for window.chrome + // but needs to check if window.opr is not undefined + // and new IE Edge outputs to true now for window.chrome + // and if not iOS Chrome check + // so use the below updated condition + + if (G_IS_MOBILE_APP || G_IS_STANDALONE) { + return true; + } + + // @ts-ignore + var isChromium = window.chrome; + var winNav = window.navigator; + var vendorName = winNav.vendor; + // @ts-ignore + var isIEedge = winNav.userAgent.indexOf("Edge") > -1; + var isIOSChrome = winNav.userAgent.match("CriOS"); + + if (isIOSChrome) { + // is Google Chrome on IOS + return false; + } else if ( + isChromium !== null && + typeof isChromium !== "undefined" && + vendorName === "Google Inc." && + isIEedge === false + ) { + // is Google Chrome + return true; + } else { + // not Google Chrome + return false; + } +} + +/** + * Formats an amount of seconds into something like "5s ago" + * @param {number} secs Seconds + * @returns {string} + */ +export function formatSecondsToTimeAgo(secs) { + const seconds = Math.floor(secs); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + + if (seconds < 60) { + if (seconds === 1) { + return T.global.time.oneSecondAgo; + } + return T.global.time.xSecondsAgo.replace("", "" + seconds); + } else if (minutes < 60) { + if (minutes === 1) { + return T.global.time.oneMinuteAgo; + } + return T.global.time.xMinutesAgo.replace("", "" + minutes); + } else if (hours < 24) { + if (hours === 1) { + return T.global.time.oneHourAgo; + } + return T.global.time.xHoursAgo.replace("", "" + hours); + } else { + if (days === 1) { + return T.global.time.oneDayAgo; + } + return T.global.time.xDaysAgo.replace("", "" + days); + } +} + +/** + * Formats seconds into a readable string like "5h 23m" + * @param {number} secs Seconds + * @returns {string} + */ +export function formatSeconds(secs) { + const trans = T.global.time; + secs = Math.ceil(secs); + if (secs < 60) { + return trans.secondsShort.replace("", "" + secs); + } else if (secs < 60 * 60) { + const minutes = Math.floor(secs / 60); + const seconds = secs % 60; + return trans.minutesAndSecondsShort + .replace("", "" + seconds) + .replace("", "" + minutes); + } else { + const hours = Math.floor(secs / 3600); + const minutes = Math.floor(secs / 60) % 60; + return trans.hoursAndMinutesShort.replace("", "" + minutes).replace("", "" + hours); + } +} + +/** + * Formats a number like 2.5 to "2.5 items / s" + * @param {number} speed + * @param {boolean=} double + * @param {string=} separator The decimal separator for numbers like 50.1 (separator='.') + */ +export function formatItemsPerSecond(speed, double = false, separator = T.global.decimalSeparator) { + return speed === 1.0 + ? T.ingame.buildingPlacement.infoTexts.oneItemPerSecond + : T.ingame.buildingPlacement.infoTexts.itemsPerSecond.replace( + "", + round2Digits(speed).toString().replace(".", separator) + ) + (double ? " " + T.ingame.buildingPlacement.infoTexts.itemsPerSecondDouble : ""); +} + +/** + * Rotates a flat 3x3 matrix clockwise + * Entries: + * 0 lo + * 1 mo + * 2 ro + * 3 lm + * 4 mm + * 5 rm + * 6 lu + * 7 mu + * 8 ru + * @param {Array} flatMatrix + */ + +export function rotateFlatMatrix3x3(flatMatrix) { + return [ + flatMatrix[6], + flatMatrix[3], + flatMatrix[0], + flatMatrix[7], + flatMatrix[4], + flatMatrix[1], + flatMatrix[8], + flatMatrix[5], + flatMatrix[2], + ]; +} + +/** + * Generates rotated variants of the matrix + * @param {Array} originalMatrix + * @returns {Object>} + */ +export function generateMatrixRotations(originalMatrix) { + const result = { + 0: originalMatrix, + }; + + originalMatrix = rotateFlatMatrix3x3(originalMatrix); + result[90] = originalMatrix; + + originalMatrix = rotateFlatMatrix3x3(originalMatrix); + result[180] = originalMatrix; + + originalMatrix = rotateFlatMatrix3x3(originalMatrix); + result[270] = originalMatrix; + + return result; +} + +/** + * + * @typedef {{ + * top: any, + * right: any, + * bottom: any, + * left: any + * }} DirectionalObject + */ + +/** + * Rotates a directional object + * @param {DirectionalObject} obj + * @returns {DirectionalObject} + */ +export function rotateDirectionalObject(obj, rotation) { + const queue = [obj.top, obj.right, obj.bottom, obj.left]; + while (rotation !== 0) { + rotation -= 90; + queue.push(queue.shift()); + } + + return { + top: queue[0], + right: queue[1], + bottom: queue[2], + left: queue[3], + }; +} + +/** + * Modulo which works for negative numbers + * @param {number} n + * @param {number} m + */ +export function safeModulo(n, m) { + return ((n % m) + m) % m; +} + +/** + * Returns a smooth pulse between 0 and 1 + * @param {number} time time in seconds + * @returns {number} + */ +export function smoothPulse(time) { + return Math.sin(time * 4) * 0.5 + 0.5; +} diff --git a/src/js/core/vector.js b/src/js/core/vector.js index b0a2d3fa..50fa9433 100644 --- a/src/js/core/vector.js +++ b/src/js/core/vector.js @@ -1,4 +1,5 @@ import { globalConfig } from "./config"; +import { safeModulo } from "./utils"; const tileSize = globalConfig.tileSize; const halfTileSize = globalConfig.halfTileSize; @@ -43,6 +44,14 @@ export const enumAngleToDirection = { 270: enumDirection.left, }; +/** @type {Array} */ +export const arrayAllDirections = [ + enumDirection.top, + enumDirection.right, + enumDirection.bottom, + enumDirection.left, +]; + export class Vector { /** * @@ -279,6 +288,15 @@ export class Vector { return dx * dx + dy * dy; } + /** + * Returns x % f, y % f + * @param {number} f + * @returns {Vector} new vector + */ + modScalar(f) { + return new Vector(safeModulo(this.x, f), safeModulo(this.y, f)); + } + /** * Computes and returns the center between both points * @param {Vector} v diff --git a/src/js/game/automatic_save.js b/src/js/game/automatic_save.js index e32b9b62..9d841966 100644 --- a/src/js/game/automatic_save.js +++ b/src/js/game/automatic_save.js @@ -1,82 +1,79 @@ -import { GameRoot } from "./root"; -import { globalConfig, IS_DEBUG } from "../core/config"; -import { createLogger } from "../core/logging"; - -// How important it is that a savegame is created -/** - * @enum {number} - */ -export const enumSavePriority = { - regular: 2, - asap: 100, -}; - -const logger = createLogger("autosave"); - -// Internals -let MIN_INTERVAL_SECS = 60; - -export class AutomaticSave { - constructor(root) { - /** @type {GameRoot} */ - this.root = root; - - // Store the current maximum save importance - this.saveImportance = enumSavePriority.regular; - - this.lastSaveAttempt = -1000; - } - - setSaveImportance(importance) { - this.saveImportance = Math.max(this.saveImportance, importance); - } - - doSave() { - if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) { - return; - } - - this.root.gameState.doSave(); - this.saveImportance = enumSavePriority.regular; - } - - update() { - if (!this.root.gameInitialized) { - // Bad idea - return; - } - - const saveInterval = this.root.app.settings.getAutosaveIntervalSeconds(); - if (!saveInterval) { - // Disabled - return; - } - - // Check when the last save was, but make sure that if it fails, we don't spam - const lastSaveTime = Math.max(this.lastSaveAttempt, this.root.savegame.getRealLastUpdate()); - - const secondsSinceLastSave = (Date.now() - lastSaveTime) / 1000.0; - let shouldSave = false; - - switch (this.saveImportance) { - case enumSavePriority.asap: - // High always should save - shouldSave = true; - break; - - case enumSavePriority.regular: - // Could determine if there is a good / bad point here - shouldSave = secondsSinceLastSave > saveInterval; - break; - - default: - assert(false, "Unknown save prio: " + this.saveImportance); - break; - } - if (shouldSave) { - logger.log("Saving automatically"); - this.lastSaveAttempt = Date.now(); - this.doSave(); - } - } -} +import { globalConfig } from "../core/config"; +import { createLogger } from "../core/logging"; +import { GameRoot } from "./root"; + +// How important it is that a savegame is created +/** + * @enum {number} + */ +export const enumSavePriority = { + regular: 2, + asap: 100, +}; + +const logger = createLogger("autosave"); + +export class AutomaticSave { + constructor(root) { + /** @type {GameRoot} */ + this.root = root; + + // Store the current maximum save importance + this.saveImportance = enumSavePriority.regular; + + this.lastSaveAttempt = -1000; + } + + setSaveImportance(importance) { + this.saveImportance = Math.max(this.saveImportance, importance); + } + + doSave() { + if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) { + return; + } + + this.root.gameState.doSave(); + this.saveImportance = enumSavePriority.regular; + } + + update() { + if (!this.root.gameInitialized) { + // Bad idea + return; + } + + const saveInterval = this.root.app.settings.getAutosaveIntervalSeconds(); + if (!saveInterval) { + // Disabled + return; + } + + // Check when the last save was, but make sure that if it fails, we don't spam + const lastSaveTime = Math.max(this.lastSaveAttempt, this.root.savegame.getRealLastUpdate()); + + const secondsSinceLastSave = (Date.now() - lastSaveTime) / 1000.0; + let shouldSave = false; + + switch (this.saveImportance) { + case enumSavePriority.asap: + // High always should save + shouldSave = true; + break; + + case enumSavePriority.regular: + // Could determine if there is a good / bad point here + shouldSave = secondsSinceLastSave > saveInterval; + break; + + default: + assert(false, "Unknown save prio: " + this.saveImportance); + break; + } + if (shouldSave) { + logger.log("Saving automatically"); + this.lastSaveAttempt = Date.now(); + this.doSave(); + } + } +} diff --git a/src/js/game/base_item.js b/src/js/game/base_item.js index d0da5fa1..cbd89e7f 100644 --- a/src/js/game/base_item.js +++ b/src/js/game/base_item.js @@ -1,26 +1,9 @@ +import { globalConfig } from "../core/config"; import { DrawParameters } from "../core/draw_parameters"; import { BasicSerializableObject } from "../savegame/serialization"; -import { enumLayer } from "./root"; -/** @enum {string} */ -export const enumItemType = { - shape: "shape", - color: "color", - positiveEnergy: "positiveEnergy", - negativeEnergy: "negativeEnergy", - - // Can be used for filters - genericEnergy: "genericEnergy", -}; - -/** @enum {enumLayer} */ -export const enumItemTypeToLayer = { - [enumItemType.shape]: enumLayer.regular, - [enumItemType.color]: enumLayer.regular, - [enumItemType.positiveEnergy]: enumLayer.wires, - [enumItemType.negativeEnergy]: enumLayer.wires, - [enumItemType.genericEnergy]: enumLayer.wires, -}; +/** @type {ItemType[]} **/ +export const itemTypes = ["shape", "color", "boolean"]; /** * Class for items on belts etc. Not an entity for performance reasons @@ -39,10 +22,33 @@ export class BaseItem extends BasicSerializableObject { return {}; } - /** @returns {enumItemType} */ + /** @returns {ItemType} **/ getItemType() { abstract; - return ""; + return "shape"; + } + + /** + * Returns if the item equals the other itme + * @param {BaseItem} other + * @returns {boolean} + */ + equals(other) { + if (this.getItemType() !== other.getItemType()) { + return false; + } + return this.equalsImpl(other); + } + + /** + * Override for custom comparison + * @abstract + * @param {BaseItem} other + * @returns {boolean} + */ + equalsImpl(other) { + abstract; + return false; } /** @@ -50,9 +56,24 @@ export class BaseItem extends BasicSerializableObject { * @param {number} x * @param {number} y * @param {DrawParameters} parameters - * @param {number=} size + * @param {number=} diameter */ - draw(x, y, parameters, size) {} + drawItemCenteredClipped(x, y, parameters, diameter = globalConfig.defaultItemDiameter) { + if (parameters.visibleRect.containsCircle(x, y, diameter / 2)) { + this.drawItemCenteredImpl(x, y, parameters, diameter); + } + } + + /** + * INTERNAL + * @param {number} x + * @param {number} y + * @param {DrawParameters} parameters + * @param {number=} diameter + */ + drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) { + abstract; + } getBackgroundColorAsResource() { abstract; diff --git a/src/js/game/belt_path.js b/src/js/game/belt_path.js index 0b6da48c..b999e0ee 100644 --- a/src/js/game/belt_path.js +++ b/src/js/game/belt_path.js @@ -1,1166 +1,1241 @@ -import { globalConfig } from "../core/config"; -import { DrawParameters } from "../core/draw_parameters"; -import { createLogger } from "../core/logging"; -import { epsilonCompare, round4Digits } from "../core/utils"; -import { Vector } from "../core/vector"; -import { BaseItem } from "./base_item"; -import { Entity } from "./entity"; -import { GameRoot, enumLayer } from "./root"; -import { Rectangle } from "../core/rectangle"; -import { BasicSerializableObject, types } from "../savegame/serialization"; -import { gItemRegistry } from "../core/global_registries"; - -const logger = createLogger("belt_path"); - -// Helpers for more semantic access into interleaved arrays -const _nextDistance = 0; -const _item = 1; - -const DEBUG = G_IS_DEV && false; - -/** - * Stores a path of belts, used for optimizing performance - */ -export class BeltPath extends BasicSerializableObject { - static getId() { - return "BeltPath"; - } - - static getSchema() { - return { - entityPath: types.array(types.entity), - items: types.array(types.pair(types.ufloat, types.obj(gItemRegistry))), - spacingToFirstItem: types.ufloat, - }; - } - - /** - * Creates a path from a serialized object - * @param {GameRoot} root - * @param {Object} data - * @returns {BeltPath|string} - */ - static fromSerialized(root, data) { - // Create fake object which looks like a belt path but skips the constructor - const fakeObject = /** @type {BeltPath} */ (Object.create(BeltPath.prototype)); - fakeObject.root = root; - - // Deserialize the data - const errorCodeDeserialize = fakeObject.deserialize(data); - if (errorCodeDeserialize) { - return errorCodeDeserialize; - } - - // Compute other properties - fakeObject.init(false); - - return fakeObject; - } - - /** - * @param {GameRoot} root - * @param {Array} entityPath - */ - constructor(root, entityPath) { - super(); - this.root = root; - - assert(entityPath.length > 0, "invalid entity path"); - this.entityPath = entityPath; - - /** - * Stores the items sorted, and their distance to the previous item (or start) - * Layout: [distanceToNext, item] - * @type {Array<[number, BaseItem]>} - */ - this.items = []; - - /** - * Stores the spacing to the first item - */ - - this.init(); - - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_checkIntegrity("constructor"); - } - } - /** - * Initializes the path by computing the properties which are not saved - * @param {boolean} computeSpacing Whether to also compute the spacing - */ - init(computeSpacing = true) { - this.onPathChanged(); - - this.totalLength = this.computeTotalLength(); - - if (computeSpacing) { - this.spacingToFirstItem = this.totalLength; - } - - /** - * Current bounds of this path - * @type {Rectangle} - */ - this.worldBounds = this.computeBounds(); - - // Connect the belts - for (let i = 0; i < this.entityPath.length; ++i) { - this.entityPath[i].components.Belt.assignedPath = this; - } - } - - /** - * Returns whether this path can accept a new item - * @returns {boolean} - */ - canAcceptItem() { - return this.spacingToFirstItem >= this.getItemSpacing(); - } - - /** - * Returns the spacing between items - */ - getItemSpacing() { - return globalConfig.beltItemSpacingByLayer[this.layer]; - } - - /** - * Returns the layer of the this path - * @returns {enumLayer} - */ - getLayer() { - return this.entityPath[0].layer; - } - - /** - * Tries to accept the item - * @param {BaseItem} item - */ - tryAcceptItem(item) { - if (this.spacingToFirstItem >= this.getItemSpacing()) { - // So, since we already need one tick to accept this item we will add this directly. - const beltProgressPerTick = - this.root.hubGoals.getBeltBaseSpeed(this.layer) * - this.root.dynamicTickrate.deltaSeconds * - this.getItemSpacing(); - - // First, compute how much progress we can make *at max* - const maxProgress = Math.max(0, this.spacingToFirstItem - this.getItemSpacing()); - const initialProgress = Math.min(maxProgress, beltProgressPerTick); - - this.items.unshift([this.spacingToFirstItem - initialProgress, item]); - this.spacingToFirstItem = initialProgress; - - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_checkIntegrity("accept-item"); - } - - return true; - } - return false; - } - - /** - * SLOW / Tries to find the item closest to the given tile - * @param {Vector} tile - * @returns {BaseItem|null} - */ - findItemAtTile(tile) { - // TODO: This breaks color blind mode otherwise - return null; - } - - /** - * Computes the tile bounds of the path - * @returns {Rectangle} - */ - computeBounds() { - let bounds = this.entityPath[0].components.StaticMapEntity.getTileSpaceBounds(); - for (let i = 1; i < this.entityPath.length; ++i) { - const staticComp = this.entityPath[i].components.StaticMapEntity; - const otherBounds = staticComp.getTileSpaceBounds(); - bounds = bounds.getUnion(otherBounds); - } - return bounds.allScaled(globalConfig.tileSize); - } - - /** - * Updates all ejectors on the path, so that only the last ejector - */ - onPathChanged() { - this.ejectorComp = this.entityPath[this.entityPath.length - 1].components.ItemEjector; - this.ejectorSlot = this.ejectorComp.slots[0]; - - for (let i = 0; i < this.entityPath.length; ++i) { - const ejectorComp = this.entityPath[i].components.ItemEjector; - const isLast = i === this.entityPath.length - 1; - ejectorComp.enabled = isLast; - - // Clear all slots of non-end entities - if (!isLast) { - for (let k = 0; k < ejectorComp.slots.length; ++k) { - ejectorComp.slots[k].item = null; - ejectorComp.slots[k].progress = 0.0; - } - } - } - - this.layer = this.entityPath[0].layer; - } - - // Following code will be compiled out outside of dev versions - /* dev:start */ - - /** - * Helper to throw an error on mismatch - * @param {string} change - * @param {Array} reason - */ - debug_failIntegrity(change, ...reason) { - throw new Error("belt path invalid (" + change + "): " + reason.map(i => "" + i).join(" ")); - } - - /** - * Checks if this path is valid - */ - debug_checkIntegrity(currentChange = "change") { - const fail = (...args) => this.debug_failIntegrity(currentChange, ...args); - - // Check for empty path - if (this.entityPath.length === 0) { - return fail("Belt path is empty"); - } - - // Check for mismatching length - const totalLength = this.computeTotalLength(); - if (!epsilonCompare(this.totalLength, totalLength, 0.01)) { - return this.debug_failIntegrity( - currentChange, - "Total length mismatch, stored =", - this.totalLength, - "but correct is", - totalLength - ); - } - - // Check for misconnected entities - for (let i = 0; i < this.entityPath.length - 1; ++i) { - const entity = this.entityPath[i]; - if (entity.destroyed) { - return fail("Reference to destroyed entity " + entity.uid); - } - - const enabledState = i === this.entityPath.length - 1; - if (entity.components.ItemEjector.enabled !== enabledState) { - return fail("Item ejector enabled state is not synchronized (index =" + i + ")"); - } - - const followUp = this.root.systemMgr.systems.belt.findFollowUpEntity(entity); - if (!followUp) { - return fail( - "Follow up entity for the", - i, - "-th entity (total length", - this.entityPath.length, - ") was null!" - ); - } - if (followUp !== this.entityPath[i + 1]) { - return fail( - "Follow up entity mismatch, stored is", - this.entityPath[i + 1].uid, - "but real one is", - followUp.uid - ); - } - if (entity.components.Belt.assignedPath !== this) { - return fail( - "Entity with uid", - entity.uid, - "doesn't have this path assigned, but this path contains the entity." - ); - } - } - - // Check for right ejector component and slot - if (this.ejectorComp !== this.entityPath[this.entityPath.length - 1].components.ItemEjector) { - return fail("Stale ejectorComp handle"); - } - if (this.ejectorSlot !== this.ejectorComp.slots[0]) { - return fail("Stale ejector slot handle"); - } - if (!this.ejectorComp) { - return fail("Ejector comp not set"); - } - if (!this.ejectorSlot) { - return fail("Ejector slot not set"); - } - - // Check spacing - if (this.spacingToFirstItem > this.totalLength + 0.005) { - return fail( - currentChange, - "spacing to first item (", - this.spacingToFirstItem, - ") is greater than total length (", - this.totalLength, - ")" - ); - } - - // Check distance if empty - if (this.items.length === 0 && !epsilonCompare(this.spacingToFirstItem, this.totalLength, 0.01)) { - return fail( - currentChange, - "Path is empty but spacing to first item (", - this.spacingToFirstItem, - ") does not equal total length (", - this.totalLength, - ")" - ); - } - - // Check items etc - let currentPos = this.spacingToFirstItem; - for (let i = 0; i < this.items.length; ++i) { - const item = this.items[i]; - - if (item[_nextDistance] < 0 || item[_nextDistance] > this.totalLength + 0.02) { - return fail( - "Item has invalid offset to next item: ", - item[_nextDistance], - "(total length:", - this.totalLength, - ")" - ); - } - - currentPos += item[_nextDistance]; - } - - // Check the total sum matches - if (!epsilonCompare(currentPos, this.totalLength, 0.01)) { - return fail( - "total sum (", - currentPos, - ") of first item spacing (", - this.spacingToFirstItem, - ") and items does not match total length (", - this.totalLength, - ") -> items: " + this.items.map(i => i[_nextDistance]).join("|") - ); - } - - // Check bounds - const actualBounds = this.computeBounds(); - if (!actualBounds.equalsEpsilon(this.worldBounds, 0.01)) { - return fail("Bounds are stale"); - } - } - - /* dev:end */ - - /** - * Extends the belt path by the given belt - * @param {Entity} entity - */ - extendOnEnd(entity) { - DEBUG && logger.log("Extending belt path by entity at", entity.components.StaticMapEntity.origin); - - const beltComp = entity.components.Belt; - - // If the last belt has something on its ejector, put that into the path first - const pendingItem = this.ejectorComp.takeSlotItem(0); - if (pendingItem) { - // Ok, so we have a pending item - DEBUG && logger.log("Taking pending item and putting it back on the path"); - this.items.push([0, pendingItem]); - } - - // Append the entity - this.entityPath.push(entity); - this.onPathChanged(); - - // Extend the path length - const additionalLength = beltComp.getEffectiveLengthTiles(entity.layer); - this.totalLength += additionalLength; - DEBUG && logger.log(" Extended total length by", additionalLength, "to", this.totalLength); - - // If we have no item, just update the distance to the first item - if (this.items.length === 0) { - this.spacingToFirstItem = this.totalLength; - DEBUG && logger.log(" Extended spacing to first to", this.totalLength, "(= total length)"); - } else { - // Otherwise, update the next-distance of the last item - const lastItem = this.items[this.items.length - 1]; - DEBUG && - logger.log( - " Extended spacing of last item from", - lastItem[_nextDistance], - "to", - lastItem[_nextDistance] + additionalLength - ); - lastItem[_nextDistance] += additionalLength; - } - - // Assign reference - beltComp.assignedPath = this; - - // Update bounds - this.worldBounds = this.computeBounds(); - - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_checkIntegrity("extend-on-end"); - } - } - - /** - * Extends the path with the given entity on the beginning - * @param {Entity} entity - */ - extendOnBeginning(entity) { - const beltComp = entity.components.Belt; - - DEBUG && logger.log("Extending the path on the beginning"); - - // All items on that belt are simply lost (for now) - - const length = beltComp.getEffectiveLengthTiles(entity.layer); - - // Extend the length of this path - this.totalLength += length; - - // Simply adjust the first item spacing cuz we have no items contained - this.spacingToFirstItem += length; - - // Set handles and append entity - beltComp.assignedPath = this; - this.entityPath.unshift(entity); - this.onPathChanged(); - - // Update bounds - this.worldBounds = this.computeBounds(); - - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_checkIntegrity("extend-on-begin"); - } - } - - /** - * Returns if the given entity is the end entity of the path - * @param {Entity} entity - * @returns {boolean} - */ - isEndEntity(entity) { - return this.entityPath[this.entityPath.length - 1] === entity; - } - - /** - * Returns if the given entity is the start entity of the path - * @param {Entity} entity - * @returns {boolean} - */ - isStartEntity(entity) { - return this.entityPath[0] === entity; - } - - /** - * Splits this path at the given entity by removing it, and - * returning the new secondary paht - * @param {Entity} entity - * @returns {BeltPath} - */ - deleteEntityOnPathSplitIntoTwo(entity) { - DEBUG && logger.log("Splitting path at entity", entity.components.StaticMapEntity.origin); - - // First, find where the current path ends - const beltComp = entity.components.Belt; - beltComp.assignedPath = null; - - const entityLength = beltComp.getEffectiveLengthTiles(entity.layer); - assert(this.entityPath.indexOf(entity) >= 0, "Entity not contained for split"); - assert(this.entityPath.indexOf(entity) !== 0, "Entity is first"); - assert(this.entityPath.indexOf(entity) !== this.entityPath.length - 1, "Entity is last"); - - let firstPathEntityCount = 0; - let firstPathLength = 0; - let firstPathEndEntity = null; - - for (let i = 0; i < this.entityPath.length; ++i) { - const otherEntity = this.entityPath[i]; - if (otherEntity === entity) { - DEBUG && logger.log("Found entity at", i, "of length", firstPathLength); - break; - } - - ++firstPathEntityCount; - firstPathEndEntity = otherEntity; - firstPathLength += otherEntity.components.Belt.getEffectiveLengthTiles(otherEntity.layer); - } - - DEBUG && - logger.log( - "First path ends at", - firstPathLength, - "and entity", - firstPathEndEntity.components.StaticMapEntity.origin, - "and has", - firstPathEntityCount, - "entities" - ); - - // Compute length of second path - const secondPathLength = this.totalLength - firstPathLength - entityLength; - const secondPathStart = firstPathLength + entityLength; - const secondEntities = this.entityPath.splice(firstPathEntityCount + 1); - DEBUG && - logger.log( - "Second path starts at", - secondPathStart, - "and has a length of ", - secondPathLength, - "with", - secondEntities.length, - "entities" - ); - - // Remove the last item - this.entityPath.pop(); - - DEBUG && logger.log("Splitting", this.items.length, "items"); - DEBUG && - logger.log( - "Old items are", - this.items.map(i => i[_nextDistance]) - ); - - // Create second path - const secondPath = new BeltPath(this.root, secondEntities); - - // Remove all items which are no longer relevant and transfer them to the second path - let itemPos = this.spacingToFirstItem; - for (let i = 0; i < this.items.length; ++i) { - const item = this.items[i]; - const distanceToNext = item[_nextDistance]; - - DEBUG && logger.log(" Checking item at", itemPos, "with distance of", distanceToNext, "to next"); - - // Check if this item is past the first path - if (itemPos >= firstPathLength) { - // Remove it from the first path - this.items.splice(i, 1); - i -= 1; - DEBUG && - logger.log(" Removed item from first path since its no longer contained @", itemPos); - - // Check if its on the second path (otherwise its on the removed belt and simply lost) - if (itemPos >= secondPathStart) { - // Put item on second path - secondPath.items.push([distanceToNext, item[_item]]); - DEBUG && - logger.log( - " Put item to second path @", - itemPos, - "with distance to next =", - distanceToNext - ); - - // If it was the first item, adjust the distance to the first item - if (secondPath.items.length === 1) { - DEBUG && logger.log(" Sinc it was the first, set sapcing of first to", itemPos); - secondPath.spacingToFirstItem = itemPos - secondPathStart; - } - } else { - DEBUG && logger.log(" Item was on the removed belt, so its gone - forever!"); - } - } else { - // Seems this item is on the first path (so all good), so just make sure it doesn't - // have a nextDistance which is bigger than the total path length - const clampedDistanceToNext = Math.min(itemPos + distanceToNext, firstPathLength) - itemPos; - if (clampedDistanceToNext < distanceToNext) { - DEBUG && - logger.log( - "Correcting next distance (first path) from", - distanceToNext, - "to", - clampedDistanceToNext - ); - item[_nextDistance] = clampedDistanceToNext; - } - } - - // Advance items - itemPos += distanceToNext; - } - - DEBUG && - logger.log( - "New items are", - this.items.map(i => i[_nextDistance]) - ); - - DEBUG && - logger.log( - "And second path items are", - secondPath.items.map(i => i[_nextDistance]) - ); - - // Adjust our total length - this.totalLength = firstPathLength; - - // Make sure that if we are empty, we set our first distance properly - if (this.items.length === 0) { - this.spacingToFirstItem = this.totalLength; - } - - this.onPathChanged(); - secondPath.onPathChanged(); - - // Update bounds - this.worldBounds = this.computeBounds(); - - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_checkIntegrity("split-two-first"); - secondPath.debug_checkIntegrity("split-two-second"); - } - - return secondPath; - } - - /** - * Deletes the last entity - * @param {Entity} entity - */ - deleteEntityOnEnd(entity) { - assert( - this.entityPath[this.entityPath.length - 1] === entity, - "Not actually the last entity (instead " + this.entityPath.indexOf(entity) + ")" - ); - - // Ok, first remove the entity - const beltComp = entity.components.Belt; - const beltLength = beltComp.getEffectiveLengthTiles(entity.layer); - - DEBUG && - logger.log( - "Deleting last entity on path with length", - this.entityPath.length, - "(reducing", - this.totalLength, - " by", - beltLength, - ")" - ); - this.totalLength -= beltLength; - this.entityPath.pop(); - this.onPathChanged(); - - DEBUG && - logger.log( - " New path has length of", - this.totalLength, - "with", - this.entityPath.length, - "entities" - ); - - // This is just for sanity - beltComp.assignedPath = null; - - // Clean up items - if (this.items.length === 0) { - // Simple case with no items, just update the first item spacing - this.spacingToFirstItem = this.totalLength; - } else { - // Ok, make sure we simply drop all items which are no longer contained - let itemOffset = this.spacingToFirstItem; - let lastItemOffset = itemOffset; - - DEBUG && logger.log(" Adjusting", this.items.length, "items"); - - for (let i = 0; i < this.items.length; ++i) { - const item = this.items[i]; - - // Get rid of items past this path - if (itemOffset >= this.totalLength) { - DEBUG && logger.log("Dropping item (current index=", i, ")"); - this.items.splice(i, 1); - i -= 1; - continue; - } - - DEBUG && logger.log("Item", i, "is at", itemOffset, "with next offset", item[_nextDistance]); - lastItemOffset = itemOffset; - itemOffset += item[_nextDistance]; - } - - // If we still have an item, make sure the last item matches - if (this.items.length > 0) { - // We can easily compute the next distance since we know where the last item is now - const lastDistance = this.totalLength - lastItemOffset; - assert( - lastDistance >= 0.0, - "Last item distance mismatch: " + - lastDistance + - " -> Total length was " + - this.totalLength + - " and lastItemOffset was " + - lastItemOffset - ); - - DEBUG && - logger.log( - "Adjusted distance of last item: it is at", - lastItemOffset, - "so it has a distance of", - lastDistance, - "to the end (", - this.totalLength, - ")" - ); - this.items[this.items.length - 1][_nextDistance] = lastDistance; - } else { - DEBUG && logger.log(" Removed all items so we'll update spacing to total length"); - - // We removed all items so update our spacing - this.spacingToFirstItem = this.totalLength; - } - } - - // Update bounds - this.worldBounds = this.computeBounds(); - - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_checkIntegrity("delete-on-end"); - } - } - - /** - * Deletes the entity of the start of the path - * @see deleteEntityOnEnd - * @param {Entity} entity - */ - deleteEntityOnStart(entity) { - assert( - entity === this.entityPath[0], - "Not actually the start entity (instead " + this.entityPath.indexOf(entity) + ")" - ); - - // Ok, first remove the entity - const beltComp = entity.components.Belt; - const beltLength = beltComp.getEffectiveLengthTiles(entity.layer); - - DEBUG && - logger.log( - "Deleting first entity on path with length", - this.entityPath.length, - "(reducing", - this.totalLength, - " by", - beltLength, - ")" - ); - this.totalLength -= beltLength; - this.entityPath.shift(); - this.onPathChanged(); - - DEBUG && - logger.log( - " New path has length of", - this.totalLength, - "with", - this.entityPath.length, - "entities" - ); - - // This is just for sanity - beltComp.assignedPath = null; - - // Clean up items - if (this.items.length === 0) { - // Simple case with no items, just update the first item spacing - this.spacingToFirstItem = this.totalLength; - } else { - // Simple case, we had no item on the beginning -> all good - if (this.spacingToFirstItem >= beltLength) { - DEBUG && - logger.log( - " No item on the first place, so we can just adjust the spacing (spacing=", - this.spacingToFirstItem, - ") removed =", - beltLength - ); - this.spacingToFirstItem -= beltLength; - } else { - // Welp, okay we need to drop all items which are < beltLength and adjust - // the other item offsets as well - - DEBUG && - logger.log( - " We have at least one item in the beginning, drop those and adjust spacing (first item @", - this.spacingToFirstItem, - ") since we removed", - beltLength, - "length from path" - ); - DEBUG && - logger.log( - " Items:", - this.items.map(i => i[_nextDistance]) - ); - - // Find offset to first item - let itemOffset = this.spacingToFirstItem; - for (let i = 0; i < this.items.length; ++i) { - const item = this.items[i]; - if (itemOffset <= beltLength) { - DEBUG && - logger.log( - " -> Dropping item with index", - i, - "at", - itemOffset, - "since it was on the removed belt" - ); - // This item must be dropped - this.items.splice(i, 1); - i -= 1; - itemOffset += item[_nextDistance]; - continue; - } else { - // This item can be kept, thus its the first we know - break; - } - } - - if (this.items.length > 0) { - DEBUG && - logger.log( - " Offset of first non-dropped item was at:", - itemOffset, - "-> setting spacing to it (total length=", - this.totalLength, - ")" - ); - - this.spacingToFirstItem = itemOffset - beltLength; - assert( - this.spacingToFirstItem >= 0.0, - "Invalid spacing after delete on start: " + this.spacingToFirstItem - ); - } else { - DEBUG && logger.log(" We dropped all items, simply set spacing to total length"); - // We dropped all items, simple one - this.spacingToFirstItem = this.totalLength; - } - } - } - - // Update bounds - this.worldBounds = this.computeBounds(); - - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_checkIntegrity("delete-on-start"); - } - } - - /** - * Extends the path by the given other path - * @param {BeltPath} otherPath - */ - extendByPath(otherPath) { - assert(otherPath !== this, "Circular path dependency"); - - const entities = otherPath.entityPath; - DEBUG && logger.log("Extending path by other path, starting to add entities"); - - const oldLength = this.totalLength; - - DEBUG && logger.log(" Adding", entities.length, "new entities, current length =", this.totalLength); - - // First, append entities - for (let i = 0; i < entities.length; ++i) { - const entity = entities[i]; - const beltComp = entity.components.Belt; - - // Add to path and update references - this.entityPath.push(entity); - beltComp.assignedPath = this; - - // Update our length - const additionalLength = beltComp.getEffectiveLengthTiles(entity.layer); - this.totalLength += additionalLength; - } - - DEBUG && - logger.log( - " Path is now", - this.entityPath.length, - "entities and has a length of", - this.totalLength - ); - - // Now, update the distance of our last item - if (this.items.length !== 0) { - const lastItem = this.items[this.items.length - 1]; - lastItem[_nextDistance] += otherPath.spacingToFirstItem; - DEBUG && - logger.log(" Add distance to last item, effectively being", lastItem[_nextDistance], "now"); - } else { - // Seems we have no items, update our first item distance - this.spacingToFirstItem = oldLength + otherPath.spacingToFirstItem; - DEBUG && - logger.log( - " We had no items, so our new spacing to first is old length (", - oldLength, - ") plus others spacing to first (", - otherPath.spacingToFirstItem, - ") =", - this.spacingToFirstItem - ); - } - - DEBUG && logger.log(" Pushing", otherPath.items.length, "items from other path"); - - // Aaand push the other paths items - for (let i = 0; i < otherPath.items.length; ++i) { - const item = otherPath.items[i]; - this.items.push([item[_nextDistance], item[_item]]); - } - - // Update bounds - this.worldBounds = this.computeBounds(); - - this.onPathChanged(); - - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_checkIntegrity("extend-by-path"); - } - } - - /** - * Computes the total length of the path - * @returns {number} - */ - computeTotalLength() { - let length = 0; - for (let i = 0; i < this.entityPath.length; ++i) { - const entity = this.entityPath[i]; - length += entity.components.Belt.getEffectiveLengthTiles(this.layer); - } - return length; - } - - /** - * Performs one tick - */ - update() { - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_checkIntegrity("pre-update"); - } - - // Divide by item spacing on belts since we use throughput and not speed - let beltSpeed = - this.root.hubGoals.getBeltBaseSpeed(this.layer) * - this.root.dynamicTickrate.deltaSeconds * - this.getItemSpacing(); - - if (G_IS_DEV && globalConfig.debug.instantBelts) { - beltSpeed *= 100; - } - - let minimumDistance = this.ejectorSlot.item ? this.getItemSpacing() : 0; - - // Try to reduce spacing - let remainingAmount = beltSpeed; - for (let i = this.items.length - 1; i >= 0; --i) { - const nextDistanceAndItem = this.items[i]; - const minimumSpacing = minimumDistance; - - const takeAway = Math.max( - 0, - Math.min(remainingAmount, nextDistanceAndItem[_nextDistance] - minimumSpacing) - ); - - remainingAmount -= takeAway; - nextDistanceAndItem[_nextDistance] -= takeAway; - - this.spacingToFirstItem += takeAway; - if (remainingAmount < 0.01) { - break; - } - - minimumDistance = this.getItemSpacing(); - } - - const lastItem = this.items[this.items.length - 1]; - if (lastItem && lastItem[_nextDistance] === 0) { - // Take over - if (this.ejectorComp.tryEject(0, lastItem[_item])) { - this.items.pop(); - } - } - - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_checkIntegrity("post-update"); - } - } - - /** - * Computes a world space position from the given progress - * @param {number} progress - * @returns {Vector} - */ - computePositionFromProgress(progress) { - let currentLength = 0; - - // floating point issuses .. - assert(progress <= this.totalLength + 0.02, "Progress too big: " + progress); - - for (let i = 0; i < this.entityPath.length; ++i) { - const beltComp = this.entityPath[i].components.Belt; - const localLength = beltComp.getEffectiveLengthTiles(this.layer); - - if (currentLength + localLength >= progress || i === this.entityPath.length - 1) { - // Min required here due to floating point issues - const localProgress = Math.min(1.0, progress - currentLength); - - assert(localProgress >= 0.0, "Invalid local progress: " + localProgress); - const localSpace = beltComp.transformBeltToLocalSpace(localProgress, this.layer); - return this.entityPath[i].components.StaticMapEntity.localTileToWorld(localSpace); - } - currentLength += localLength; - } - - assert(false, "invalid progress: " + progress + " (max: " + this.totalLength + ")"); - } - - /** - * - * @param {DrawParameters} parameters - */ - drawDebug(parameters) { - if (!parameters.visibleRect.containsRect(this.worldBounds)) { - return; - } - - if (this.entityPath[0].layer !== this.root.currentLayer) { - // Don't draw - return; - } - - parameters.context.fillStyle = "#d79a25"; - parameters.context.strokeStyle = "#d79a25"; - parameters.context.beginPath(); - - for (let i = 0; i < this.entityPath.length; ++i) { - const entity = this.entityPath[i]; - const pos = entity.components.StaticMapEntity; - const worldPos = pos.origin.toWorldSpaceCenterOfTile(); - - if (i === 0) { - parameters.context.moveTo(worldPos.x, worldPos.y); - } else { - parameters.context.lineTo(worldPos.x, worldPos.y); - } - } - parameters.context.stroke(); - - // Items - let progress = this.spacingToFirstItem; - for (let i = 0; i < this.items.length; ++i) { - const nextDistanceAndItem = this.items[i]; - const worldPos = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile(); - parameters.context.fillStyle = "#268e4d"; - parameters.context.beginRoundedRect(worldPos.x - 5, worldPos.y - 5, 10, 10, 3); - parameters.context.fill(); - parameters.context.font = "6px GameFont"; - parameters.context.fillStyle = "#111"; - parameters.context.fillText( - "" + round4Digits(nextDistanceAndItem[_nextDistance]), - worldPos.x + 5, - worldPos.y + 2 - ); - progress += nextDistanceAndItem[_nextDistance]; - } - - for (let i = 0; i < this.entityPath.length; ++i) { - const entity = this.entityPath[i]; - parameters.context.fillStyle = "#d79a25"; - const pos = entity.components.StaticMapEntity; - const worldPos = pos.origin.toWorldSpaceCenterOfTile(); - parameters.context.beginCircle(worldPos.x, worldPos.y, i === 0 ? 5 : 3); - parameters.context.fill(); - } - - for (let progress = 0; progress <= this.totalLength + 0.01; progress += 0.2) { - const worldPos = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile(); - parameters.context.fillStyle = "red"; - parameters.context.beginCircle(worldPos.x, worldPos.y, 1); - parameters.context.fill(); - } - - const firstItemIndicator = this.computePositionFromProgress( - this.spacingToFirstItem - ).toWorldSpaceCenterOfTile(); - parameters.context.fillStyle = "purple"; - parameters.context.fillRect(firstItemIndicator.x - 3, firstItemIndicator.y - 1, 6, 2); - } - - /** - * Draws the path - * @param {DrawParameters} parameters - */ - draw(parameters) { - if (!parameters.visibleRect.containsRect(this.worldBounds)) { - return; - } - - if (this.items.length === 0) { - // Early out - return; - } - - let currentItemPos = this.spacingToFirstItem; - let currentItemIndex = 0; - - let trackPos = 0.0; - - // Iterate whole track and check items - for (let i = 0; i < this.entityPath.length; ++i) { - const entity = this.entityPath[i]; - const beltComp = entity.components.Belt; - const beltLength = beltComp.getEffectiveLengthTiles(this.layer); - - // Check if the current items are on the belt - while (trackPos + beltLength >= currentItemPos) { - // Its on the belt, render it now - const staticComp = entity.components.StaticMapEntity; - assert( - currentItemPos - trackPos >= 0, - "invalid track pos: " + currentItemPos + " vs " + trackPos + " (l =" + beltLength + ")" - ); - - const localPos = beltComp.transformBeltToLocalSpace(currentItemPos - trackPos, this.layer); - const worldPos = staticComp.localTileToWorld(localPos).toWorldSpaceCenterOfTile(); - - const distanceAndItem = this.items[currentItemIndex]; - if (parameters.visibleRect.containsCircle(worldPos.x, worldPos.y, 10)) { - distanceAndItem[_item].draw(worldPos.x, worldPos.y, parameters); - } - - // Check for the next item - currentItemPos += distanceAndItem[_nextDistance]; - ++currentItemIndex; - - if (currentItemIndex >= this.items.length) { - // We rendered all items - return; - } - } - - trackPos += beltLength; - } - } -} +import { globalConfig } from "../core/config"; +import { DrawParameters } from "../core/draw_parameters"; +import { createLogger } from "../core/logging"; +import { Rectangle } from "../core/rectangle"; +import { epsilonCompare, round4Digits, clamp } from "../core/utils"; +import { enumDirection, enumDirectionToVector, enumInvertedDirections, Vector } from "../core/vector"; +import { BasicSerializableObject, types } from "../savegame/serialization"; +import { BaseItem } from "./base_item"; +import { Entity } from "./entity"; +import { typeItemSingleton } from "./item_resolver"; +import { GameRoot } from "./root"; + +const logger = createLogger("belt_path"); + +// Helpers for more semantic access into interleaved arrays +const _nextDistance = 0; +const _item = 1; + +const DEBUG = G_IS_DEV && false; + +/** + * Stores a path of belts, used for optimizing performance + */ +export class BeltPath extends BasicSerializableObject { + static getId() { + return "BeltPath"; + } + + static getSchema() { + return { + entityPath: types.array(types.entity), + items: types.array(types.pair(types.ufloat, typeItemSingleton)), + spacingToFirstItem: types.ufloat, + }; + } + + /** + * Creates a path from a serialized object + * @param {GameRoot} root + * @param {Object} data + * @returns {BeltPath|string} + */ + static fromSerialized(root, data) { + // Create fake object which looks like a belt path but skips the constructor + const fakeObject = /** @type {BeltPath} */ (Object.create(BeltPath.prototype)); + fakeObject.root = root; + + // Deserialize the data + const errorCodeDeserialize = fakeObject.deserialize(data); + if (errorCodeDeserialize) { + return errorCodeDeserialize; + } + + // Compute other properties + fakeObject.init(false); + + return fakeObject; + } + + /** + * @param {GameRoot} root + * @param {Array} entityPath + */ + constructor(root, entityPath) { + super(); + this.root = root; + + assert(entityPath.length > 0, "invalid entity path"); + this.entityPath = entityPath; + + /** + * Stores the items sorted, and their distance to the previous item (or start) + * Layout: [distanceToNext, item] + * @type {Array<[number, BaseItem]>} + */ + this.items = []; + + /** + * Stores the spacing to the first item + */ + + this.init(); + + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_checkIntegrity("constructor"); + } + } + /** + * Initializes the path by computing the properties which are not saved + * @param {boolean} computeSpacing Whether to also compute the spacing + */ + init(computeSpacing = true) { + this.onPathChanged(); + + this.totalLength = this.computeTotalLength(); + + if (computeSpacing) { + this.spacingToFirstItem = this.totalLength; + } + + /** + * Current bounds of this path + * @type {Rectangle} + */ + this.worldBounds = this.computeBounds(); + + // Connect the belts + for (let i = 0; i < this.entityPath.length; ++i) { + this.entityPath[i].components.Belt.assignedPath = this; + } + } + + /** + * Returns whether this path can accept a new item + * @returns {boolean} + */ + canAcceptItem() { + return this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts; + } + + /** + * Tries to accept the item + * @param {BaseItem} item + */ + tryAcceptItem(item) { + if (this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts) { + // So, since we already need one tick to accept this item we will add this directly. + const beltProgressPerTick = + this.root.hubGoals.getBeltBaseSpeed() * + this.root.dynamicTickrate.deltaSeconds * + globalConfig.itemSpacingOnBelts; + + // First, compute how much progress we can make *at max* + const maxProgress = Math.max(0, this.spacingToFirstItem - globalConfig.itemSpacingOnBelts); + const initialProgress = Math.min(maxProgress, beltProgressPerTick); + + this.items.unshift([this.spacingToFirstItem - initialProgress, item]); + this.spacingToFirstItem = initialProgress; + + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_checkIntegrity("accept-item"); + } + + return true; + } + return false; + } + + /** + * SLOW / Tries to find the item closest to the given tile + * @param {Vector} tile + * @returns {BaseItem|null} + */ + findItemAtTile(tile) { + // @TODO: This breaks color blind mode otherwise + return null; + } + + /** + * Computes the tile bounds of the path + * @returns {Rectangle} + */ + computeBounds() { + let bounds = this.entityPath[0].components.StaticMapEntity.getTileSpaceBounds(); + for (let i = 1; i < this.entityPath.length; ++i) { + const staticComp = this.entityPath[i].components.StaticMapEntity; + const otherBounds = staticComp.getTileSpaceBounds(); + bounds = bounds.getUnion(otherBounds); + } + return bounds.allScaled(globalConfig.tileSize); + } + + /** + * Recomputes cache variables once the path was changed + */ + onPathChanged() { + this.acceptorTarget = this.computeAcceptingEntityAndSlot(); + } + + /** + * Called by the belt system when the surroundings changed + */ + onSurroundingsChanged() { + this.onPathChanged(); + } + + /** + * Finds the entity which accepts our items + * @return {{ entity: Entity, slot: number, direction?: enumDirection }} + */ + computeAcceptingEntityAndSlot() { + const lastEntity = this.entityPath[this.entityPath.length - 1]; + const lastStatic = lastEntity.components.StaticMapEntity; + const lastBeltComp = lastEntity.components.Belt; + + // Figure out where and into which direction we eject items + const ejectSlotWsTile = lastStatic.localTileToWorld(new Vector(0, 0)); + const ejectSlotWsDirection = lastStatic.localDirectionToWorld(lastBeltComp.direction); + const ejectSlotWsDirectionVector = enumDirectionToVector[ejectSlotWsDirection]; + const ejectSlotTargetWsTile = ejectSlotWsTile.add(ejectSlotWsDirectionVector); + + // Try to find the given acceptor component to take the item + const targetEntity = this.root.map.getLayerContentXY( + ejectSlotTargetWsTile.x, + ejectSlotTargetWsTile.y, + "regular" + ); + + if (targetEntity) { + const targetStaticComp = targetEntity.components.StaticMapEntity; + const targetBeltComp = targetEntity.components.Belt; + + // Check for belts (special case) + if (targetBeltComp) { + const beltAcceptingDirection = targetStaticComp.localDirectionToWorld(enumDirection.top); + if (ejectSlotWsDirection === beltAcceptingDirection) { + return { + entity: targetEntity, + direction: null, + slot: 0, + }; + } + } + + // Check for item acceptors + const targetAcceptorComp = targetEntity.components.ItemAcceptor; + if (!targetAcceptorComp) { + // Entity doesn't accept items + return; + } + + const ejectingDirection = targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection); + const matchingSlot = targetAcceptorComp.findMatchingSlot( + targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile), + ejectingDirection + ); + + if (!matchingSlot) { + // No matching slot found + return; + } + + return { + entity: targetEntity, + slot: matchingSlot.index, + direction: enumInvertedDirections[ejectingDirection], + }; + } + } + + // Following code will be compiled out outside of dev versions + /* dev:start */ + + /** + * Helper to throw an error on mismatch + * @param {string} change + * @param {Array} reason + */ + debug_failIntegrity(change, ...reason) { + throw new Error("belt path invalid (" + change + "): " + reason.map(i => "" + i).join(" ")); + } + + /** + * Checks if this path is valid + */ + debug_checkIntegrity(currentChange = "change") { + const fail = (...args) => this.debug_failIntegrity(currentChange, ...args); + + // Check for empty path + if (this.entityPath.length === 0) { + return fail("Belt path is empty"); + } + + // Check for mismatching length + const totalLength = this.computeTotalLength(); + if (!epsilonCompare(this.totalLength, totalLength, 0.01)) { + return this.debug_failIntegrity( + currentChange, + "Total length mismatch, stored =", + this.totalLength, + "but correct is", + totalLength + ); + } + + // Check for misconnected entities + for (let i = 0; i < this.entityPath.length - 1; ++i) { + const entity = this.entityPath[i]; + if (entity.destroyed) { + return fail("Reference to destroyed entity " + entity.uid); + } + + const followUp = this.root.systemMgr.systems.belt.findFollowUpEntity(entity); + if (!followUp) { + return fail( + "Follow up entity for the", + i, + "-th entity (total length", + this.entityPath.length, + ") was null!" + ); + } + if (followUp !== this.entityPath[i + 1]) { + return fail( + "Follow up entity mismatch, stored is", + this.entityPath[i + 1].uid, + "but real one is", + followUp.uid + ); + } + if (entity.components.Belt.assignedPath !== this) { + return fail( + "Entity with uid", + entity.uid, + "doesn't have this path assigned, but this path contains the entity." + ); + } + } + + // Check spacing + if (this.spacingToFirstItem > this.totalLength + 0.005) { + return fail( + currentChange, + "spacing to first item (", + this.spacingToFirstItem, + ") is greater than total length (", + this.totalLength, + ")" + ); + } + + // Check distance if empty + if (this.items.length === 0 && !epsilonCompare(this.spacingToFirstItem, this.totalLength, 0.01)) { + return fail( + currentChange, + "Path is empty but spacing to first item (", + this.spacingToFirstItem, + ") does not equal total length (", + this.totalLength, + ")" + ); + } + + // Check items etc + let currentPos = this.spacingToFirstItem; + for (let i = 0; i < this.items.length; ++i) { + const item = this.items[i]; + + if (item[_nextDistance] < 0 || item[_nextDistance] > this.totalLength + 0.02) { + return fail( + "Item has invalid offset to next item: ", + item[_nextDistance], + "(total length:", + this.totalLength, + ")" + ); + } + + currentPos += item[_nextDistance]; + } + + // Check the total sum matches + if (!epsilonCompare(currentPos, this.totalLength, 0.01)) { + return fail( + "total sum (", + currentPos, + ") of first item spacing (", + this.spacingToFirstItem, + ") and items does not match total length (", + this.totalLength, + ") -> items: " + this.items.map(i => i[_nextDistance]).join("|") + ); + } + + // Check bounds + const actualBounds = this.computeBounds(); + if (!actualBounds.equalsEpsilon(this.worldBounds, 0.01)) { + return fail("Bounds are stale"); + } + } + + /* dev:end */ + + /** + * Extends the belt path by the given belt + * @param {Entity} entity + */ + extendOnEnd(entity) { + DEBUG && logger.log("Extending belt path by entity at", entity.components.StaticMapEntity.origin); + + const beltComp = entity.components.Belt; + + // Append the entity + this.entityPath.push(entity); + this.onPathChanged(); + + // Extend the path length + const additionalLength = beltComp.getEffectiveLengthTiles(); + this.totalLength += additionalLength; + DEBUG && logger.log(" Extended total length by", additionalLength, "to", this.totalLength); + + // If we have no item, just update the distance to the first item + if (this.items.length === 0) { + this.spacingToFirstItem = this.totalLength; + DEBUG && logger.log(" Extended spacing to first to", this.totalLength, "(= total length)"); + } else { + // Otherwise, update the next-distance of the last item + const lastItem = this.items[this.items.length - 1]; + DEBUG && + logger.log( + " Extended spacing of last item from", + lastItem[_nextDistance], + "to", + lastItem[_nextDistance] + additionalLength + ); + lastItem[_nextDistance] += additionalLength; + } + + // Assign reference + beltComp.assignedPath = this; + + // Update bounds + this.worldBounds = this.computeBounds(); + + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_checkIntegrity("extend-on-end"); + } + } + + /** + * Extends the path with the given entity on the beginning + * @param {Entity} entity + */ + extendOnBeginning(entity) { + const beltComp = entity.components.Belt; + + DEBUG && logger.log("Extending the path on the beginning"); + + // All items on that belt are simply lost (for now) + + const length = beltComp.getEffectiveLengthTiles(); + + // Extend the length of this path + this.totalLength += length; + + // Simply adjust the first item spacing cuz we have no items contained + this.spacingToFirstItem += length; + + // Set handles and append entity + beltComp.assignedPath = this; + this.entityPath.unshift(entity); + this.onPathChanged(); + + // Update bounds + this.worldBounds = this.computeBounds(); + + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_checkIntegrity("extend-on-begin"); + } + } + + /** + * Returns if the given entity is the end entity of the path + * @param {Entity} entity + * @returns {boolean} + */ + isEndEntity(entity) { + return this.entityPath[this.entityPath.length - 1] === entity; + } + + /** + * Returns if the given entity is the start entity of the path + * @param {Entity} entity + * @returns {boolean} + */ + isStartEntity(entity) { + return this.entityPath[0] === entity; + } + + /** + * Splits this path at the given entity by removing it, and + * returning the new secondary paht + * @param {Entity} entity + * @returns {BeltPath} + */ + deleteEntityOnPathSplitIntoTwo(entity) { + DEBUG && logger.log("Splitting path at entity", entity.components.StaticMapEntity.origin); + + // First, find where the current path ends + const beltComp = entity.components.Belt; + beltComp.assignedPath = null; + + const entityLength = beltComp.getEffectiveLengthTiles(); + assert(this.entityPath.indexOf(entity) >= 0, "Entity not contained for split"); + assert(this.entityPath.indexOf(entity) !== 0, "Entity is first"); + assert(this.entityPath.indexOf(entity) !== this.entityPath.length - 1, "Entity is last"); + + let firstPathEntityCount = 0; + let firstPathLength = 0; + let firstPathEndEntity = null; + + for (let i = 0; i < this.entityPath.length; ++i) { + const otherEntity = this.entityPath[i]; + if (otherEntity === entity) { + DEBUG && logger.log("Found entity at", i, "of length", firstPathLength); + break; + } + + ++firstPathEntityCount; + firstPathEndEntity = otherEntity; + firstPathLength += otherEntity.components.Belt.getEffectiveLengthTiles(); + } + + DEBUG && + logger.log( + "First path ends at", + firstPathLength, + "and entity", + firstPathEndEntity.components.StaticMapEntity.origin, + "and has", + firstPathEntityCount, + "entities" + ); + + // Compute length of second path + const secondPathLength = this.totalLength - firstPathLength - entityLength; + const secondPathStart = firstPathLength + entityLength; + const secondEntities = this.entityPath.splice(firstPathEntityCount + 1); + DEBUG && + logger.log( + "Second path starts at", + secondPathStart, + "and has a length of ", + secondPathLength, + "with", + secondEntities.length, + "entities" + ); + + // Remove the last item + this.entityPath.pop(); + + DEBUG && logger.log("Splitting", this.items.length, "items"); + DEBUG && + logger.log( + "Old items are", + this.items.map(i => i[_nextDistance]) + ); + + // Create second path + const secondPath = new BeltPath(this.root, secondEntities); + + // Remove all items which are no longer relevant and transfer them to the second path + let itemPos = this.spacingToFirstItem; + for (let i = 0; i < this.items.length; ++i) { + const item = this.items[i]; + const distanceToNext = item[_nextDistance]; + + DEBUG && logger.log(" Checking item at", itemPos, "with distance of", distanceToNext, "to next"); + + // Check if this item is past the first path + if (itemPos >= firstPathLength) { + // Remove it from the first path + this.items.splice(i, 1); + i -= 1; + DEBUG && + logger.log(" Removed item from first path since its no longer contained @", itemPos); + + // Check if its on the second path (otherwise its on the removed belt and simply lost) + if (itemPos >= secondPathStart) { + // Put item on second path + secondPath.items.push([distanceToNext, item[_item]]); + DEBUG && + logger.log( + " Put item to second path @", + itemPos, + "with distance to next =", + distanceToNext + ); + + // If it was the first item, adjust the distance to the first item + if (secondPath.items.length === 1) { + DEBUG && logger.log(" Sinc it was the first, set sapcing of first to", itemPos); + secondPath.spacingToFirstItem = itemPos - secondPathStart; + } + } else { + DEBUG && logger.log(" Item was on the removed belt, so its gone - forever!"); + } + } else { + // Seems this item is on the first path (so all good), so just make sure it doesn't + // have a nextDistance which is bigger than the total path length + const clampedDistanceToNext = Math.min(itemPos + distanceToNext, firstPathLength) - itemPos; + if (clampedDistanceToNext < distanceToNext) { + DEBUG && + logger.log( + "Correcting next distance (first path) from", + distanceToNext, + "to", + clampedDistanceToNext + ); + item[_nextDistance] = clampedDistanceToNext; + } + } + + // Advance items + itemPos += distanceToNext; + } + + DEBUG && + logger.log( + "New items are", + this.items.map(i => i[_nextDistance]) + ); + + DEBUG && + logger.log( + "And second path items are", + secondPath.items.map(i => i[_nextDistance]) + ); + + // Adjust our total length + this.totalLength = firstPathLength; + + // Make sure that if we are empty, we set our first distance properly + if (this.items.length === 0) { + this.spacingToFirstItem = this.totalLength; + } + + this.onPathChanged(); + secondPath.onPathChanged(); + + // Update bounds + this.worldBounds = this.computeBounds(); + + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_checkIntegrity("split-two-first"); + secondPath.debug_checkIntegrity("split-two-second"); + } + + return secondPath; + } + + /** + * Deletes the last entity + * @param {Entity} entity + */ + deleteEntityOnEnd(entity) { + assert( + this.entityPath[this.entityPath.length - 1] === entity, + "Not actually the last entity (instead " + this.entityPath.indexOf(entity) + ")" + ); + + // Ok, first remove the entity + const beltComp = entity.components.Belt; + const beltLength = beltComp.getEffectiveLengthTiles(); + + DEBUG && + logger.log( + "Deleting last entity on path with length", + this.entityPath.length, + "(reducing", + this.totalLength, + " by", + beltLength, + ")" + ); + this.totalLength -= beltLength; + this.entityPath.pop(); + this.onPathChanged(); + + DEBUG && + logger.log( + " New path has length of", + this.totalLength, + "with", + this.entityPath.length, + "entities" + ); + + // This is just for sanity + beltComp.assignedPath = null; + + // Clean up items + if (this.items.length === 0) { + // Simple case with no items, just update the first item spacing + this.spacingToFirstItem = this.totalLength; + } else { + // Ok, make sure we simply drop all items which are no longer contained + let itemOffset = this.spacingToFirstItem; + let lastItemOffset = itemOffset; + + DEBUG && logger.log(" Adjusting", this.items.length, "items"); + + for (let i = 0; i < this.items.length; ++i) { + const item = this.items[i]; + + // Get rid of items past this path + if (itemOffset >= this.totalLength) { + DEBUG && logger.log("Dropping item (current index=", i, ")"); + this.items.splice(i, 1); + i -= 1; + continue; + } + + DEBUG && logger.log("Item", i, "is at", itemOffset, "with next offset", item[_nextDistance]); + lastItemOffset = itemOffset; + itemOffset += item[_nextDistance]; + } + + // If we still have an item, make sure the last item matches + if (this.items.length > 0) { + // We can easily compute the next distance since we know where the last item is now + const lastDistance = this.totalLength - lastItemOffset; + assert( + lastDistance >= 0.0, + "Last item distance mismatch: " + + lastDistance + + " -> Total length was " + + this.totalLength + + " and lastItemOffset was " + + lastItemOffset + ); + + DEBUG && + logger.log( + "Adjusted distance of last item: it is at", + lastItemOffset, + "so it has a distance of", + lastDistance, + "to the end (", + this.totalLength, + ")" + ); + this.items[this.items.length - 1][_nextDistance] = lastDistance; + } else { + DEBUG && logger.log(" Removed all items so we'll update spacing to total length"); + + // We removed all items so update our spacing + this.spacingToFirstItem = this.totalLength; + } + } + + // Update bounds + this.worldBounds = this.computeBounds(); + + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_checkIntegrity("delete-on-end"); + } + } + + /** + * Deletes the entity of the start of the path + * @see deleteEntityOnEnd + * @param {Entity} entity + */ + deleteEntityOnStart(entity) { + assert( + entity === this.entityPath[0], + "Not actually the start entity (instead " + this.entityPath.indexOf(entity) + ")" + ); + + // Ok, first remove the entity + const beltComp = entity.components.Belt; + const beltLength = beltComp.getEffectiveLengthTiles(); + + DEBUG && + logger.log( + "Deleting first entity on path with length", + this.entityPath.length, + "(reducing", + this.totalLength, + " by", + beltLength, + ")" + ); + this.totalLength -= beltLength; + this.entityPath.shift(); + this.onPathChanged(); + + DEBUG && + logger.log( + " New path has length of", + this.totalLength, + "with", + this.entityPath.length, + "entities" + ); + + // This is just for sanity + beltComp.assignedPath = null; + + // Clean up items + if (this.items.length === 0) { + // Simple case with no items, just update the first item spacing + this.spacingToFirstItem = this.totalLength; + } else { + // Simple case, we had no item on the beginning -> all good + if (this.spacingToFirstItem >= beltLength) { + DEBUG && + logger.log( + " No item on the first place, so we can just adjust the spacing (spacing=", + this.spacingToFirstItem, + ") removed =", + beltLength + ); + this.spacingToFirstItem -= beltLength; + } else { + // Welp, okay we need to drop all items which are < beltLength and adjust + // the other item offsets as well + + DEBUG && + logger.log( + " We have at least one item in the beginning, drop those and adjust spacing (first item @", + this.spacingToFirstItem, + ") since we removed", + beltLength, + "length from path" + ); + DEBUG && + logger.log( + " Items:", + this.items.map(i => i[_nextDistance]) + ); + + // Find offset to first item + let itemOffset = this.spacingToFirstItem; + for (let i = 0; i < this.items.length; ++i) { + const item = this.items[i]; + if (itemOffset <= beltLength) { + DEBUG && + logger.log( + " -> Dropping item with index", + i, + "at", + itemOffset, + "since it was on the removed belt" + ); + // This item must be dropped + this.items.splice(i, 1); + i -= 1; + itemOffset += item[_nextDistance]; + continue; + } else { + // This item can be kept, thus its the first we know + break; + } + } + + if (this.items.length > 0) { + DEBUG && + logger.log( + " Offset of first non-dropped item was at:", + itemOffset, + "-> setting spacing to it (total length=", + this.totalLength, + ")" + ); + + this.spacingToFirstItem = itemOffset - beltLength; + assert( + this.spacingToFirstItem >= 0.0, + "Invalid spacing after delete on start: " + this.spacingToFirstItem + ); + } else { + DEBUG && logger.log(" We dropped all items, simply set spacing to total length"); + // We dropped all items, simple one + this.spacingToFirstItem = this.totalLength; + } + } + } + + // Update bounds + this.worldBounds = this.computeBounds(); + + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_checkIntegrity("delete-on-start"); + } + } + + /** + * Extends the path by the given other path + * @param {BeltPath} otherPath + */ + extendByPath(otherPath) { + assert(otherPath !== this, "Circular path dependency"); + + const entities = otherPath.entityPath; + DEBUG && logger.log("Extending path by other path, starting to add entities"); + + const oldLength = this.totalLength; + + DEBUG && logger.log(" Adding", entities.length, "new entities, current length =", this.totalLength); + + // First, append entities + for (let i = 0; i < entities.length; ++i) { + const entity = entities[i]; + const beltComp = entity.components.Belt; + + // Add to path and update references + this.entityPath.push(entity); + beltComp.assignedPath = this; + + // Update our length + const additionalLength = beltComp.getEffectiveLengthTiles(); + this.totalLength += additionalLength; + } + + DEBUG && + logger.log( + " Path is now", + this.entityPath.length, + "entities and has a length of", + this.totalLength + ); + + // Now, update the distance of our last item + if (this.items.length !== 0) { + const lastItem = this.items[this.items.length - 1]; + lastItem[_nextDistance] += otherPath.spacingToFirstItem; + DEBUG && + logger.log(" Add distance to last item, effectively being", lastItem[_nextDistance], "now"); + } else { + // Seems we have no items, update our first item distance + this.spacingToFirstItem = oldLength + otherPath.spacingToFirstItem; + DEBUG && + logger.log( + " We had no items, so our new spacing to first is old length (", + oldLength, + ") plus others spacing to first (", + otherPath.spacingToFirstItem, + ") =", + this.spacingToFirstItem + ); + } + + DEBUG && logger.log(" Pushing", otherPath.items.length, "items from other path"); + + // Aaand push the other paths items + for (let i = 0; i < otherPath.items.length; ++i) { + const item = otherPath.items[i]; + this.items.push([item[_nextDistance], item[_item]]); + } + + // Update bounds + this.worldBounds = this.computeBounds(); + + this.onPathChanged(); + + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_checkIntegrity("extend-by-path"); + } + } + + /** + * Computes the total length of the path + * @returns {number} + */ + computeTotalLength() { + let length = 0; + for (let i = 0; i < this.entityPath.length; ++i) { + const entity = this.entityPath[i]; + length += entity.components.Belt.getEffectiveLengthTiles(); + } + return length; + } + + /** + * Performs one tick + */ + update() { + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_checkIntegrity("pre-update"); + } + + // Divide by item spacing on belts since we use throughput and not speed + let beltSpeed = + this.root.hubGoals.getBeltBaseSpeed() * + this.root.dynamicTickrate.deltaSeconds * + globalConfig.itemSpacingOnBelts; + + if (G_IS_DEV && globalConfig.debug.instantBelts) { + beltSpeed *= 100; + } + + // Store whether this is the first item we processed, so premature + // item ejection is available + let isFirstItemProcessed = true; + + // Store how much velocity (strictly its distance, not velocity) we have to distribute over all items + let remainingVelocity = beltSpeed; + + for (let i = this.items.length - 1; i >= 0; --i) { + const nextDistanceAndItem = this.items[i]; + + // Compute how much spacing we need at least + const minimumSpacing = i === this.items.length - 1 ? 0 : globalConfig.itemSpacingOnBelts; + + // Compute how much we can advance + const clampedProgress = Math.max( + 0, + Math.min(remainingVelocity, nextDistanceAndItem[_nextDistance] - minimumSpacing) + ); + + // Reduce our velocity by the amount we consumed + remainingVelocity -= clampedProgress; + + // Reduce the spacing + nextDistanceAndItem[_nextDistance] -= clampedProgress; + + // If the last item can be ejected, eject it and reduce the spacing, because otherwise + // we lose velocity + if (isFirstItemProcessed && nextDistanceAndItem[_nextDistance] < 1e-7) { + // Store how much velocity we "lost" because we bumped the item to the end of the + // belt but couldn't move it any farther. We need this to tell the item acceptor + // animation to start a tad later, so everything matches up. Yes I'm a perfectionist. + const excessVelocity = beltSpeed - clampedProgress; + + // Try to directly get rid of the item + if (this.tryHandOverItem(nextDistanceAndItem[_item], excessVelocity)) { + this.items.pop(); + } + } + + isFirstItemProcessed = false; + this.spacingToFirstItem += clampedProgress; + if (remainingVelocity < 0.01) { + break; + } + } + + // Check if we have an item which is ready to be emitted + const lastItem = this.items[this.items.length - 1]; + if (lastItem && lastItem[_nextDistance] === 0 && this.acceptorTarget) { + if (this.tryHandOverItem(lastItem[_item])) { + this.items.pop(); + } + } + + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_checkIntegrity("post-update"); + } + } + + /** + * Tries to hand over the item to the end entity + * @param {BaseItem} item + */ + tryHandOverItem(item, remainingProgress = 0.0) { + if (!this.acceptorTarget) { + return; + } + + const targetAcceptorComp = this.acceptorTarget.entity.components.ItemAcceptor; + + // Check if the acceptor has a filter for example + if (targetAcceptorComp && !targetAcceptorComp.canAcceptItem(this.acceptorTarget.slot, item)) { + // Well, this item is not accepted + return false; + } + + // Try to pass over + if ( + this.root.systemMgr.systems.itemEjector.tryPassOverItem( + item, + this.acceptorTarget.entity, + this.acceptorTarget.slot + ) + ) { + // Trigger animation on the acceptor comp + const targetAcceptorComp = this.acceptorTarget.entity.components.ItemAcceptor; + if (targetAcceptorComp) { + targetAcceptorComp.onItemAccepted( + this.acceptorTarget.slot, + this.acceptorTarget.direction, + item, + remainingProgress + ); + } + + return true; + } + + return false; + } + + /** + * Computes a world space position from the given progress + * @param {number} progress + * @returns {Vector} + */ + computePositionFromProgress(progress) { + let currentLength = 0; + + // floating point issuses .. + assert(progress <= this.totalLength + 0.02, "Progress too big: " + progress); + + for (let i = 0; i < this.entityPath.length; ++i) { + const beltComp = this.entityPath[i].components.Belt; + const localLength = beltComp.getEffectiveLengthTiles(); + + if (currentLength + localLength >= progress || i === this.entityPath.length - 1) { + // Min required here due to floating point issues + const localProgress = Math.min(1.0, progress - currentLength); + + assert(localProgress >= 0.0, "Invalid local progress: " + localProgress); + const localSpace = beltComp.transformBeltToLocalSpace(localProgress); + return this.entityPath[i].components.StaticMapEntity.localTileToWorld(localSpace); + } + currentLength += localLength; + } + + assert(false, "invalid progress: " + progress + " (max: " + this.totalLength + ")"); + } + + /** + * + * @param {DrawParameters} parameters + */ + drawDebug(parameters) { + if (!parameters.visibleRect.containsRect(this.worldBounds)) { + return; + } + + parameters.context.fillStyle = "#d79a25"; + parameters.context.strokeStyle = "#d79a25"; + parameters.context.beginPath(); + + for (let i = 0; i < this.entityPath.length; ++i) { + const entity = this.entityPath[i]; + const pos = entity.components.StaticMapEntity; + const worldPos = pos.origin.toWorldSpaceCenterOfTile(); + + if (i === 0) { + parameters.context.moveTo(worldPos.x, worldPos.y); + } else { + parameters.context.lineTo(worldPos.x, worldPos.y); + } + } + parameters.context.stroke(); + + // Items + let progress = this.spacingToFirstItem; + for (let i = 0; i < this.items.length; ++i) { + const nextDistanceAndItem = this.items[i]; + const worldPos = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile(); + parameters.context.fillStyle = "#268e4d"; + parameters.context.beginRoundedRect(worldPos.x - 5, worldPos.y - 5, 10, 10, 3); + parameters.context.fill(); + parameters.context.font = "6px GameFont"; + parameters.context.fillStyle = "#111"; + parameters.context.fillText( + "" + round4Digits(nextDistanceAndItem[_nextDistance]), + worldPos.x + 5, + worldPos.y + 2 + ); + progress += nextDistanceAndItem[_nextDistance]; + } + + for (let i = 0; i < this.entityPath.length; ++i) { + const entity = this.entityPath[i]; + parameters.context.fillStyle = "#d79a25"; + const pos = entity.components.StaticMapEntity; + const worldPos = pos.origin.toWorldSpaceCenterOfTile(); + parameters.context.beginCircle(worldPos.x, worldPos.y, i === 0 ? 5 : 3); + parameters.context.fill(); + } + + for (let progress = 0; progress <= this.totalLength + 0.01; progress += 0.2) { + const worldPos = this.computePositionFromProgress(progress).toWorldSpaceCenterOfTile(); + parameters.context.fillStyle = "red"; + parameters.context.beginCircle(worldPos.x, worldPos.y, 1); + parameters.context.fill(); + } + + const firstItemIndicator = this.computePositionFromProgress( + this.spacingToFirstItem + ).toWorldSpaceCenterOfTile(); + parameters.context.fillStyle = "purple"; + parameters.context.fillRect(firstItemIndicator.x - 3, firstItemIndicator.y - 1, 6, 2); + } + + /** + * Draws the path + * @param {DrawParameters} parameters + */ + draw(parameters) { + if (!parameters.visibleRect.containsRect(this.worldBounds)) { + return; + } + + if (this.items.length === 0) { + // Early out + return; + } + + let currentItemPos = this.spacingToFirstItem; + let currentItemIndex = 0; + + let trackPos = 0.0; + + // Iterate whole track and check items + for (let i = 0; i < this.entityPath.length; ++i) { + const entity = this.entityPath[i]; + const beltComp = entity.components.Belt; + const beltLength = beltComp.getEffectiveLengthTiles(); + + // Check if the current items are on the belt + while (trackPos + beltLength >= currentItemPos - 1e-5) { + // Its on the belt, render it now + const staticComp = entity.components.StaticMapEntity; + assert( + currentItemPos - trackPos >= 0, + "invalid track pos: " + currentItemPos + " vs " + trackPos + " (l =" + beltLength + ")" + ); + + const localPos = beltComp.transformBeltToLocalSpace(currentItemPos - trackPos); + const worldPos = staticComp.localTileToWorld(localPos).toWorldSpaceCenterOfTile(); + + const distanceAndItem = this.items[currentItemIndex]; + + distanceAndItem[_item].drawItemCenteredClipped( + worldPos.x, + worldPos.y, + parameters, + globalConfig.defaultItemDiameter + ); + + // Check for the next item + currentItemPos += distanceAndItem[_nextDistance]; + ++currentItemIndex; + + if (currentItemIndex >= this.items.length) { + // We rendered all items + return; + } + } + + trackPos += beltLength; + } + } +} diff --git a/src/js/game/blueprint.js b/src/js/game/blueprint.js index 4e322eb0..ccbbc248 100644 --- a/src/js/game/blueprint.js +++ b/src/js/game/blueprint.js @@ -3,7 +3,7 @@ import { Loader } from "../core/loader"; import { createLogger } from "../core/logging"; import { Vector } from "../core/vector"; import { Entity } from "./entity"; -import { GameRoot, enumLayer } from "./root"; +import { GameRoot } from "./root"; import { findNiceIntegerValue } from "../core/utils"; import { blueprintShape } from "./upgrades"; import { globalConfig } from "../core/config"; @@ -20,11 +20,11 @@ export class Blueprint { /** * Returns the layer of this blueprint - * @returns {enumLayer} + * @returns {Layer} */ get layer() { if (this.entities.length === 0) { - return enumLayer.regular; + return "regular"; } return this.entities[0].layer; } @@ -81,10 +81,6 @@ export class Blueprint { for (let i = 0; i < this.entities.length; ++i) { const entity = this.entities[i]; const staticComp = entity.components.StaticMapEntity; - if (!staticComp.blueprintSpriteKey) { - logger.warn("Blueprint entity without sprite!"); - return; - } const newPos = staticComp.origin.add(tile); const rect = staticComp.getTileSpaceBounds(); @@ -96,13 +92,7 @@ export class Blueprint { parameters.context.globalAlpha = 1; } - staticComp.drawSpriteOnFullEntityBounds( - parameters, - Loader.getSprite(staticComp.blueprintSpriteKey), - 0, - true, - newPos - ); + staticComp.drawSpriteOnBoundsClipped(parameters, staticComp.getBlueprintSprite(), 0, newPos); } parameters.context.globalAlpha = 1; } diff --git a/src/js/game/building_codes.js b/src/js/game/building_codes.js new file mode 100644 index 00000000..05c27f57 --- /dev/null +++ b/src/js/game/building_codes.js @@ -0,0 +1,83 @@ +/* typehints:start */ +import { MetaBuilding } from "./meta_building"; +import { AtlasSprite } from "../core/sprites"; +import { Vector } from "../core/vector"; +/* typehints:end */ + +/** + * @typedef {{ + * metaClass: typeof MetaBuilding, + * metaInstance?: MetaBuilding, + * variant?: string, + * rotationVariant?: number, + * tileSize?: Vector, + * sprite?: AtlasSprite, + * blueprintSprite?: AtlasSprite, + * silhouetteColor?: string + * }} BuildingVariantIdentifier + */ + +/** + * Stores a lookup table for all building variants (for better performance) + * @type {Object} + */ +export const gBuildingVariants = { + // Set later +}; + +/** + * Registers a new variant + * @param {number} id + * @param {typeof MetaBuilding} meta + * @param {string} variant + * @param {number} rotationVariant + */ +export function registerBuildingVariant( + id, + meta, + variant = "default" /* FIXME: Circular dependency, actually its defaultBuildingVariant */, + rotationVariant = 0 +) { + assert(!gBuildingVariants[id], "Duplicate id: " + id); + gBuildingVariants[id] = { + metaClass: meta, + variant, + rotationVariant, + // @ts-ignore + tileSize: new meta().getDimensions(variant), + }; +} + +/** + * + * @param {number} code + * @returns {BuildingVariantIdentifier} + */ +export function getBuildingDataFromCode(code) { + assert(gBuildingVariants[code], "Invalid building code: " + code); + return gBuildingVariants[code]; +} + +/** + * Finds the code for a given variant + * @param {MetaBuilding} metaBuilding + * @param {string} variant + * @param {number} rotationVariant + */ +export function getCodeFromBuildingData(metaBuilding, variant, rotationVariant) { + for (const key in gBuildingVariants) { + const data = gBuildingVariants[key]; + if ( + data.metaInstance.getId() === metaBuilding.getId() && + data.variant === variant && + data.rotationVariant === rotationVariant + ) { + return +key; + } + } + assertAlways( + false, + "Building not found by data: " + metaBuilding.getId() + " / " + variant + " / " + rotationVariant + ); + return 0; +} diff --git a/src/js/game/buildings/advanced_processor.js b/src/js/game/buildings/advanced_processor.js deleted file mode 100644 index a688c878..00000000 --- a/src/js/game/buildings/advanced_processor.js +++ /dev/null @@ -1,108 +0,0 @@ -import { formatItemsPerSecond } from "../../core/utils"; -import { enumDirection, Vector } from "../../core/vector"; -import { T } from "../../translations"; -import { enumItemType } from "../base_item"; -import { EnergyConsumerComponent } from "../components/energy_consumer"; -import { ItemAcceptorComponent } from "../components/item_acceptor"; -import { ItemEjectorComponent } from "../components/item_ejector"; -import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; -import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; -import { Entity } from "../entity"; -import { MetaBuilding } from "../meta_building"; -import { enumLayer, GameRoot } from "../root"; - -export class MetaAdvancedProcessorBuilding extends MetaBuilding { - constructor() { - super("advanced_processor"); - } - - getSilhouetteColor() { - return "#25d7b8"; - } - - getDimensions(variant) { - return new Vector(2, 2); - } - - /** - * @param {GameRoot} root - * @param {string} variant - * @returns {Array<[string, string]>} - */ - getAdditionalStatistics(root, variant) { - const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.advancedProcessor); - return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; - } - - /** - * @param {GameRoot} root - */ - getIsUnlocked(root) { - // TODO - return true; - // return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash); - } - - /** - * Creates the entity at the given location - * @param {Entity} entity - */ - setupEntityComponents(entity) { - entity.addComponent( - new ItemProcessorComponent({ - inputsPerCharge: 1, - processorType: enumItemProcessorTypes.advancedProcessor, - }) - ); - entity.addComponent( - new ItemEjectorComponent({ - slots: [ - { pos: new Vector(1, 0), direction: enumDirection.right }, - { pos: new Vector(1, 0), direction: enumDirection.top, layer: enumLayer.wires }, - ], - }) - ); - entity.addComponent( - new EnergyConsumerComponent({ - bufferSize: 3, - perCharge: 1, - batteryPosition: new Vector(0.63, 0.7), - acceptorSlotIndex: 1, - ejectorSlotIndex: 1, - }) - ); - - entity.addComponent( - new WiredPinsComponent({ - slots: [ - { - pos: new Vector(0, 0), - direction: enumDirection.top, - type: enumPinSlotType.positiveEnergyAcceptor, - }, - { - pos: new Vector(1, 0), - direction: enumDirection.top, - type: enumPinSlotType.negativeEnergyEjector, - }, - ], - }) - ); - entity.addComponent( - new ItemAcceptorComponent({ - slots: [ - { - pos: new Vector(0, 1), - directions: [enumDirection.left], - }, - { - pos: new Vector(0, 0), - directions: [enumDirection.top], - filter: enumItemType.positiveEnergy, - layer: enumLayer.wires, - }, - ], - }) - ); - } -} diff --git a/src/js/game/buildings/belt_base.js b/src/js/game/buildings/belt_base.js index b8e92150..1aafa9e1 100644 --- a/src/js/game/buildings/belt_base.js +++ b/src/js/game/buildings/belt_base.js @@ -1,18 +1,20 @@ -import { Loader } from "../../core/loader"; -import { formatItemsPerSecond } from "../../core/utils"; +import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils"; import { enumAngleToDirection, enumDirection, Vector } from "../../core/vector"; import { SOUNDS } from "../../platform/sound"; import { T } from "../../translations"; import { BeltComponent } from "../components/belt"; -import { ItemAcceptorComponent } from "../components/item_acceptor"; -import { ItemEjectorComponent } from "../components/item_ejector"; -import { ReplaceableMapEntityComponent } from "../components/replaceable_map_entity"; import { Entity } from "../entity"; import { MetaBuilding } from "../meta_building"; -import { GameRoot, enumLayer } from "../root"; +import { GameRoot } from "../root"; export const arrayBeltVariantToRotation = [enumDirection.top, enumDirection.left, enumDirection.right]; +export const beltOverlayMatrices = { + [enumDirection.top]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]), + [enumDirection.left]: generateMatrixRotations([0, 0, 0, 1, 1, 0, 0, 1, 0]), + [enumDirection.right]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]), +}; + export class MetaBeltBaseBuilding extends MetaBuilding { getHasDirectionLockAvailable() { return true; @@ -24,7 +26,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding { * @returns {Array<[string, string]>} */ getAdditionalStatistics(root, variant) { - const beltSpeed = root.hubGoals.getBeltBaseSpeed(enumLayer.regular); + const beltSpeed = root.hubGoals.getBeltBaseSpeed(); return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]]; } @@ -40,6 +42,25 @@ export class MetaBeltBaseBuilding extends MetaBuilding { return SOUNDS.placeBelt; } + getSprite() { + return null; + } + + getIsReplaceable() { + return true; + } + + /** + * + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return beltOverlayMatrices[entity.components.Belt.direction][rotation]; + } + /** * Creates the entity at the given location * @param {Entity} entity @@ -50,34 +71,6 @@ export class MetaBeltBaseBuilding extends MetaBuilding { direction: enumDirection.top, // updated later }) ); - // Make this entity replaceabel - entity.addComponent(new ReplaceableMapEntityComponent()); - - entity.addComponent( - new ItemAcceptorComponent({ - slots: [ - { - pos: new Vector(0, 0), - directions: [enumDirection.bottom], - layer: this.getLayer(), - }, - ], - animated: false, - }) - ); - - entity.addComponent( - new ItemEjectorComponent({ - slots: [ - { - pos: new Vector(0, 0), - direction: enumDirection.top, // updated later - layer: this.getLayer(), - }, - ], - instantEject: true, - }) - ); } /** @@ -87,8 +80,6 @@ export class MetaBeltBaseBuilding extends MetaBuilding { */ updateVariants(entity, rotationVariant) { entity.components.Belt.direction = arrayBeltVariantToRotation[rotationVariant]; - entity.components.ItemEjector.slots[0].direction = arrayBeltVariantToRotation[rotationVariant]; - entity.components.StaticMapEntity.spriteKey = null; } /** @@ -98,7 +89,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding { * @param {Vector} param0.tile * @param {number} param0.rotation * @param {string} param0.variant - * @param {string} param0.layer + * @param {Layer} param0.layer * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array }} */ computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { @@ -107,7 +98,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding { const bottomDirection = enumAngleToDirection[(rotation + 180) % 360]; const leftDirection = enumAngleToDirection[(rotation + 270) % 360]; - const { ejectors, acceptors } = root.logic.getEjectorsAndAcceptorsAtTile(tile, layer); + const { ejectors, acceptors } = root.logic.getEjectorsAndAcceptorsAtTile(tile); let hasBottomEjector = false; let hasRightEjector = false; diff --git a/src/js/game/buildings/constant_signal.js b/src/js/game/buildings/constant_signal.js new file mode 100644 index 00000000..d2c47c26 --- /dev/null +++ b/src/js/game/buildings/constant_signal.js @@ -0,0 +1,56 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { ConstantSignalComponent } from "../components/constant_signal"; + +export class MetaConstantSignalBuilding extends MetaBuilding { + constructor() { + super("constant_signal"); + } + + getSilhouetteColor() { + return "#2bafda"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getDimensions() { + return new Vector(1, 1); + } + + getRenderPins() { + return false; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + ], + }) + ); + entity.addComponent(new ConstantSignalComponent({})); + } +} diff --git a/src/js/game/buildings/cutter.js b/src/js/game/buildings/cutter.js index bfe142d5..7dee4449 100644 --- a/src/js/game/buildings/cutter.js +++ b/src/js/game/buildings/cutter.js @@ -1,123 +1,122 @@ -import { formatItemsPerSecond } from "../../core/utils"; -import { enumDirection, Vector } from "../../core/vector"; -import { T } from "../../translations"; -import { ItemAcceptorComponent } from "../components/item_acceptor"; -import { ItemEjectorComponent } from "../components/item_ejector"; -import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; -import { Entity } from "../entity"; -import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; -import { GameRoot } from "../root"; -import { enumHubGoalRewards } from "../tutorial_goals"; -import { enumItemType } from "../base_item"; - -/** @enum {string} */ -export const enumCutterVariants = { quad: "quad" }; - -export class MetaCutterBuilding extends MetaBuilding { - constructor() { - super("cutter"); - } - - getSilhouetteColor() { - return "#7dcda2"; - } - - getDimensions(variant) { - switch (variant) { - case defaultBuildingVariant: - return new Vector(2, 1); - case enumCutterVariants.quad: - return new Vector(4, 1); - default: - assertAlways(false, "Unknown splitter variant: " + variant); - } - } - - /** - * @param {GameRoot} root - * @param {string} variant - * @returns {Array<[string, string]>} - */ - getAdditionalStatistics(root, variant) { - const speed = root.hubGoals.getProcessorBaseSpeed( - variant === enumCutterVariants.quad - ? enumItemProcessorTypes.cutterQuad - : enumItemProcessorTypes.cutter - ); - return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; - } - - /** - * @param {GameRoot} root - */ - getAvailableVariants(root) { - if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_quad)) { - return [defaultBuildingVariant, enumCutterVariants.quad]; - } - return super.getAvailableVariants(root); - } - - /** - * @param {GameRoot} root - */ - getIsUnlocked(root) { - return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash); - } - - /** - * Creates the entity at the given location - * @param {Entity} entity - */ - setupEntityComponents(entity) { - entity.addComponent( - new ItemProcessorComponent({ - inputsPerCharge: 1, - processorType: enumItemProcessorTypes.cutter, - }) - ); - entity.addComponent(new ItemEjectorComponent({})); - entity.addComponent( - new ItemAcceptorComponent({ - slots: [ - { - pos: new Vector(0, 0), - directions: [enumDirection.bottom], - filter: enumItemType.shape, - }, - ], - }) - ); - } - - /** - * - * @param {Entity} entity - * @param {number} rotationVariant - * @param {string} variant - */ - updateVariants(entity, rotationVariant, variant) { - switch (variant) { - case defaultBuildingVariant: { - entity.components.ItemEjector.setSlots([ - { pos: new Vector(0, 0), direction: enumDirection.top }, - { pos: new Vector(1, 0), direction: enumDirection.top }, - ]); - entity.components.ItemProcessor.type = enumItemProcessorTypes.cutter; - break; - } - case enumCutterVariants.quad: { - entity.components.ItemEjector.setSlots([ - { pos: new Vector(0, 0), direction: enumDirection.top }, - { pos: new Vector(1, 0), direction: enumDirection.top }, - { pos: new Vector(2, 0), direction: enumDirection.top }, - { pos: new Vector(3, 0), direction: enumDirection.top }, - ]); - entity.components.ItemProcessor.type = enumItemProcessorTypes.cutterQuad; - break; - } - - default: - assertAlways(false, "Unknown painter variant: " + variant); - } - } -} +import { formatItemsPerSecond } from "../../core/utils"; +import { enumDirection, Vector } from "../../core/vector"; +import { T } from "../../translations"; +import { ItemAcceptorComponent } from "../components/item_acceptor"; +import { ItemEjectorComponent } from "../components/item_ejector"; +import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; +import { Entity } from "../entity"; +import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { enumHubGoalRewards } from "../tutorial_goals"; + +/** @enum {string} */ +export const enumCutterVariants = { quad: "quad" }; + +export class MetaCutterBuilding extends MetaBuilding { + constructor() { + super("cutter"); + } + + getSilhouetteColor() { + return "#7dcda2"; + } + + getDimensions(variant) { + switch (variant) { + case defaultBuildingVariant: + return new Vector(2, 1); + case enumCutterVariants.quad: + return new Vector(4, 1); + default: + assertAlways(false, "Unknown cutter variant: " + variant); + } + } + + /** + * @param {GameRoot} root + * @param {string} variant + * @returns {Array<[string, string]>} + */ + getAdditionalStatistics(root, variant) { + const speed = root.hubGoals.getProcessorBaseSpeed( + variant === enumCutterVariants.quad + ? enumItemProcessorTypes.cutterQuad + : enumItemProcessorTypes.cutter + ); + return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; + } + + /** + * @param {GameRoot} root + */ + getAvailableVariants(root) { + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_quad)) { + return [defaultBuildingVariant, enumCutterVariants.quad]; + } + return super.getAvailableVariants(root); + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash); + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new ItemProcessorComponent({ + inputsPerCharge: 1, + processorType: enumItemProcessorTypes.cutter, + }) + ); + entity.addComponent(new ItemEjectorComponent({})); + entity.addComponent( + new ItemAcceptorComponent({ + slots: [ + { + pos: new Vector(0, 0), + directions: [enumDirection.bottom], + filter: "shape", + }, + ], + }) + ); + } + + /** + * + * @param {Entity} entity + * @param {number} rotationVariant + * @param {string} variant + */ + updateVariants(entity, rotationVariant, variant) { + switch (variant) { + case defaultBuildingVariant: { + entity.components.ItemEjector.setSlots([ + { pos: new Vector(0, 0), direction: enumDirection.top }, + { pos: new Vector(1, 0), direction: enumDirection.top }, + ]); + entity.components.ItemProcessor.type = enumItemProcessorTypes.cutter; + break; + } + case enumCutterVariants.quad: { + entity.components.ItemEjector.setSlots([ + { pos: new Vector(0, 0), direction: enumDirection.top }, + { pos: new Vector(1, 0), direction: enumDirection.top }, + { pos: new Vector(2, 0), direction: enumDirection.top }, + { pos: new Vector(3, 0), direction: enumDirection.top }, + ]); + entity.components.ItemProcessor.type = enumItemProcessorTypes.cutterQuad; + break; + } + + default: + assertAlways(false, "Unknown painter variant: " + variant); + } + } +} diff --git a/src/js/game/buildings/display.js b/src/js/game/buildings/display.js new file mode 100644 index 00000000..9c072af9 --- /dev/null +++ b/src/js/game/buildings/display.js @@ -0,0 +1,51 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { DisplayComponent } from "../components/display"; + +export class MetaDisplayBuilding extends MetaBuilding { + constructor() { + super("display"); + } + + getSilhouetteColor() { + return "#aaaaaa"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + getDimensions() { + return new Vector(1, 1); + } + + getShowWiresLayerPreview() { + return true; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + ], + }) + ); + entity.addComponent(new DisplayComponent()); + } +} diff --git a/src/js/game/buildings/energy_generator.js b/src/js/game/buildings/energy_generator.js deleted file mode 100644 index 1d7ac18b..00000000 --- a/src/js/game/buildings/energy_generator.js +++ /dev/null @@ -1,109 +0,0 @@ -import { enumDirection, Vector } from "../../core/vector"; -import { enumItemType } from "../base_item"; -import { EnergyGeneratorComponent } from "../components/energy_generator"; -import { ItemAcceptorComponent } from "../components/item_acceptor"; -import { ItemEjectorComponent } from "../components/item_ejector"; -import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; -import { Entity } from "../entity"; -import { MetaBuilding } from "../meta_building"; -import { enumLayer, GameRoot } from "../root"; -import { enumHubGoalRewards } from "../tutorial_goals"; - -export class MetaEnergyGenerator extends MetaBuilding { - constructor() { - super("energy_generator"); - } - - getSilhouetteColor() { - return "#c425d7"; - } - - /** - * @param {GameRoot} root - * @param {string} variant - * @returns {Array<[string, string]>} - */ - getAdditionalStatistics(root, variant) { - // TODO - return []; - } - - getDimensions(variant) { - return new Vector(2, 2); - } - - /** - * @param {GameRoot} root - */ - getIsUnlocked(root) { - return true; - // return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash); - } - - /** - * Creates the entity at the given location - * @param {Entity} entity - */ - setupEntityComponents(entity) { - entity.addComponent( - new ItemAcceptorComponent({ - slots: [ - { - pos: new Vector(0, 1), - directions: [enumDirection.bottom], - filter: enumItemType.shape, - }, - { - pos: new Vector(1, 1), - directions: [enumDirection.bottom], - filter: enumItemType.shape, - }, - { - pos: new Vector(1, 0), - directions: [enumDirection.top], - layer: enumLayer.wires, - filter: enumItemType.negativeEnergy, - }, - ], - }) - ); - - entity.addComponent( - new ItemEjectorComponent({ - slots: [ - { - pos: new Vector(0, 0), - direction: enumDirection.top, - layer: enumLayer.wires, - }, - ], - instantEject: true, - }) - ); - - entity.addComponent( - new EnergyGeneratorComponent({ - // Set by the energy generator system later - requiredKey: null, - wasteAcceptorSlotIndex: 2, - }) - ); - - entity.addComponent( - new WiredPinsComponent({ - slots: [ - { - pos: new Vector(0, 0), - type: enumPinSlotType.positiveEnergyEjector, - direction: enumDirection.top, - }, - { - pos: new Vector(1, 0), - type: enumPinSlotType.negativeEnergyAcceptor, - direction: enumDirection.top, - }, - ], - }) - ); - } -} diff --git a/src/js/game/buildings/filter.js b/src/js/game/buildings/filter.js new file mode 100644 index 00000000..fb368fc7 --- /dev/null +++ b/src/js/game/buildings/filter.js @@ -0,0 +1,90 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { ItemAcceptorComponent } from "../components/item_acceptor"; +import { ItemEjectorComponent } from "../components/item_ejector"; +import { + enumItemProcessorRequirements, + enumItemProcessorTypes, + ItemProcessorComponent, +} from "../components/item_processor"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; + +export class MetaFilterBuilding extends MetaBuilding { + constructor() { + super("filter"); + } + + getSilhouetteColor() { + return "#c45c2e"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + getDimensions() { + return new Vector(2, 1); + } + + getShowWiresLayerPreview() { + return true; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(0, 0), + direction: enumDirection.left, + type: enumPinSlotType.logicalAcceptor, + }, + ], + }) + ); + + entity.addComponent( + new ItemAcceptorComponent({ + slots: [ + { + pos: new Vector(0, 0), + directions: [enumDirection.bottom], + }, + ], + }) + ); + + entity.addComponent( + new ItemEjectorComponent({ + slots: [ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + }, + { + pos: new Vector(1, 0), + direction: enumDirection.right, + }, + ], + }) + ); + + entity.addComponent( + new ItemProcessorComponent({ + processorType: enumItemProcessorTypes.filter, + inputsPerCharge: 1, + processingRequirement: enumItemProcessorRequirements.filter, + }) + ); + } +} diff --git a/src/js/game/buildings/hub.js b/src/js/game/buildings/hub.js index 61a61f27..b9929b31 100644 --- a/src/js/game/buildings/hub.js +++ b/src/js/game/buildings/hub.js @@ -1,11 +1,10 @@ import { enumDirection, Vector } from "../../core/vector"; -import { enumItemType } from "../base_item"; import { HubComponent } from "../components/hub"; import { ItemAcceptorComponent } from "../components/item_acceptor"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; -import { UnremovableComponent } from "../components/unremovable"; import { Entity } from "../entity"; import { MetaBuilding } from "../meta_building"; +import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins"; export class MetaHubBuilding extends MetaBuilding { constructor() { @@ -20,7 +19,7 @@ export class MetaHubBuilding extends MetaBuilding { return "#eb5555"; } - isRotateable() { + getIsRotateable() { return false; } @@ -28,6 +27,15 @@ export class MetaHubBuilding extends MetaBuilding { return null; } + getSprite() { + // We render it ourself + return null; + } + + getIsRemovable() { + return false; + } + /** * Creates the entity at the given location * @param {Entity} entity @@ -41,82 +49,90 @@ export class MetaHubBuilding extends MetaBuilding { }) ); - // We render the sprite ourself - entity.components.StaticMapEntity.spriteKey = null; + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(0, 2), + type: enumPinSlotType.logicalEjector, + direction: enumDirection.left, + }, + ], + }) + ); - entity.addComponent(new UnremovableComponent()); entity.addComponent( new ItemAcceptorComponent({ slots: [ { pos: new Vector(0, 0), directions: [enumDirection.top, enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(1, 0), directions: [enumDirection.top], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(2, 0), directions: [enumDirection.top], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(3, 0), directions: [enumDirection.top, enumDirection.right], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(0, 3), directions: [enumDirection.bottom, enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(1, 3), directions: [enumDirection.bottom], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(2, 3), directions: [enumDirection.bottom], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(3, 3), directions: [enumDirection.bottom, enumDirection.right], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(0, 1), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(0, 2), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(0, 3), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(3, 1), directions: [enumDirection.right], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(3, 2), directions: [enumDirection.right], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(3, 3), directions: [enumDirection.right], - filter: enumItemType.shape, + filter: "shape", }, ], }) diff --git a/src/js/game/buildings/lever.js b/src/js/game/buildings/lever.js new file mode 100644 index 00000000..244a9b17 --- /dev/null +++ b/src/js/game/buildings/lever.js @@ -0,0 +1,57 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { LeverComponent } from "../components/lever"; + +export class MetaLeverBuilding extends MetaBuilding { + constructor() { + super("lever"); + } + + getSilhouetteColor() { + // @todo: Render differently based on if its activated or not + return "#1a678b"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + getDimensions() { + return new Vector(1, 1); + } + + getSprite() { + return null; + } + + getShowWiresLayerPreview() { + return true; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + ], + }) + ); + + entity.addComponent(new LeverComponent({})); + } +} diff --git a/src/js/game/buildings/logic_gate.js b/src/js/game/buildings/logic_gate.js new file mode 100644 index 00000000..e07db3ea --- /dev/null +++ b/src/js/game/buildings/logic_gate.js @@ -0,0 +1,155 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; +import { GameRoot } from "../root"; +import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate"; + +/** @enum {string} */ +export const enumLogicGateVariants = { + not: "not", + xor: "xor", + or: "or", + transistor: "transistor", +}; + +/** @enum {string} */ +export const enumVariantToGate = { + [defaultBuildingVariant]: enumLogicGateType.and, + [enumLogicGateVariants.not]: enumLogicGateType.not, + [enumLogicGateVariants.xor]: enumLogicGateType.xor, + [enumLogicGateVariants.or]: enumLogicGateType.or, + [enumLogicGateVariants.transistor]: enumLogicGateType.transistor, +}; + +export class MetaLogicGateBuilding extends MetaBuilding { + constructor() { + super("logic_gate"); + } + + getSilhouetteColor() { + return "#89dc60"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getDimensions() { + return new Vector(1, 1); + } + + getAvailableVariants() { + return [ + defaultBuildingVariant, + enumLogicGateVariants.not, + enumLogicGateVariants.xor, + enumLogicGateVariants.or, + enumLogicGateVariants.transistor, + ]; + } + + getRenderPins() { + // We already have it included + return false; + } + + /** + * + * @param {Entity} entity + * @param {number} rotationVariant + */ + updateVariants(entity, rotationVariant, variant) { + const gateType = enumVariantToGate[variant]; + entity.components.LogicGate.type = gateType; + + const pinComp = entity.components.WiredPins; + + switch (gateType) { + case enumLogicGateType.and: + case enumLogicGateType.xor: + case enumLogicGateType.or: { + pinComp.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.left, + type: enumPinSlotType.logicalAcceptor, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.right, + type: enumPinSlotType.logicalAcceptor, + }, + ]); + break; + } + case enumLogicGateType.transistor: { + pinComp.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.left, + type: enumPinSlotType.logicalAcceptor, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + ]); + break; + } + + case enumLogicGateType.not: { + pinComp.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + ]); + break; + } + + default: + assertAlways("unknown logic gate type: " + gateType); + } + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new WiredPinsComponent({ + slots: [], + }) + ); + + entity.addComponent(new LogicGateComponent({})); + } +} diff --git a/src/js/game/buildings/miner.js b/src/js/game/buildings/miner.js index ed87bc85..1a9c97ff 100644 --- a/src/js/game/buildings/miner.js +++ b/src/js/game/buildings/miner.js @@ -6,11 +6,13 @@ import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; import { GameRoot } from "../root"; import { enumHubGoalRewards } from "../tutorial_goals"; import { T } from "../../translations"; -import { round1Digit, round2Digits, formatItemsPerSecond } from "../../core/utils"; +import { formatItemsPerSecond } from "../../core/utils"; /** @enum {string} */ export const enumMinerVariants = { chainable: "chainable" }; +const overlayMatrix = [1, 1, 1, 1, 0, 1, 1, 1, 1]; + export class MetaMinerBuilding extends MetaBuilding { constructor() { super("miner"); @@ -41,6 +43,16 @@ export class MetaMinerBuilding extends MetaBuilding { return super.getAvailableVariants(root); } + /** + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return overlayMatrix; + } + /** * Creates the entity at the given location * @param {Entity} entity diff --git a/src/js/game/buildings/mixer.js b/src/js/game/buildings/mixer.js index a2b35280..cbde309e 100644 --- a/src/js/game/buildings/mixer.js +++ b/src/js/game/buildings/mixer.js @@ -1,7 +1,6 @@ import { formatItemsPerSecond } from "../../core/utils"; import { enumDirection, Vector } from "../../core/vector"; import { T } from "../../translations"; -import { enumItemType } from "../base_item"; import { ItemAcceptorComponent } from "../components/item_acceptor"; import { ItemEjectorComponent } from "../components/item_ejector"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; @@ -63,12 +62,12 @@ export class MetaMixerBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.bottom], - filter: enumItemType.color, + filter: "color", }, { pos: new Vector(1, 0), directions: [enumDirection.bottom], - filter: enumItemType.color, + filter: "color", }, ], }) diff --git a/src/js/game/buildings/painter.js b/src/js/game/buildings/painter.js index 61e77a7c..b74d24b9 100644 --- a/src/js/game/buildings/painter.js +++ b/src/js/game/buildings/painter.js @@ -3,12 +3,16 @@ import { enumDirection, Vector } from "../../core/vector"; import { T } from "../../translations"; import { ItemAcceptorComponent } from "../components/item_acceptor"; import { ItemEjectorComponent } from "../components/item_ejector"; -import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; +import { + enumItemProcessorTypes, + ItemProcessorComponent, + enumItemProcessorRequirements, +} from "../components/item_processor"; import { Entity } from "../entity"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; import { GameRoot } from "../root"; import { enumHubGoalRewards } from "../tutorial_goals"; -import { enumItemType } from "../base_item"; +import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins"; /** @enum {string} */ export const enumPainterVariants = { mirrored: "mirrored", double: "double", quad: "quad" }; @@ -98,12 +102,12 @@ export class MetaPainterBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(1, 0), directions: [enumDirection.top], - filter: enumItemType.color, + filter: "color", }, ], }) @@ -120,92 +124,143 @@ export class MetaPainterBuilding extends MetaBuilding { switch (variant) { case defaultBuildingVariant: case enumPainterVariants.mirrored: { + // REGULAR PAINTER + + if (entity.components.WiredPins) { + entity.removeComponent(WiredPinsComponent); + } + entity.components.ItemAcceptor.setSlots([ { pos: new Vector(0, 0), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(1, 0), directions: [ variant === defaultBuildingVariant ? enumDirection.top : enumDirection.bottom, ], - filter: enumItemType.color, + filter: "color", }, ]); - entity.components.ItemProcessor.type = enumItemProcessorTypes.painter; - entity.components.ItemProcessor.inputsPerCharge = 2; entity.components.ItemEjector.setSlots([ { pos: new Vector(1, 0), direction: enumDirection.right }, ]); + + entity.components.ItemProcessor.type = enumItemProcessorTypes.painter; + entity.components.ItemProcessor.processingRequirement = null; + entity.components.ItemProcessor.inputsPerCharge = 2; + break; } + case enumPainterVariants.double: { + // DOUBLE PAINTER + + if (entity.components.WiredPins) { + entity.removeComponent(WiredPinsComponent); + } + entity.components.ItemAcceptor.setSlots([ { pos: new Vector(0, 0), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(0, 1), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(1, 0), directions: [enumDirection.top], - filter: enumItemType.color, + filter: "color", }, ]); - entity.components.ItemProcessor.type = enumItemProcessorTypes.painterDouble; - entity.components.ItemProcessor.inputsPerCharge = 3; - entity.components.ItemEjector.setSlots([ { pos: new Vector(1, 0), direction: enumDirection.right }, ]); + + entity.components.ItemProcessor.type = enumItemProcessorTypes.painterDouble; + entity.components.ItemProcessor.processingRequirement = null; + entity.components.ItemProcessor.inputsPerCharge = 3; break; } + case enumPainterVariants.quad: { + // QUAD PAINTER + + if (!entity.components.WiredPins) { + entity.addComponent(new WiredPinsComponent({ slots: [] })); + } + + entity.components.WiredPins.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + { + pos: new Vector(1, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + { + pos: new Vector(2, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + { + pos: new Vector(3, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + ]); + entity.components.ItemAcceptor.setSlots([ { pos: new Vector(0, 0), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(0, 0), directions: [enumDirection.bottom], - filter: enumItemType.color, + filter: "color", }, { pos: new Vector(1, 0), directions: [enumDirection.bottom], - filter: enumItemType.color, + filter: "color", }, { pos: new Vector(2, 0), directions: [enumDirection.bottom], - filter: enumItemType.color, + filter: "color", }, { pos: new Vector(3, 0), directions: [enumDirection.bottom], - filter: enumItemType.color, + filter: "color", }, ]); - entity.components.ItemProcessor.type = enumItemProcessorTypes.painterQuad; - entity.components.ItemProcessor.inputsPerCharge = 5; - entity.components.ItemEjector.setSlots([ { pos: new Vector(0, 0), direction: enumDirection.top }, ]); + + entity.components.ItemProcessor.type = enumItemProcessorTypes.painterQuad; + entity.components.ItemProcessor.processingRequirement = + enumItemProcessorRequirements.painterQuad; + entity.components.ItemProcessor.inputsPerCharge = 5; + break; } + default: assertAlways(false, "Unknown painter variant: " + variant); } diff --git a/src/js/game/buildings/reader.js b/src/js/game/buildings/reader.js new file mode 100644 index 00000000..cc3bd6b0 --- /dev/null +++ b/src/js/game/buildings/reader.js @@ -0,0 +1,101 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { ItemAcceptorComponent } from "../components/item_acceptor"; +import { ItemEjectorComponent } from "../components/item_ejector"; +import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { BeltUnderlaysComponent } from "../components/belt_underlays"; +import { BeltReaderComponent } from "../components/belt_reader"; + +export class MetaReaderBuilding extends MetaBuilding { + constructor() { + super("reader"); + } + + getSilhouetteColor() { + return "#25fff2"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + getDimensions() { + return new Vector(1, 1); + } + + getShowWiresLayerPreview() { + return true; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(0, 0), + direction: enumDirection.right, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.left, + type: enumPinSlotType.logicalEjector, + }, + ], + }) + ); + + entity.addComponent( + new ItemAcceptorComponent({ + slots: [ + { + pos: new Vector(0, 0), + directions: [enumDirection.bottom], + }, + ], + }) + ); + + entity.addComponent( + new ItemEjectorComponent({ + slots: [ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + }, + ], + }) + ); + + entity.addComponent( + new ItemProcessorComponent({ + processorType: enumItemProcessorTypes.reader, + inputsPerCharge: 1, + }) + ); + + entity.addComponent( + new BeltUnderlaysComponent({ + underlays: [ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + }, + ], + }) + ); + + entity.addComponent(new BeltReaderComponent()); + } +} diff --git a/src/js/game/buildings/rotater.js b/src/js/game/buildings/rotater.js index 56c0c87d..c278ef0d 100644 --- a/src/js/game/buildings/rotater.js +++ b/src/js/game/buildings/rotater.js @@ -8,10 +8,9 @@ import { Entity } from "../entity"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; import { GameRoot } from "../root"; import { enumHubGoalRewards } from "../tutorial_goals"; -import { enumItemType } from "../base_item"; /** @enum {string} */ -export const enumRotaterVariants = { ccw: "ccw" }; +export const enumRotaterVariants = { ccw: "ccw", fl: "fl" }; export class MetaRotaterBuilding extends MetaBuilding { constructor() { @@ -28,12 +27,20 @@ export class MetaRotaterBuilding extends MetaBuilding { * @returns {Array<[string, string]>} */ getAdditionalStatistics(root, variant) { - const speed = root.hubGoals.getProcessorBaseSpeed( - variant === enumRotaterVariants.ccw - ? enumItemProcessorTypes.rotaterCCW - : enumItemProcessorTypes.rotater - ); - return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; + switch (variant) { + case defaultBuildingVariant: { + const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotater); + return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; + } + case enumRotaterVariants.ccw: { + const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotaterCCW); + return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; + } + case enumRotaterVariants.fl: { + const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotaterFL); + return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; + } + } } /** @@ -41,10 +48,14 @@ export class MetaRotaterBuilding extends MetaBuilding { * @param {GameRoot} root */ getAvailableVariants(root) { + let variants = [defaultBuildingVariant]; if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater_ccw)) { - return [defaultBuildingVariant, enumRotaterVariants.ccw]; + variants.push(enumRotaterVariants.ccw); } - return super.getAvailableVariants(root); + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater_fl)) { + variants.push(enumRotaterVariants.fl); + } + return variants; } /** @@ -77,7 +88,7 @@ export class MetaRotaterBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.bottom], - filter: enumItemType.shape, + filter: "shape", }, ], }) @@ -100,6 +111,10 @@ export class MetaRotaterBuilding extends MetaBuilding { entity.components.ItemProcessor.type = enumItemProcessorTypes.rotaterCCW; break; } + case enumRotaterVariants.fl: { + entity.components.ItemProcessor.type = enumItemProcessorTypes.rotaterFL; + break; + } default: assertAlways(false, "Unknown rotater variant: " + variant); } diff --git a/src/js/game/buildings/splitter.js b/src/js/game/buildings/splitter.js index 12f0e6e7..d512e002 100644 --- a/src/js/game/buildings/splitter.js +++ b/src/js/game/buildings/splitter.js @@ -1,156 +1,197 @@ -import { globalConfig } from "../../core/config"; -import { enumDirection, Vector } from "../../core/vector"; -import { ItemAcceptorComponent } from "../components/item_acceptor"; -import { ItemEjectorComponent } from "../components/item_ejector"; -import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; -import { Entity } from "../entity"; -import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; -import { GameRoot, enumLayer } from "../root"; -import { enumHubGoalRewards } from "../tutorial_goals"; -import { T } from "../../translations"; -import { formatItemsPerSecond } from "../../core/utils"; - -/** @enum {string} */ -export const enumSplitterVariants = { compact: "compact", compactInverse: "compact-inverse" }; - -export class MetaSplitterBuilding extends MetaBuilding { - constructor() { - super("splitter"); - } - - getDimensions(variant) { - switch (variant) { - case defaultBuildingVariant: - return new Vector(2, 1); - case enumSplitterVariants.compact: - case enumSplitterVariants.compactInverse: - return new Vector(1, 1); - default: - assertAlways(false, "Unknown splitter variant: " + variant); - } - } - - /** - * @param {GameRoot} root - * @param {string} variant - * @returns {Array<[string, string]>} - */ - getAdditionalStatistics(root, variant) { - const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.splitter); - return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; - } - - getSilhouetteColor() { - return "#444"; - } - - /** - * @param {GameRoot} root - */ - getAvailableVariants(root) { - if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_splitter_compact)) { - return [ - defaultBuildingVariant, - enumSplitterVariants.compact, - enumSplitterVariants.compactInverse, - ]; - } - return super.getAvailableVariants(root); - } - - /** - * @param {GameRoot} root - */ - getIsUnlocked(root) { - return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_splitter); - } - - /** - * Creates the entity at the given location - * @param {Entity} entity - */ - setupEntityComponents(entity) { - entity.addComponent( - new ItemAcceptorComponent({ - slots: [], // set later - }) - ); - - entity.addComponent( - new ItemProcessorComponent({ - inputsPerCharge: 1, - processorType: enumItemProcessorTypes.splitter, - }) - ); - - entity.addComponent( - new ItemEjectorComponent({ - slots: [], // set later - }) - ); - } - - /** - * - * @param {Entity} entity - * @param {number} rotationVariant - * @param {string} variant - */ - updateVariants(entity, rotationVariant, variant) { - switch (variant) { - case defaultBuildingVariant: { - entity.components.ItemAcceptor.setSlots([ - { - pos: new Vector(0, 0), - directions: [enumDirection.bottom], - }, - { - pos: new Vector(1, 0), - directions: [enumDirection.bottom], - }, - ]); - - entity.components.ItemEjector.setSlots([ - { pos: new Vector(0, 0), direction: enumDirection.top }, - { pos: new Vector(1, 0), direction: enumDirection.top }, - ]); - - entity.components.ItemAcceptor.beltUnderlays = [ - { pos: new Vector(0, 0), direction: enumDirection.top, layer: enumLayer.regular }, - { pos: new Vector(1, 0), direction: enumDirection.top, layer: enumLayer.regular }, - ]; - - break; - } - case enumSplitterVariants.compact: - case enumSplitterVariants.compactInverse: { - entity.components.ItemAcceptor.setSlots([ - { - pos: new Vector(0, 0), - directions: [enumDirection.bottom], - }, - { - pos: new Vector(0, 0), - directions: [ - variant === enumSplitterVariants.compactInverse - ? enumDirection.left - : enumDirection.right, - ], - }, - ]); - - entity.components.ItemEjector.setSlots([ - { pos: new Vector(0, 0), direction: enumDirection.top }, - ]); - - entity.components.ItemAcceptor.beltUnderlays = [ - { pos: new Vector(0, 0), direction: enumDirection.top, layer: enumLayer.regular }, - ]; - - break; - } - default: - assertAlways(false, "Unknown painter variant: " + variant); - } - } -} +import { enumDirection, Vector } from "../../core/vector"; +import { ItemAcceptorComponent } from "../components/item_acceptor"; +import { ItemEjectorComponent } from "../components/item_ejector"; +import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; +import { Entity } from "../entity"; +import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; +import { GameRoot } from "../root"; +import { enumHubGoalRewards } from "../tutorial_goals"; +import { T } from "../../translations"; +import { formatItemsPerSecond } from "../../core/utils"; +import { BeltUnderlaysComponent } from "../components/belt_underlays"; + +/** @enum {string} */ +export const enumSplitterVariants = { + compact: "compact", + compactInverse: "compact-inverse", + compactMerge: "compact-merge", + compactMergeInverse: "compact-merge-inverse", +}; + +export class MetaSplitterBuilding extends MetaBuilding { + constructor() { + super("splitter"); + } + + getDimensions(variant) { + switch (variant) { + case defaultBuildingVariant: + return new Vector(2, 1); + case enumSplitterVariants.compact: + case enumSplitterVariants.compactInverse: + case enumSplitterVariants.compactMerge: + case enumSplitterVariants.compactMergeInverse: + return new Vector(1, 1); + default: + assertAlways(false, "Unknown splitter variant: " + variant); + } + } + + /** + * @param {GameRoot} root + * @param {string} variant + * @returns {Array<[string, string]>} + */ + getAdditionalStatistics(root, variant) { + const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.splitter); + return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; + } + + getSilhouetteColor() { + return "#444"; + } + + /** + * @param {GameRoot} root + */ + getAvailableVariants(root) { + let available = [defaultBuildingVariant]; + + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_splitter_compact)) { + available.push(enumSplitterVariants.compact, enumSplitterVariants.compactInverse); + } + + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_merger_compact)) { + available.push(enumSplitterVariants.compactMerge, enumSplitterVariants.compactMergeInverse); + } + + return available; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_splitter); + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new ItemAcceptorComponent({ + slots: [], // set later + }) + ); + + entity.addComponent( + new ItemProcessorComponent({ + inputsPerCharge: 1, + processorType: enumItemProcessorTypes.splitter, + }) + ); + + entity.addComponent( + new ItemEjectorComponent({ + slots: [], // set later + }) + ); + + entity.addComponent(new BeltUnderlaysComponent({ underlays: [] })); + } + + /** + * + * @param {Entity} entity + * @param {number} rotationVariant + * @param {string} variant + */ + updateVariants(entity, rotationVariant, variant) { + switch (variant) { + case defaultBuildingVariant: { + entity.components.ItemAcceptor.setSlots([ + { + pos: new Vector(0, 0), + directions: [enumDirection.bottom], + }, + { + pos: new Vector(1, 0), + directions: [enumDirection.bottom], + }, + ]); + + entity.components.ItemEjector.setSlots([ + { pos: new Vector(0, 0), direction: enumDirection.top }, + { pos: new Vector(1, 0), direction: enumDirection.top }, + ]); + + entity.components.BeltUnderlays.underlays = [ + { pos: new Vector(0, 0), direction: enumDirection.top }, + { pos: new Vector(1, 0), direction: enumDirection.top }, + ]; + + break; + } + case enumSplitterVariants.compact: + case enumSplitterVariants.compactInverse: { + entity.components.ItemAcceptor.setSlots([ + { + pos: new Vector(0, 0), + directions: [enumDirection.bottom], + }, + { + pos: new Vector(0, 0), + directions: [ + variant === enumSplitterVariants.compactInverse + ? enumDirection.left + : enumDirection.right, + ], + }, + ]); + + entity.components.ItemEjector.setSlots([ + { pos: new Vector(0, 0), direction: enumDirection.top }, + ]); + + entity.components.BeltUnderlays.underlays = [ + { pos: new Vector(0, 0), direction: enumDirection.top }, + ]; + + break; + } + case enumSplitterVariants.compactMerge: + case enumSplitterVariants.compactMergeInverse: { + entity.components.ItemAcceptor.setSlots([ + { + pos: new Vector(0, 0), + directions: [enumDirection.bottom], + }, + ]); + + entity.components.ItemEjector.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + }, + { + pos: new Vector(0, 0), + direction: + variant === enumSplitterVariants.compactMergeInverse + ? enumDirection.left + : enumDirection.right, + }, + ]); + + entity.components.BeltUnderlays.underlays = [ + { pos: new Vector(0, 0), direction: enumDirection.top }, + ]; + + break; + } + default: + assertAlways(false, "Unknown splitter variant: " + variant); + } + } +} diff --git a/src/js/game/buildings/stacker.js b/src/js/game/buildings/stacker.js index 91ac3f62..40a9c5ae 100644 --- a/src/js/game/buildings/stacker.js +++ b/src/js/game/buildings/stacker.js @@ -8,7 +8,6 @@ import { Entity } from "../entity"; import { MetaBuilding } from "../meta_building"; import { GameRoot } from "../root"; import { enumHubGoalRewards } from "../tutorial_goals"; -import { enumItemType } from "../base_item"; export class MetaStackerBuilding extends MetaBuilding { constructor() { @@ -63,12 +62,12 @@ export class MetaStackerBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.bottom], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(1, 0), directions: [enumDirection.bottom], - filter: enumItemType.shape, + filter: "shape", }, ], }) diff --git a/src/js/game/buildings/trash.js b/src/js/game/buildings/trash.js index 8ae36b8d..dfd47dfe 100644 --- a/src/js/game/buildings/trash.js +++ b/src/js/game/buildings/trash.js @@ -1,14 +1,15 @@ +import { formatBigNumber } from "../../core/utils"; import { enumDirection, Vector } from "../../core/vector"; +import { T } from "../../translations"; import { ItemAcceptorComponent } from "../components/item_acceptor"; import { ItemEjectorComponent } from "../components/item_ejector"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; -import { Entity } from "../entity"; -import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; -import { enumHubGoalRewards } from "../tutorial_goals"; -import { GameRoot } from "../root"; import { StorageComponent } from "../components/storage"; -import { T } from "../../translations"; -import { formatBigNumber } from "../../core/utils"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { enumHubGoalRewards } from "../tutorial_goals"; /** @enum {string} */ export const enumTrashVariants = { storage: "storage" }; @@ -20,7 +21,7 @@ export class MetaTrashBuilding extends MetaBuilding { super("trash"); } - isRotateable(variant) { + getIsRotateable(variant) { return variant !== defaultBuildingVariant; } @@ -117,6 +118,9 @@ export class MetaTrashBuilding extends MetaBuilding { if (entity.components.Storage) { entity.removeComponent(StorageComponent); } + if (entity.components.WiredPins) { + entity.removeComponent(WiredPinsComponent); + } entity.components.ItemAcceptor.setSlots([ { @@ -140,6 +144,24 @@ export class MetaTrashBuilding extends MetaBuilding { if (!entity.components.Storage) { entity.addComponent(new StorageComponent({})); } + if (!entity.components.WiredPins) { + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(1, 1), + direction: enumDirection.right, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 1), + direction: enumDirection.left, + type: enumPinSlotType.logicalEjector, + }, + ], + }) + ); + } entity.components.Storage.maximumStorage = trashSize; entity.components.ItemAcceptor.setSlots([ diff --git a/src/js/game/buildings/underground_belt.js b/src/js/game/buildings/underground_belt.js index 99004b99..155b69e2 100644 --- a/src/js/game/buildings/underground_belt.js +++ b/src/js/game/buildings/underground_belt.js @@ -5,10 +5,10 @@ import { ItemEjectorComponent } from "../components/item_ejector"; import { enumUndergroundBeltMode, UndergroundBeltComponent } from "../components/underground_belt"; import { Entity } from "../entity"; import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; -import { GameRoot, enumLayer } from "../root"; +import { GameRoot } from "../root"; import { globalConfig } from "../../core/config"; import { enumHubGoalRewards } from "../tutorial_goals"; -import { formatItemsPerSecond } from "../../core/utils"; +import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils"; import { T } from "../../translations"; /** @enum {string} */ @@ -25,13 +25,21 @@ export const enumUndergroundBeltVariantToTier = { [enumUndergroundBeltVariants.tier2]: 1, }; +const overlayMatrices = [ + // Sender + generateMatrixRotations([1, 1, 1, 0, 1, 0, 0, 1, 0]), + + // Receiver + generateMatrixRotations([0, 1, 0, 0, 1, 0, 1, 1, 1]), +]; + export class MetaUndergroundBeltBuilding extends MetaBuilding { constructor() { super("underground_belt"); } getSilhouetteColor() { - return "#555"; + return "#222"; } getFlipOrientationAfterPlacement() { @@ -42,6 +50,16 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding { return true; } + /** + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return overlayMatrices[rotationVariant][rotation]; + } + /** * @param {GameRoot} root * @param {string} variant @@ -71,6 +89,10 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding { return super.getAvailableVariants(root); } + /** + * @param {number} rotationVariant + * @param {string} variant + */ getPreviewSprite(rotationVariant, variant) { let suffix = ""; if (variant !== defaultBuildingVariant) { @@ -87,6 +109,10 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding { } } + /** + * @param {number} rotationVariant + * @param {string} variant + */ getBlueprintSprite(rotationVariant, variant) { let suffix = ""; if (variant !== defaultBuildingVariant) { @@ -103,6 +129,14 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding { } } + /** + * @param {number} rotationVariant + * @param {string} variant + */ + getSprite(rotationVariant, variant) { + return this.getPreviewSprite(rotationVariant, variant); + } + /** * @param {GameRoot} root */ @@ -137,7 +171,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding { * @param {Vector} param0.tile * @param {number} param0.rotation * @param {string} param0.variant - * @param {string} param0.layer + * @param {Layer} param0.layer * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array }} */ computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { @@ -156,7 +190,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding { tile = tile.addScalars(searchVector.x, searchVector.y); /* WIRES: FIXME */ - const contents = root.map.getTileContent(tile, enumLayer.regular); + const contents = root.map.getTileContent(tile, "regular"); if (contents) { const undergroundComp = contents.components.UndergroundBelt; if (undergroundComp && undergroundComp.tier === tier) { @@ -201,10 +235,6 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding { */ updateVariants(entity, rotationVariant, variant) { entity.components.UndergroundBelt.tier = enumUndergroundBeltVariantToTier[variant]; - entity.components.StaticMapEntity.spriteKey = this.getPreviewSprite( - rotationVariant, - variant - ).spriteName; switch (arrayUndergroundRotationVariantToMode[rotationVariant]) { case enumUndergroundBeltMode.sender: { diff --git a/src/js/game/buildings/virtual_processor.js b/src/js/game/buildings/virtual_processor.js new file mode 100644 index 00000000..dba8978a --- /dev/null +++ b/src/js/game/buildings/virtual_processor.js @@ -0,0 +1,151 @@ +import { Vector, enumDirection } from "../../core/vector"; +import { LogicGateComponent, enumLogicGateType } from "../components/logic_gate"; +import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; + +/** @enum {string} */ +export const enumVirtualProcessorVariants = { + analyzer: "analyzer", + rotater: "rotater", + unstacker: "unstacker", + shapecompare: "shapecompare", +}; + +/** @enum {string} */ +export const enumVariantToGate = { + [defaultBuildingVariant]: enumLogicGateType.cutter, + [enumVirtualProcessorVariants.analyzer]: enumLogicGateType.analyzer, + [enumVirtualProcessorVariants.rotater]: enumLogicGateType.rotater, + [enumVirtualProcessorVariants.unstacker]: enumLogicGateType.unstacker, + [enumVirtualProcessorVariants.shapecompare]: enumLogicGateType.shapecompare, +}; + +export class MetaVirtualProcessorBuilding extends MetaBuilding { + constructor() { + super("virtual_processor"); + } + + getSilhouetteColor() { + return "#823cab"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getDimensions() { + return new Vector(1, 1); + } + + getAvailableVariants() { + return [ + defaultBuildingVariant, + enumVirtualProcessorVariants.rotater, + enumVirtualProcessorVariants.unstacker, + enumVirtualProcessorVariants.analyzer, + enumVirtualProcessorVariants.shapecompare, + ]; + } + + getRenderPins() { + // We already have it included + return false; + } + + /** + * + * @param {Entity} entity + * @param {number} rotationVariant + */ + updateVariants(entity, rotationVariant, variant) { + const gateType = enumVariantToGate[variant]; + entity.components.LogicGate.type = gateType; + const pinComp = entity.components.WiredPins; + switch (gateType) { + case enumLogicGateType.cutter: + case enumLogicGateType.analyzer: + case enumLogicGateType.unstacker: { + pinComp.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.left, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.right, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + ]); + break; + } + case enumLogicGateType.rotater: { + pinComp.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + ]); + break; + } + case enumLogicGateType.shapecompare: { + pinComp.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.left, + type: enumPinSlotType.logicalAcceptor, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.right, + type: enumPinSlotType.logicalAcceptor, + }, + ]); + break; + } + default: + assertAlways("unknown logic gate type: " + gateType); + } + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new WiredPinsComponent({ + slots: [], + }) + ); + + entity.addComponent(new LogicGateComponent({})); + } +} diff --git a/src/js/game/buildings/wire.js b/src/js/game/buildings/wire.js new file mode 100644 index 00000000..59c9cb7d --- /dev/null +++ b/src/js/game/buildings/wire.js @@ -0,0 +1,263 @@ +import { Loader } from "../../core/loader"; +import { generateMatrixRotations } from "../../core/utils"; +import { enumDirection, enumDirectionToAngle, enumDirectionToVector, Vector } from "../../core/vector"; +import { SOUNDS } from "../../platform/sound"; +import { enumWireType, WireComponent } from "../components/wire"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; + +export const arrayWireRotationVariantToType = [ + enumWireType.regular, + enumWireType.turn, + enumWireType.split, + enumWireType.cross, +]; + +export const wireOverlayMatrices = { + [enumWireType.regular]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]), + [enumWireType.split]: generateMatrixRotations([0, 0, 0, 1, 1, 1, 0, 1, 0]), + [enumWireType.turn]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]), + [enumWireType.cross]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]), +}; + +export class MetaWireBuilding extends MetaBuilding { + constructor() { + super("wire"); + } + + getHasDirectionLockAvailable() { + return true; + } + + getSilhouetteColor() { + return "#25fff2"; + } + + getDimensions() { + return new Vector(1, 1); + } + + getStayInPlacementMode() { + return true; + } + + getPlacementSound() { + return SOUNDS.placeBelt; + } + + getRotateAutomaticallyWhilePlacing() { + return true; + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getSprite() { + return null; + } + + getIsReplaceable() { + return true; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + // @todo + entity.addComponent(new WireComponent({})); + } + + /** + * + * @param {Entity} entity + * @param {number} rotationVariant + */ + updateVariants(entity, rotationVariant) { + entity.components.Wire.type = arrayWireRotationVariantToType[rotationVariant]; + } + + /** + * + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return wireOverlayMatrices[entity.components.Wire.type][rotation]; + } + + getPreviewSprite(rotationVariant) { + switch (arrayWireRotationVariantToType[rotationVariant]) { + case enumWireType.regular: { + return Loader.getSprite("sprites/buildings/wire.png"); + } + case enumWireType.turn: { + return Loader.getSprite("sprites/buildings/wire-turn.png"); + } + case enumWireType.split: { + return Loader.getSprite("sprites/buildings/wire-split.png"); + } + case enumWireType.cross: { + return Loader.getSprite("sprites/buildings/wire-cross.png"); + } + default: { + assertAlways(false, "Invalid wire rotation variant"); + } + } + } + + getBlueprintSprite(rotationVariant) { + switch (arrayWireRotationVariantToType[rotationVariant]) { + case enumWireType.regular: { + return Loader.getSprite("sprites/blueprints/wire.png"); + } + case enumWireType.turn: { + return Loader.getSprite("sprites/blueprints/wire-turn.png"); + } + case enumWireType.split: { + return Loader.getSprite("sprites/blueprints/wire-split.png"); + } + case enumWireType.cross: { + return Loader.getSprite("sprites/blueprints/wire-cross.png"); + } + default: { + assertAlways(false, "Invalid wire rotation variant"); + } + } + } + + /** + * Should compute the optimal rotation variant on the given tile + * @param {object} param0 + * @param {GameRoot} param0.root + * @param {Vector} param0.tile + * @param {number} param0.rotation + * @param {string} param0.variant + * @param {string} param0.layer + * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array }} + */ + computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { + const connections = { + top: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.top }), + right: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.right }), + bottom: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.bottom }), + left: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.left }), + }; + + let flag = 0; + flag |= connections.top ? 0x1000 : 0; + flag |= connections.right ? 0x100 : 0; + flag |= connections.bottom ? 0x10 : 0; + flag |= connections.left ? 0x1 : 0; + + let targetType = enumWireType.regular; + + // First, reset rotation + rotation = 0; + + switch (flag) { + case 0x0000: + // Nothing + break; + + case 0x0001: + // Left + rotation += 90; + break; + + case 0x0010: + // Bottom + // END + break; + + case 0x0011: + // Bottom | Left + targetType = enumWireType.turn; + rotation += 90; + break; + + case 0x0100: + // Right + rotation += 90; + break; + + case 0x0101: + // Right | Left + rotation += 90; + break; + + case 0x0110: + // Right | Bottom + targetType = enumWireType.turn; + break; + + case 0x0111: + // Right | Bottom | Left + targetType = enumWireType.split; + break; + + case 0x1000: + // Top + break; + + case 0x1001: + // Top | Left + targetType = enumWireType.turn; + rotation += 180; + break; + + case 0x1010: + // Top | Bottom + break; + + case 0x1011: + // Top | Bottom | Left + targetType = enumWireType.split; + rotation += 90; + break; + + case 0x1100: + // Top | Right + targetType = enumWireType.turn; + rotation -= 90; + break; + + case 0x1101: + // Top | Right | Left + targetType = enumWireType.split; + rotation += 180; + break; + + case 0x1110: + // Top | Right | Bottom + targetType = enumWireType.split; + rotation -= 90; + break; + + case 0x1111: + // Top | Right | Bottom | Left + targetType = enumWireType.cross; + break; + } + + return { + // Clamp rotation + rotation: (rotation + 360 * 10) % 360, + rotationVariant: arrayWireRotationVariantToType.indexOf(targetType), + }; + } +} diff --git a/src/js/game/buildings/wire_base.js b/src/js/game/buildings/wire_base.js deleted file mode 100644 index 6f3ffec8..00000000 --- a/src/js/game/buildings/wire_base.js +++ /dev/null @@ -1,52 +0,0 @@ -import { Loader } from "../../core/loader"; -import { enumDirection } from "../../core/vector"; -import { enumLayer } from "../root"; -import { arrayBeltVariantToRotation, MetaBeltBaseBuilding } from "./belt_base"; - -export class MetaWireBaseBuilding extends MetaBeltBaseBuilding { - constructor() { - super("wire"); - } - - getSilhouetteColor() { - return "#c425d7"; - } - - getLayer() { - return enumLayer.wires; - } - - getPreviewSprite(rotationVariant) { - switch (arrayBeltVariantToRotation[rotationVariant]) { - case enumDirection.top: { - return Loader.getSprite("sprites/buildings/wire_top.png"); - } - case enumDirection.left: { - return Loader.getSprite("sprites/buildings/wire_left.png"); - } - case enumDirection.right: { - return Loader.getSprite("sprites/buildings/wire_right.png"); - } - default: { - assertAlways(false, "Invalid belt rotation variant"); - } - } - } - - getBlueprintSprite(rotationVariant) { - switch (arrayBeltVariantToRotation[rotationVariant]) { - case enumDirection.top: { - return Loader.getSprite("sprites/blueprints/wire_top.png"); - } - case enumDirection.left: { - return Loader.getSprite("sprites/blueprints/wire_left.png"); - } - case enumDirection.right: { - return Loader.getSprite("sprites/blueprints/wire_right.png"); - } - default: { - assertAlways(false, "Invalid belt rotation variant"); - } - } - } -} diff --git a/src/js/game/buildings/wire_crossings.js b/src/js/game/buildings/wire_crossings.js deleted file mode 100644 index 111d7ce4..00000000 --- a/src/js/game/buildings/wire_crossings.js +++ /dev/null @@ -1,120 +0,0 @@ -import { enumDirection, Vector } from "../../core/vector"; -import { enumItemType } from "../base_item"; -import { ItemAcceptorComponent } from "../components/item_acceptor"; -import { ItemEjectorComponent } from "../components/item_ejector"; -import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; -import { Entity } from "../entity"; -import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; -import { enumLayer, GameRoot } from "../root"; - -/** @enum {string} */ -export const enumWireCrossingVariants = { - // Default = splitter - merger: "merger", -}; - -export class MetaWireCrossingsBuilding extends MetaBuilding { - constructor() { - super("wire_crossings"); - } - - getDimensions(variant) { - return new Vector(1, 1); - } - - getSilhouetteColor() { - return "#c425d7"; - } - - getLayer() { - return enumLayer.wires; - } - - /** - * @param {GameRoot} root - */ - getAvailableVariants(root) { - return [defaultBuildingVariant, enumWireCrossingVariants.merger]; - } - - /** - * @param {GameRoot} root - */ - getIsUnlocked(root) { - return true; - } - - /** - * Creates the entity at the given location - * @param {Entity} entity - */ - setupEntityComponents(entity) { - entity.addComponent( - new ItemAcceptorComponent({ - slots: [], // set later - }) - ); - - entity.addComponent( - new ItemProcessorComponent({ - inputsPerCharge: 1, - processorType: enumItemProcessorTypes.splitterWires, - }) - ); - - entity.addComponent( - new ItemEjectorComponent({ - slots: [], // set later - instantEject: true, - }) - ); - } - - /** - * - * @param {Entity} entity - * @param {number} rotationVariant - * @param {string} variant - */ - updateVariants(entity, rotationVariant, variant) { - switch (variant) { - case defaultBuildingVariant: { - entity.components.ItemAcceptor.setSlots([ - { - pos: new Vector(0, 0), - directions: [enumDirection.bottom], - layer: enumLayer.wires, - }, - ]); - - entity.components.ItemEjector.setSlots([ - { pos: new Vector(0, 0), direction: enumDirection.left, layer: enumLayer.wires }, - { pos: new Vector(0, 0), direction: enumDirection.right, layer: enumLayer.wires }, - ]); - - break; - } - case enumWireCrossingVariants.merger: { - entity.components.ItemAcceptor.setSlots([ - { - pos: new Vector(0, 0), - directions: [enumDirection.left], - layer: enumLayer.wires, - }, - { - pos: new Vector(0, 0), - directions: [enumDirection.right], - layer: enumLayer.wires, - }, - ]); - - entity.components.ItemEjector.setSlots([ - { pos: new Vector(0, 0), direction: enumDirection.top, layer: enumLayer.wires }, - ]); - break; - } - default: - assertAlways(false, "Unknown painter variant: " + variant); - } - } -} diff --git a/src/js/game/buildings/wire_tunnel.js b/src/js/game/buildings/wire_tunnel.js new file mode 100644 index 00000000..f885abc6 --- /dev/null +++ b/src/js/game/buildings/wire_tunnel.js @@ -0,0 +1,87 @@ +import { Vector } from "../../core/vector"; +import { Entity } from "../entity"; +import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; +import { GameRoot } from "../root"; +import { WireTunnelComponent } from "../components/wire_tunnel"; +import { generateMatrixRotations } from "../../core/utils"; + +/** @enum {string} */ +export const enumWireTunnelVariants = { + coating: "coating", +}; + +const wireTunnelOverlayMatrices = { + [defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]), + [enumWireTunnelVariants.coating]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]), +}; + +export class MetaWireTunnelBuilding extends MetaBuilding { + constructor() { + super("wire_tunnel"); + } + + getSilhouetteColor() { + return "#777a86"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + /** + * + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return wireTunnelOverlayMatrices[variant][rotation]; + } + + getIsRotateable(variant) { + return variant !== defaultBuildingVariant; + } + + getDimensions() { + return new Vector(1, 1); + } + + getAvailableVariants() { + return [defaultBuildingVariant, enumWireTunnelVariants.coating]; + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getRotateAutomaticallyWhilePlacing() { + return true; + } + + getStayInPlacementMode() { + return true; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent(new WireTunnelComponent({})); + } + + /** + * @param {Entity} entity + * @param {number} rotationVariant + * @param {string} variant + */ + updateVariants(entity, rotationVariant, variant) { + entity.components.WireTunnel.multipleDirections = variant === defaultBuildingVariant; + } +} diff --git a/src/js/game/colors.js b/src/js/game/colors.js index 9c7d0d2d..e7219175 100644 --- a/src/js/game/colors.js +++ b/src/js/game/colors.js @@ -10,8 +10,6 @@ export const enumColors = { white: "white", uncolored: "uncolored", - - black: "black", }; /** @enum {string} */ @@ -26,8 +24,6 @@ export const enumColorToShortcode = { [enumColors.white]: "w", [enumColors.uncolored]: "u", - - [enumColors.black]: "0", }; /** @enum {enumColors} */ @@ -54,27 +50,9 @@ export const enumColorsToHexCode = { // blue + green + red [enumColors.white]: "#ffffff", - [enumColors.black]: "#31383a", - [enumColors.uncolored]: "#aaaaaa", }; -/** @enum {enumColors} */ -export const enumInvertedColors = { - [enumColors.red]: enumColors.cyan, - [enumColors.green]: enumColors.purple, - [enumColors.blue]: enumColors.yellow, - - [enumColors.yellow]: enumColors.blue, - [enumColors.purple]: enumColors.green, - [enumColors.cyan]: enumColors.red, - - [enumColors.white]: enumColors.black, - [enumColors.black]: enumColors.white, - - [enumColors.uncolored]: enumColors.uncolored, -}; - const c = enumColors; /** @enum {Object.} */ export const enumColorMixingResults = { @@ -88,7 +66,6 @@ export const enumColorMixingResults = { [c.cyan]: c.white, [c.white]: c.white, - [c.black]: c.red, }, // 0, 255, 0 @@ -100,7 +77,6 @@ export const enumColorMixingResults = { [c.cyan]: c.cyan, [c.white]: c.white, - [c.black]: c.green, }, // 0, 255, 0 @@ -110,20 +86,17 @@ export const enumColorMixingResults = { [c.cyan]: c.cyan, [c.white]: c.white, - [c.black]: c.blue, }, // 255, 255, 0 [c.yellow]: { [c.purple]: c.white, [c.cyan]: c.white, - [c.black]: c.yellow, }, // 255, 0, 255 [c.purple]: { [c.cyan]: c.white, - [c.black]: c.purple, }, // 0, 255, 255 @@ -140,24 +113,12 @@ export const enumColorMixingResults = { [c.uncolored]: { // auto }, - - [c.black]: { - // auto - [c.white]: c.uncolored, - [c.cyan]: c.cyan, - [c.uncolored]: c.uncolored, - }, }; // Create same color lookups for (const color in enumColors) { enumColorMixingResults[color][color] = color; - - // Anything with white is white again, except for black which creates gray - if (color !== enumColors.black) { - enumColorMixingResults[color][c.white] = c.white; - } - + enumColorMixingResults[color][c.white] = c.white; // Anything with uncolored is the same color enumColorMixingResults[color][c.uncolored] = color; } diff --git a/src/js/game/component.js b/src/js/game/component.js index 1d44d60f..7d30faff 100644 --- a/src/js/game/component.js +++ b/src/js/game/component.js @@ -44,3 +44,9 @@ export class Component extends BasicSerializableObject { } /* dev:end */ } + +/** + * TypeScript does not support Abstract Static methods (https://github.com/microsoft/TypeScript/issues/34516) + * One workaround is to declare the type of the component and reference that for static methods + * @typedef {typeof Component} StaticComponent + */ diff --git a/src/js/game/component_registry.js b/src/js/game/component_registry.js index d3398937..b03c164f 100644 --- a/src/js/game/component_registry.js +++ b/src/js/game/component_registry.js @@ -5,14 +5,18 @@ import { ItemEjectorComponent } from "./components/item_ejector"; import { ItemAcceptorComponent } from "./components/item_acceptor"; import { MinerComponent } from "./components/miner"; import { ItemProcessorComponent } from "./components/item_processor"; -import { ReplaceableMapEntityComponent } from "./components/replaceable_map_entity"; import { UndergroundBeltComponent } from "./components/underground_belt"; -import { UnremovableComponent } from "./components/unremovable"; import { HubComponent } from "./components/hub"; import { StorageComponent } from "./components/storage"; -import { EnergyGeneratorComponent } from "./components/energy_generator"; import { WiredPinsComponent } from "./components/wired_pins"; -import { EnergyConsumerComponent } from "./components/energy_consumer"; +import { BeltUnderlaysComponent } from "./components/belt_underlays"; +import { WireComponent } from "./components/wire"; +import { ConstantSignalComponent } from "./components/constant_signal"; +import { LogicGateComponent } from "./components/logic_gate"; +import { LeverComponent } from "./components/lever"; +import { WireTunnelComponent } from "./components/wire_tunnel"; +import { DisplayComponent } from "./components/display"; +import { BeltReaderComponent } from "./components/belt_reader"; export function initComponentRegistry() { gComponentRegistry.register(StaticMapEntityComponent); @@ -21,14 +25,18 @@ export function initComponentRegistry() { gComponentRegistry.register(ItemAcceptorComponent); gComponentRegistry.register(MinerComponent); gComponentRegistry.register(ItemProcessorComponent); - gComponentRegistry.register(ReplaceableMapEntityComponent); gComponentRegistry.register(UndergroundBeltComponent); - gComponentRegistry.register(UnremovableComponent); gComponentRegistry.register(HubComponent); gComponentRegistry.register(StorageComponent); - gComponentRegistry.register(EnergyGeneratorComponent); gComponentRegistry.register(WiredPinsComponent); - gComponentRegistry.register(EnergyConsumerComponent); + gComponentRegistry.register(BeltUnderlaysComponent); + gComponentRegistry.register(WireComponent); + gComponentRegistry.register(ConstantSignalComponent); + gComponentRegistry.register(LogicGateComponent); + gComponentRegistry.register(LeverComponent); + gComponentRegistry.register(WireTunnelComponent); + gComponentRegistry.register(DisplayComponent); + gComponentRegistry.register(BeltReaderComponent); // IMPORTANT ^^^^^ UPDATE ENTITY COMPONENT STORAGE AFTERWARDS diff --git a/src/js/game/components/belt.js b/src/js/game/components/belt.js index e9a0cd80..02197822 100644 --- a/src/js/game/components/belt.js +++ b/src/js/game/components/belt.js @@ -2,23 +2,44 @@ import { enumDirection, Vector } from "../../core/vector"; import { types } from "../../savegame/serialization"; import { BeltPath } from "../belt_path"; import { Component } from "../component"; -import { Entity } from "../entity"; -import { enumLayer } from "../root"; export const curvedBeltLength = /* Math.PI / 4 */ 0.78; +/** @type {import("./item_acceptor").ItemAcceptorSlot} */ +export const FAKE_BELT_ACCEPTOR_SLOT = { + pos: new Vector(0, 0), + directions: [enumDirection.bottom], +}; + +/** @type {Object} */ +export const FAKE_BELT_EJECTOR_SLOT_BY_DIRECTION = { + [enumDirection.top]: { + pos: new Vector(0, 0), + direction: enumDirection.top, + item: null, + progress: 0, + }, + + [enumDirection.right]: { + pos: new Vector(0, 0), + direction: enumDirection.right, + item: null, + progress: 0, + }, + + [enumDirection.left]: { + pos: new Vector(0, 0), + direction: enumDirection.left, + item: null, + progress: 0, + }, +}; + export class BeltComponent extends Component { static getId() { return "Belt"; } - static getSchema() { - // The followUpCache field is not serialized. - return { - direction: types.string, - }; - } - duplicateWithoutContents() { return new BeltComponent({ direction: this.direction }); } @@ -33,9 +54,6 @@ export class BeltComponent extends Component { this.direction = direction; - /** @type {Entity} */ - this.followUpCache = null; - /** * The path this belt is contained in, not serialized * @type {BeltPath} @@ -45,77 +63,59 @@ export class BeltComponent extends Component { /** * Returns the effective length of this belt in tile space - * @param {enumLayer} layer * @returns {number} */ - getEffectiveLengthTiles(layer) { - assert(layer, "no layer given"); - if (layer === enumLayer.wires) { - return 1.0; - } + getEffectiveLengthTiles() { return this.direction === enumDirection.top ? 1.0 : curvedBeltLength; } + /** + * Returns fake acceptor slot used for matching + * @returns {import("./item_acceptor").ItemAcceptorSlot} + */ + getFakeAcceptorSlot() { + return FAKE_BELT_ACCEPTOR_SLOT; + } + + /** + * Returns fake acceptor slot used for matching + * @returns {import("./item_ejector").ItemEjectorSlot} + */ + getFakeEjectorSlot() { + assert( + FAKE_BELT_EJECTOR_SLOT_BY_DIRECTION[this.direction], + "Invalid belt direction: ", + this.direction + ); + return FAKE_BELT_EJECTOR_SLOT_BY_DIRECTION[this.direction]; + } + /** * Converts from belt space (0 = start of belt ... 1 = end of belt) to the local * belt coordinates (-0.5|-0.5 to 0.5|0.5) * @param {number} progress - * @param {enumLayer} layer * @returns {Vector} */ - transformBeltToLocalSpace(progress, layer) { + transformBeltToLocalSpace(progress) { assert(progress >= 0.0, "Invalid progress ( < 0): " + progress); + switch (this.direction) { + case enumDirection.top: + assert(progress <= 1.02, "Invalid progress: " + progress); + return new Vector(0, 0.5 - progress); - switch (layer) { - case enumLayer.regular: { - switch (this.direction) { - case enumDirection.top: - assert(progress <= 1.02, "Invalid progress: " + progress); - return new Vector(0, 0.5 - progress); - - case enumDirection.right: { - assert(progress <= curvedBeltLength + 0.02, "Invalid progress 2: " + progress); - const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI; - return new Vector( - 0.5 - 0.5 * Math.cos(arcProgress), - 0.5 - 0.5 * Math.sin(arcProgress) - ); - } - case enumDirection.left: { - assert(progress <= curvedBeltLength + 0.02, "Invalid progress 3: " + progress); - const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI; - return new Vector( - -0.5 + 0.5 * Math.cos(arcProgress), - 0.5 - 0.5 * Math.sin(arcProgress) - ); - } - default: - assertAlways(false, "Invalid belt direction: " + this.direction); - return new Vector(0, 0); - } + case enumDirection.right: { + assert(progress <= curvedBeltLength + 0.02, "Invalid progress 2: " + progress); + const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI; + return new Vector(0.5 - 0.5 * Math.cos(arcProgress), 0.5 - 0.5 * Math.sin(arcProgress)); } - case enumLayer.wires: { - const pow = 0.5; - switch (this.direction) { - case enumDirection.top: - assert(progress <= 1.02, "Invalid progress: " + progress); - return new Vector(0, 0.5 - progress); - - case enumDirection.right: { - assert(progress <= 1.02, "Invalid progress 2: " + progress); - return progress > 0.5 ? new Vector(progress - 0.5, 0) : new Vector(0, 0.5 - progress); - } - case enumDirection.left: { - assert(progress <= 1.02, "Invalid progress 3: " + progress); - return progress > 0.5 - ? new Vector(-progress + 0.5, 0) - : new Vector(0, 0.5 - progress); - } - default: - assertAlways(false, "Invalid belt direction: " + this.direction); - return new Vector(0, 0); - } + case enumDirection.left: { + assert(progress <= curvedBeltLength + 0.02, "Invalid progress 3: " + progress); + const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI; + return new Vector(-0.5 + 0.5 * Math.cos(arcProgress), 0.5 - 0.5 * Math.sin(arcProgress)); } + default: + assertAlways(false, "Invalid belt direction: " + this.direction); + return new Vector(0, 0); } } } diff --git a/src/js/game/components/belt_reader.js b/src/js/game/components/belt_reader.js new file mode 100644 index 00000000..d59feb9c --- /dev/null +++ b/src/js/game/components/belt_reader.js @@ -0,0 +1,48 @@ +import { Component } from "../component"; +import { BaseItem } from "../base_item"; +import { typeItemSingleton } from "../item_resolver"; +import { types } from "../../savegame/serialization"; + +export class BeltReaderComponent extends Component { + static getId() { + return "BeltReader"; + } + + duplicateWithoutContents() { + return new BeltReaderComponent(); + } + + static getSchema() { + return { + lastItem: types.nullable(typeItemSingleton), + }; + } + + constructor() { + super(); + + /** + * Which items went through the reader, we only store the time + * @type {Array} + */ + this.lastItemTimes = []; + + /** + * Which item passed the reader last + * @type {BaseItem} + */ + this.lastItem = null; + + /** + * Stores the last throughput we computed + * @type {number} + */ + this.lastThroughput = 0; + + /** + * Stores when we last computed the throughput + * @type {number} + */ + this.lastThroughputComputation = 0; + } +} diff --git a/src/js/game/components/belt_underlays.js b/src/js/game/components/belt_underlays.js new file mode 100644 index 00000000..cb516b1a --- /dev/null +++ b/src/js/game/components/belt_underlays.js @@ -0,0 +1,33 @@ +import { Component } from "../component"; +import { types } from "../../savegame/serialization"; +import { enumDirection, Vector } from "../../core/vector"; + +export class BeltUnderlaysComponent extends Component { + static getId() { + return "BeltUnderlays"; + } + + duplicateWithoutContents() { + const beltUnderlaysCopy = []; + for (let i = 0; i < this.underlays.length; ++i) { + const underlay = this.underlays[i]; + beltUnderlaysCopy.push({ + pos: underlay.pos.copy(), + direction: underlay.direction, + }); + } + + return new BeltUnderlaysComponent({ + underlays: beltUnderlaysCopy, + }); + } + + /** + * @param {object} param0 + * @param {Array<{pos: Vector, direction: enumDirection}>=} param0.underlays Where to render belt underlays + */ + constructor({ underlays }) { + super(); + this.underlays = underlays; + } +} diff --git a/src/js/game/components/constant_signal.js b/src/js/game/components/constant_signal.js new file mode 100644 index 00000000..b51277a1 --- /dev/null +++ b/src/js/game/components/constant_signal.js @@ -0,0 +1,31 @@ +import { gItemRegistry } from "../../core/global_registries"; +import { types } from "../../savegame/serialization"; +import { Component } from "../component"; +import { BaseItem } from "../base_item"; +import { typeItemSingleton } from "../item_resolver"; + +export class ConstantSignalComponent extends Component { + static getId() { + return "ConstantSignal"; + } + + static getSchema() { + return { + signal: types.nullable(typeItemSingleton), + }; + } + + duplicateWithoutContents() { + return new ConstantSignalComponent({ signal: this.signal }); + } + + /** + * + * @param {object} param0 + * @param {BaseItem=} param0.signal The signal to store + */ + constructor({ signal = null }) { + super(); + this.signal = signal; + } +} diff --git a/src/js/game/components/display.js b/src/js/game/components/display.js new file mode 100644 index 00000000..720bf8c7 --- /dev/null +++ b/src/js/game/components/display.js @@ -0,0 +1,11 @@ +import { Component } from "../component"; + +export class DisplayComponent extends Component { + static getId() { + return "Display"; + } + + duplicateWithoutContents() { + return new DisplayComponent(); + } +} diff --git a/src/js/game/components/energy_consumer.js b/src/js/game/components/energy_consumer.js deleted file mode 100644 index 6e54af86..00000000 --- a/src/js/game/components/energy_consumer.js +++ /dev/null @@ -1,133 +0,0 @@ -import { Component } from "../component"; -import { types } from "../../savegame/serialization"; -import { Vector } from "../../core/vector"; -import { BaseItem, enumItemTypeToLayer, enumItemType } from "../base_item"; - -export class EnergyConsumerComponent extends Component { - static getId() { - return "EnergyConsumer"; - } - - static getSchema() { - return { - bufferSize: types.float, - perCharge: types.float, - batteryPosition: types.vector, - energyType: types.enum(enumItemType), - wasteType: types.enum(enumItemType), - acceptorSlotIndex: types.uint, - ejectorSlotIndex: types.uint, - - stored: types.float, - piledOutput: types.float, - }; - } - - duplicateWithoutContents() { - return new EnergyConsumerComponent({ - bufferSize: this.bufferSize, - perCharge: this.perCharge, - batteryPosition: this.batteryPosition.copy(), - acceptorSlotIndex: this.acceptorSlotIndex, - ejectorSlotIndex: this.ejectorSlotIndex, - }); - } - - /** - * - * @param {object} param0 - * @param {number} param0.bufferSize How much energy this consumer can store - * @param {number} param0.perCharge How much energy this consumer needs per charge - * @param {Vector} param0.batteryPosition world space render offset of the battery icon - * @param {number} param0.acceptorSlotIndex Which slot to accept energy on - * @param {number} param0.ejectorSlotIndex Which slot to eject energy off - * - */ - constructor({ - bufferSize = 3, - perCharge = 1, - batteryPosition = new Vector(), - acceptorSlotIndex = 0, - ejectorSlotIndex = 0, - }) { - super(); - this.bufferSize = bufferSize; - this.perCharge = perCharge; - this.batteryPosition = batteryPosition; - this.energyType = enumItemType.positiveEnergy; - this.wasteType = enumItemType.negativeEnergy; - this.acceptorSlotIndex = acceptorSlotIndex; - this.ejectorSlotIndex = ejectorSlotIndex; - - /** - * How much energy we have stored right now - */ - this.stored = 0; - - /** - * How much waste we have piled up so far - */ - this.piledOutput = 0; - } - - /** - * Tries to accept a given item - * @param {BaseItem} item - * @param {number} slotIndex - */ - tryAcceptItem(item, slotIndex) { - if (slotIndex !== this.acceptorSlotIndex) { - // Wrong slot - return false; - } - - if (item.getItemType() !== this.energyType) { - // Not the right type - return false; - } - - if (this.stored >= this.bufferSize) { - // We are full - return false; - } - - // All good, consume - this.stored = Math.min(this.stored + 1, this.bufferSize); - - return true; - } - - /** - * Tries to start the next charge - */ - tryStartNextCharge() { - if (this.hasTooMuchWastePiled()) { - // Too much waste remaining - return false; - } - - if (this.stored < this.perCharge) { - // Not enough energy stored - return false; - } - - this.stored -= this.perCharge; - this.piledOutput += this.perCharge; - return true; - } - - /** - * Returns if there is too much waste piled - */ - hasTooMuchWastePiled() { - return this.piledOutput >= 1.0; - } - - /** - * Reduces the waste by the given amount - * @param {number} amount - */ - reduceWaste(amount) { - this.piledOutput = Math.max(0, this.piledOutput - amount); - } -} diff --git a/src/js/game/components/energy_generator.js b/src/js/game/components/energy_generator.js deleted file mode 100644 index a45492d7..00000000 --- a/src/js/game/components/energy_generator.js +++ /dev/null @@ -1,93 +0,0 @@ -import { types } from "../../savegame/serialization"; -import { BaseItem, enumItemType } from "../base_item"; -import { Component } from "../component"; -import { ShapeItem } from "../items/shape_item"; - -const maxQueueSize = 4; - -export class EnergyGeneratorComponent extends Component { - static getId() { - return "EnergyGenerator"; - } - - static getSchema() { - return { - requiredKey: types.nullable(types.string), - itemsInQueue: types.uint, - wasteAcceptorSlotIndex: types.uint, - }; - } - - duplicateWithoutContents() { - return new EnergyGeneratorComponent({ - requiredKey: null, - wasteAcceptorSlotIndex: this.wasteAcceptorSlotIndex, - }); - } - - /** - * - * @param {object} param0 - * @param {string=} param0.requiredKey Which shape this generator needs, can be null if not computed yet - * @param {number} param0.wasteAcceptorSlotIndex Which slot accepts the waste - */ - constructor({ requiredKey, wasteAcceptorSlotIndex = 0 }) { - super(); - this.requiredKey = requiredKey; - - /** - * Stores how many items are ready to be converted to energy - * @type {number} - */ - this.itemsInQueue = 0; - - /** - * Stores which slot accepts the waste - * @type {number} - */ - this.wasteAcceptorSlotIndex = wasteAcceptorSlotIndex; - } - - /** - * - * @param {BaseItem} item - * @param {number} slot - */ - tryTakeItem(item, slot) { - if (slot === this.wasteAcceptorSlotIndex) { - // this is the acceptor slot on the wires layer - // just destroy it - return true; - } else { - if (item.getItemType() !== enumItemType.shape) { - // This shouldn't happen since we have a filter - still, it doesn't hurt - // to check either - assertAlways( - false, - "Energy generator took wrong item: " + - item.getItemType() + - " on slot " + - slot + - " (waste slot = " + - this.wasteAcceptorSlotIndex + - ")" - ); - return false; - } - - if (/** @type {ShapeItem} */ (item).definition.getHash() !== this.requiredKey) { - // Not our shape - return false; - } - - if (this.itemsInQueue >= maxQueueSize) { - // Queue is full - return false; - } - - // Take item and put it into the queue - ++this.itemsInQueue; - return true; - } - } -} diff --git a/src/js/game/components/hub.js b/src/js/game/components/hub.js index f9c13dc3..fb88d6f6 100644 --- a/src/js/game/components/hub.js +++ b/src/js/game/components/hub.js @@ -1,32 +1,7 @@ import { Component } from "../component"; -import { ShapeDefinition } from "../shape_definition"; -import { types } from "../../savegame/serialization"; export class HubComponent extends Component { static getId() { return "Hub"; } - - static getSchema() { - return { - definitionsToAnalyze: types.array(types.knownType(ShapeDefinition)), - }; - } - - constructor() { - super(); - - /** - * Shape definitions in queue to be analyzed and counted towards the goal - * @type {Array} - */ - this.definitionsToAnalyze = []; - } - - /** - * @param {ShapeDefinition} definition - */ - queueShapeDefinition(definition) { - this.definitionsToAnalyze.push(definition); - } } diff --git a/src/js/game/components/item_acceptor.js b/src/js/game/components/item_acceptor.js index a5676119..3885eb1f 100644 --- a/src/js/game/components/item_acceptor.js +++ b/src/js/game/components/item_acceptor.js @@ -1,219 +1,150 @@ -import { enumDirection, enumInvertedDirections, Vector } from "../../core/vector"; -import { types } from "../../savegame/serialization"; -import { BaseItem, enumItemType } from "../base_item"; -import { Component } from "../component"; -import { enumLayer } from "../root"; - -/** @typedef {{ - * pos: Vector, - * directions: enumDirection[], - * layer: enumLayer, - * filter?: enumItemType - * }} ItemAcceptorSlot */ - -/** - * Contains information about a slot plus its location - * @typedef {{ - * slot: ItemAcceptorSlot, - * index: number, - * acceptedDirection: enumDirection - * }} ItemAcceptorLocatedSlot */ - -/** @typedef {{ - * pos: Vector, - * directions: enumDirection[], - * layer?: enumLayer, - * filter?: enumItemType - * }} ItemAcceptorSlotConfig */ - -export class ItemAcceptorComponent extends Component { - static getId() { - return "ItemAcceptor"; - } - - static getSchema() { - return { - slots: types.array( - types.structured({ - pos: types.vector, - directions: types.array(types.enum(enumDirection)), - filter: types.nullable(types.enum(enumItemType)), - - // TODO: MIGRATE - layer: types.enum(enumLayer), - }) - ), - animated: types.bool, - beltUnderlays: types.array( - types.structured({ - pos: types.vector, - direction: types.enum(enumDirection), - - // TODO: MIGRATE - layer: types.enum(enumLayer), - }) - ), - }; - } - - duplicateWithoutContents() { - const slotsCopy = []; - for (let i = 0; i < this.slots.length; ++i) { - const slot = this.slots[i]; - slotsCopy.push({ - pos: slot.pos.copy(), - directions: slot.directions.slice(), - filter: slot.filter, - layer: slot.layer, - }); - } - - const beltUnderlaysCopy = []; - for (let i = 0; i < this.beltUnderlays.length; ++i) { - const underlay = this.beltUnderlays[i]; - beltUnderlaysCopy.push({ - pos: underlay.pos.copy(), - direction: underlay.direction, - layer: underlay.layer, - }); - } - - return new ItemAcceptorComponent({ - slots: slotsCopy, - beltUnderlays: beltUnderlaysCopy, - animated: this.animated, - }); - } - - /** - * - * @param {object} param0 - * @param {Array} param0.slots The slots from which we accept items - * @param {boolean=} param0.animated Whether to animate item consumption - * @param {Array<{pos: Vector, direction: enumDirection, layer: enumLayer}>=} param0.beltUnderlays Where to render belt underlays - */ - constructor({ slots = [], beltUnderlays = [], animated = true }) { - super(); - - this.animated = animated; - - /** - * Fixes belt animations - * @type {Array<{ item: BaseItem, slotIndex: number, animProgress: number, direction: enumDirection }>} - */ - this.itemConsumptionAnimations = []; - - /* Which belt underlays to render */ - this.beltUnderlays = beltUnderlays; - - this.setSlots(slots); - } - - /** - * - * @param {Array} slots - */ - setSlots(slots) { - /** @type {Array} */ - this.slots = []; - for (let i = 0; i < slots.length; ++i) { - const slot = slots[i]; - this.slots.push({ - pos: slot.pos, - directions: slot.directions, - layer: slot.layer || enumLayer.regular, - - // Which type of item to accept (shape | color | all) @see enumItemType - filter: slot.filter, - }); - } - } - - /** - * Returns if this acceptor can accept a new item at slot N - * @param {number} slotIndex - * @param {BaseItem=} item - */ - canAcceptItem(slotIndex, item) { - const slot = this.slots[slotIndex]; - return this.filterMatches(slot.filter, item); - } - - /** - * Returns if the given filter matches - * @param {enumItemType|null} filter - * @param {BaseItem} item - */ - filterMatches(filter, item) { - if (!filter) { - return true; - } - - const itemType = item.getItemType(); - if (filter === enumItemType.genericEnergy) { - return itemType === enumItemType.positiveEnergy || itemType === enumItemType.negativeEnergy; - } - - return itemType === filter; - } - - /** - * Called when an item has been accepted so that - * @param {number} slotIndex - * @param {enumDirection} direction - * @param {BaseItem} item - */ - onItemAccepted(slotIndex, direction, item) { - if (this.animated) { - this.itemConsumptionAnimations.push({ - item, - slotIndex, - direction, - animProgress: 0.0, - }); - } - } - - /** - * Tries to find a slot which accepts the current item - * @param {Vector} targetLocalTile - * @param {enumDirection} fromLocalDirection - * @param {enumLayer} layer - * @returns {ItemAcceptorLocatedSlot|null} - */ - findMatchingSlot(targetLocalTile, fromLocalDirection, layer) { - // We need to invert our direction since the acceptor specifies *from* which direction - // it accepts items, but the ejector specifies *into* which direction it ejects items. - // E.g.: Ejector ejects into "right" direction but acceptor accepts from "left" direction. - const desiredDirection = enumInvertedDirections[fromLocalDirection]; - - // Go over all slots and try to find a target slot - for (let slotIndex = 0; slotIndex < this.slots.length; ++slotIndex) { - const slot = this.slots[slotIndex]; - - // Make sure the acceptor slot is on the right position - if (!slot.pos.equals(targetLocalTile)) { - continue; - } - - // Make sure the layer matches - if (slot.layer !== layer) { - continue; - } - - // Check if the acceptor slot accepts items from our direction - for (let i = 0; i < slot.directions.length; ++i) { - // const localDirection = targetStaticComp.localDirectionToWorld(slot.directions[l]); - if (desiredDirection === slot.directions[i]) { - return { - slot, - index: slotIndex, - acceptedDirection: desiredDirection, - }; - } - } - } - - return null; - } -} +import { enumDirection, enumInvertedDirections, Vector } from "../../core/vector"; +import { types } from "../../savegame/serialization"; +import { BaseItem } from "../base_item"; +import { Component } from "../component"; + +/** @typedef {{ + * pos: Vector, + * directions: enumDirection[], + * filter?: ItemType + * }} ItemAcceptorSlot */ + +/** + * Contains information about a slot plus its location + * @typedef {{ + * slot: ItemAcceptorSlot, + * index: number, + * acceptedDirection: enumDirection + * }} ItemAcceptorLocatedSlot */ + +/** @typedef {{ + * pos: Vector, + * directions: enumDirection[], + * filter?: ItemType + * }} ItemAcceptorSlotConfig */ + +export class ItemAcceptorComponent extends Component { + static getId() { + return "ItemAcceptor"; + } + + duplicateWithoutContents() { + const slotsCopy = []; + for (let i = 0; i < this.slots.length; ++i) { + const slot = this.slots[i]; + slotsCopy.push({ + pos: slot.pos.copy(), + directions: slot.directions.slice(), + filter: slot.filter, + }); + } + + return new ItemAcceptorComponent({ + slots: slotsCopy, + }); + } + + /** + * + * @param {object} param0 + * @param {Array} param0.slots The slots from which we accept items + */ + constructor({ slots = [] }) { + super(); + + /** + * Fixes belt animations + * @type {Array<{ + * item: BaseItem, + * slotIndex: number, + * animProgress: number, + * direction: enumDirection + * }>} + */ + this.itemConsumptionAnimations = []; + + this.setSlots(slots); + } + + /** + * + * @param {Array} slots + */ + setSlots(slots) { + /** @type {Array} */ + this.slots = []; + for (let i = 0; i < slots.length; ++i) { + const slot = slots[i]; + this.slots.push({ + pos: slot.pos, + directions: slot.directions, + + // Which type of item to accept (shape | color | all) @see ItemType + filter: slot.filter, + }); + } + } + + /** + * Returns if this acceptor can accept a new item at slot N + * @param {number} slotIndex + * @param {BaseItem=} item + */ + canAcceptItem(slotIndex, item) { + const slot = this.slots[slotIndex]; + return !slot.filter || slot.filter === item.getItemType(); + } + + /** + * Called when an item has been accepted so that + * @param {number} slotIndex + * @param {enumDirection} direction + * @param {BaseItem} item + * @param {number} remainingProgress World space remaining progress, can be set to set the start position of the item + */ + onItemAccepted(slotIndex, direction, item, remainingProgress = 0.0) { + this.itemConsumptionAnimations.push({ + item, + slotIndex, + direction, + animProgress: Math.min(1, remainingProgress * 2), + }); + } + + /** + * Tries to find a slot which accepts the current item + * @param {Vector} targetLocalTile + * @param {enumDirection} fromLocalDirection + * @returns {ItemAcceptorLocatedSlot|null} + */ + findMatchingSlot(targetLocalTile, fromLocalDirection) { + // We need to invert our direction since the acceptor specifies *from* which direction + // it accepts items, but the ejector specifies *into* which direction it ejects items. + // E.g.: Ejector ejects into "right" direction but acceptor accepts from "left" direction. + const desiredDirection = enumInvertedDirections[fromLocalDirection]; + + // Go over all slots and try to find a target slot + for (let slotIndex = 0; slotIndex < this.slots.length; ++slotIndex) { + const slot = this.slots[slotIndex]; + + // Make sure the acceptor slot is on the right position + if (!slot.pos.equals(targetLocalTile)) { + continue; + } + + // Check if the acceptor slot accepts items from our direction + for (let i = 0; i < slot.directions.length; ++i) { + // const localDirection = targetStaticComp.localDirectionToWorld(slot.directions[l]); + if (desiredDirection === slot.directions[i]) { + return { + slot, + index: slotIndex, + acceptedDirection: desiredDirection, + }; + } + } + } + + return null; + } +} diff --git a/src/js/game/components/item_ejector.js b/src/js/game/components/item_ejector.js index ee661078..b9a23c38 100644 --- a/src/js/game/components/item_ejector.js +++ b/src/js/game/components/item_ejector.js @@ -1,19 +1,19 @@ -import { Vector, enumDirection, enumDirectionToVector } from "../../core/vector"; -import { BaseItem } from "../base_item"; -import { Component } from "../component"; +import { enumDirection, enumDirectionToVector, Vector } from "../../core/vector"; import { types } from "../../savegame/serialization"; -import { gItemRegistry } from "../../core/global_registries"; +import { BaseItem } from "../base_item"; +import { BeltPath } from "../belt_path"; +import { Component } from "../component"; import { Entity } from "../entity"; -import { enumLayer } from "../root"; +import { typeItemSingleton } from "../item_resolver"; /** * @typedef {{ * pos: Vector, * direction: enumDirection, * item: BaseItem, - * layer: enumLayer, * progress: number?, * cachedDestSlot?: import("./item_acceptor").ItemAcceptorLocatedSlot, + * cachedBeltPath?: BeltPath, * cachedTargetEntity?: Entity * }} ItemEjectorSlot */ @@ -24,19 +24,12 @@ export class ItemEjectorComponent extends Component { } static getSchema() { - // The cachedDestSlot, cachedTargetEntity, and cachedConnectedSlots fields - // are not serialized. + // The cachedDestSlot, cachedTargetEntity fields are not serialized. return { - instantEject: types.bool, slots: types.array( types.structured({ - pos: types.vector, - direction: types.enum(enumDirection), - item: types.nullable(types.obj(gItemRegistry)), + item: types.nullable(typeItemSingleton), progress: types.float, - - // TODO: Migrate - layer: types.enum(enumLayer), }) ), }; @@ -49,33 +42,24 @@ export class ItemEjectorComponent extends Component { slotsCopy.push({ pos: slot.pos.copy(), direction: slot.direction, - layer: slot.layer, }); } return new ItemEjectorComponent({ slots: slotsCopy, - instantEject: this.instantEject, }); } /** * * @param {object} param0 - * @param {Array<{pos: Vector, direction: enumDirection, layer?: enumLayer}>=} param0.slots The slots to eject on - * @param {boolean=} param0.instantEject If the ejection is instant + * @param {Array<{pos: Vector, direction: enumDirection }>=} param0.slots The slots to eject on */ - constructor({ slots = [], instantEject = false }) { + constructor({ slots = [] }) { super(); - // How long items take to eject - this.instantEject = instantEject; - this.setSlots(slots); - /** @type {ItemEjectorSlot[]} */ - this.cachedConnectedSlots = null; - /** * Whether this ejector slot is enabled */ @@ -83,7 +67,7 @@ export class ItemEjectorComponent extends Component { } /** - * @param {Array<{pos: Vector, direction: enumDirection, layer?: enumLayer}>} slots The slots to eject on + * @param {Array<{pos: Vector, direction: enumDirection }>} slots The slots to eject on */ setSlots(slots) { /** @type {Array} */ @@ -95,7 +79,6 @@ export class ItemEjectorComponent extends Component { direction: slot.direction, item: null, progress: 0, - layer: slot.layer || enumLayer.regular, cachedDestSlot: null, cachedTargetEntity: null, }); @@ -104,11 +87,10 @@ export class ItemEjectorComponent extends Component { /** * Returns where this slot ejects to - * @param {number} index + * @param {ItemEjectorSlot} slot * @returns {Vector} */ - getSlotTargetLocalTile(index) { - const slot = this.slots[index]; + getSlotTargetLocalTile(slot) { const directionVector = enumDirectionToVector[slot.direction]; return slot.pos.add(directionVector); } @@ -116,11 +98,10 @@ export class ItemEjectorComponent extends Component { /** * Returns whether any slot ejects to the given local tile * @param {Vector} tile - * @param {enumLayer} layer */ - anySlotEjectsToLocalTile(tile, layer) { + anySlotEjectsToLocalTile(tile) { for (let i = 0; i < this.slots.length; ++i) { - if (this.getSlotTargetLocalTile(i).equals(tile) && this.slots[i].layer === layer) { + if (this.getSlotTargetLocalTile(this.slots[i]).equals(tile)) { return true; } } @@ -139,12 +120,11 @@ export class ItemEjectorComponent extends Component { /** * Returns the first free slot on this ejector or null if there is none - * @param {enumLayer} layer * @returns {number?} */ - getFirstFreeSlot(layer) { + getFirstFreeSlot() { for (let i = 0; i < this.slots.length; ++i) { - if (this.canEjectOnSlot(i) && this.slots[i].layer === layer) { + if (this.canEjectOnSlot(i)) { return i; } } @@ -162,7 +142,7 @@ export class ItemEjectorComponent extends Component { return false; } this.slots[slotIndex].item = item; - this.slots[slotIndex].progress = this.instantEject ? 1 : 0; + this.slots[slotIndex].progress = 0; return true; } diff --git a/src/js/game/components/item_processor.js b/src/js/game/components/item_processor.js index 72422faf..5d51b4a3 100644 --- a/src/js/game/components/item_processor.js +++ b/src/js/game/components/item_processor.js @@ -1,7 +1,7 @@ -import { gItemRegistry } from "../../core/global_registries"; import { types } from "../../savegame/serialization"; import { BaseItem } from "../base_item"; import { Component } from "../component"; +import { typeItemSingleton } from "../item_resolver"; /** @enum {string} */ export const enumItemProcessorTypes = { @@ -11,16 +11,35 @@ export const enumItemProcessorTypes = { cutterQuad: "cutterQuad", rotater: "rotater", rotaterCCW: "rotaterCCW", + rotaterFL: "rotaterFL", stacker: "stacker", trash: "trash", mixer: "mixer", painter: "painter", painterDouble: "painterDouble", painterQuad: "painterQuad", - advancedProcessor: "advancedProcessor", hub: "hub", + filter: "filter", + reader: "reader", }; +/** @enum {string} */ +export const enumItemProcessorRequirements = { + painterQuad: "painterQuad", + filter: "filter", +}; + +/** @typedef {{ + * item: BaseItem, + * requiredSlot?: number, + * preferredSlot?: number + * }} EjectorItemToEject */ + +/** @typedef {{ + * remainingTime: number, + * items: Array, + * }} EjectorCharge */ + export class ItemProcessorComponent extends Component { static getId() { return "ItemProcessor"; @@ -29,29 +48,13 @@ export class ItemProcessorComponent extends Component { static getSchema() { return { nextOutputSlot: types.uint, - type: types.enum(enumItemProcessorTypes), - inputsPerCharge: types.uint, - - inputSlots: types.array( - types.structured({ - item: types.obj(gItemRegistry), - sourceSlot: types.uint, - }) - ), - itemsToEject: types.array( - types.structured({ - item: types.obj(gItemRegistry), - requiredSlot: types.nullable(types.uint), - preferredSlot: types.nullable(types.uint), - }) - ), - secondsUntilEject: types.float, }; } duplicateWithoutContents() { return new ItemProcessorComponent({ processorType: this.type, + processingRequirement: this.processingRequirement, inputsPerCharge: this.inputsPerCharge, }); } @@ -60,10 +63,15 @@ export class ItemProcessorComponent extends Component { * * @param {object} param0 * @param {enumItemProcessorTypes=} param0.processorType Which type of processor this is + * @param {enumItemProcessorRequirements=} param0.processingRequirement Applied processing requirement * @param {number=} param0.inputsPerCharge How many items this machine needs until it can start working * */ - constructor({ processorType = enumItemProcessorTypes.splitter, inputsPerCharge = 1 }) { + constructor({ + processorType = enumItemProcessorTypes.splitter, + processingRequirement = null, + inputsPerCharge = 1, + }) { super(); // Which slot to emit next, this is only a preference and if it can't emit @@ -74,6 +82,9 @@ export class ItemProcessorComponent extends Component { // Type of the processor this.type = processorType; + // Type of processing requirement + this.processingRequirement = processingRequirement; + // How many inputs we need for one charge this.inputsPerCharge = inputsPerCharge; @@ -87,14 +98,15 @@ export class ItemProcessorComponent extends Component { * What we are currently processing, empty if we don't produce anything rn * requiredSlot: Item *must* be ejected on this slot * preferredSlot: Item *can* be ejected on this slot, but others are fine too if the one is not usable - * @type {Array<{item: BaseItem, requiredSlot?: number, preferredSlot?: number}>} + * @type {Array} */ - this.itemsToEject = []; + this.ongoingCharges = []; /** - * How long it takes until we are done with the current items + * How much processing time we have left from the last tick + * @type {number} */ - this.secondsUntilEject = 0; + this.bonusTime = 0; } /** diff --git a/src/js/game/components/lever.js b/src/js/game/components/lever.js new file mode 100644 index 00000000..e17df1e8 --- /dev/null +++ b/src/js/game/components/lever.js @@ -0,0 +1,27 @@ +import { Component } from "../component"; +import { types } from "../../savegame/serialization"; + +export class LeverComponent extends Component { + static getId() { + return "Lever"; + } + + static getSchema() { + return { + toggled: types.bool, + }; + } + + duplicateWithoutContents() { + return new LeverComponent({ toggled: this.toggled }); + } + + /** + * @param {object} param0 + * @param {boolean=} param0.toggled + */ + constructor({ toggled = false }) { + super(); + this.toggled = toggled; + } +} diff --git a/src/js/game/components/logic_gate.js b/src/js/game/components/logic_gate.js new file mode 100644 index 00000000..fe151184 --- /dev/null +++ b/src/js/game/components/logic_gate.js @@ -0,0 +1,36 @@ +import { Component } from "../component"; + +/** @enum {string} */ +export const enumLogicGateType = { + and: "and", + not: "not", + xor: "xor", + or: "or", + transistor: "transistor", + + analyzer: "analyzer", + rotater: "rotater", + unstacker: "unstacker", + cutter: "cutter", + shapecompare: "shapecompare", +}; + +export class LogicGateComponent extends Component { + static getId() { + return "LogicGate"; + } + + duplicateWithoutContents() { + return new LogicGateComponent({ type: this.type }); + } + + /** + * + * @param {object} param0 + * @param {enumLogicGateType=} param0.type + */ + constructor({ type = enumLogicGateType.and }) { + super(); + this.type = type; + } +} diff --git a/src/js/game/components/miner.js b/src/js/game/components/miner.js index 74a4b616..5b818afb 100644 --- a/src/js/game/components/miner.js +++ b/src/js/game/components/miner.js @@ -1,60 +1,66 @@ -import { globalConfig } from "../../core/config"; -import { types } from "../../savegame/serialization"; -import { Component } from "../component"; -import { BaseItem } from "../base_item"; -import { gItemRegistry } from "../../core/global_registries"; - -const chainBufferSize = 3; - -export class MinerComponent extends Component { - static getId() { - return "Miner"; - } - - static getSchema() { - // cachedMinedItem is not serialized. - return { - lastMiningTime: types.ufloat, - chainable: types.bool, - itemChainBuffer: types.array(types.obj(gItemRegistry)), - }; - } - - duplicateWithoutContents() { - return new MinerComponent({ - chainable: this.chainable, - }); - } - - constructor({ chainable = false }) { - super(); - this.lastMiningTime = 0; - this.chainable = chainable; - - /** - * Stores items from other miners which were chained to this - * miner. - * @type {Array} - */ - this.itemChainBuffer = []; - - /** - * @type {BaseItem} - */ - this.cachedMinedItem = null; - } - - /** - * - * @param {BaseItem} item - */ - tryAcceptChainedItem(item) { - if (this.itemChainBuffer.length > chainBufferSize) { - // Well, this one is full - return false; - } - - this.itemChainBuffer.push(item); - return true; - } -} +import { types } from "../../savegame/serialization"; +import { BaseItem } from "../base_item"; +import { Component } from "../component"; +import { Entity } from "../entity"; +import { typeItemSingleton } from "../item_resolver"; + +const chainBufferSize = 6; + +export class MinerComponent extends Component { + static getId() { + return "Miner"; + } + + static getSchema() { + // cachedMinedItem is not serialized. + return { + lastMiningTime: types.ufloat, + itemChainBuffer: types.array(typeItemSingleton), + }; + } + + duplicateWithoutContents() { + return new MinerComponent({ + chainable: this.chainable, + }); + } + + constructor({ chainable = false }) { + super(); + this.lastMiningTime = 0; + this.chainable = chainable; + + /** + * Stores items from other miners which were chained to this + * miner. + * @type {Array} + */ + this.itemChainBuffer = []; + + /** + * @type {BaseItem} + */ + this.cachedMinedItem = null; + + /** + * Which miner this miner ejects to, in case its a chainable one. + * If the value is false, it means there is no entity, and we don't have to re-check + * @type {Entity|null|false} + */ + this.cachedChainedMiner = null; + } + + /** + * + * @param {BaseItem} item + */ + tryAcceptChainedItem(item) { + if (this.itemChainBuffer.length > chainBufferSize) { + // Well, this one is full + return false; + } + + this.itemChainBuffer.push(item); + return true; + } +} diff --git a/src/js/game/components/replaceable_map_entity.js b/src/js/game/components/replaceable_map_entity.js deleted file mode 100644 index 78861caf..00000000 --- a/src/js/game/components/replaceable_map_entity.js +++ /dev/null @@ -1,15 +0,0 @@ -import { Component } from "../component"; - -/** - * Marks an entity as replaceable, so that when other buildings are placed above him it - * simply gets deleted - */ -export class ReplaceableMapEntityComponent extends Component { - static getId() { - return "ReplaceableMapEntity"; - } - - duplicateWithoutContents() { - return new ReplaceableMapEntityComponent(); - } -} diff --git a/src/js/game/components/static_map_entity.js b/src/js/game/components/static_map_entity.js index 3f0794a4..3d138e42 100644 --- a/src/js/game/components/static_map_entity.js +++ b/src/js/game/components/static_map_entity.js @@ -4,6 +4,7 @@ import { Rectangle } from "../../core/rectangle"; import { AtlasSprite } from "../../core/sprites"; import { enumDirection, Vector } from "../../core/vector"; import { types } from "../../savegame/serialization"; +import { getBuildingDataFromCode } from "../building_codes"; import { Component } from "../component"; export class StaticMapEntityComponent extends Component { @@ -14,24 +15,60 @@ export class StaticMapEntityComponent extends Component { static getSchema() { return { origin: types.tileVector, - tileSize: types.tileVector, rotation: types.float, originalRotation: types.float, - spriteKey: types.nullable(types.string), - blueprintSpriteKey: types.string, - silhouetteColor: types.nullable(types.string), + + // See building_codes.js + code: types.uint, }; } + /** + * Returns the effective tile size + * @returns {Vector} + */ + getTileSize() { + return getBuildingDataFromCode(this.code).tileSize; + } + + /** + * Returns the sprite + * @returns {AtlasSprite} + */ + getSprite() { + return getBuildingDataFromCode(this.code).sprite; + } + + /** + * Returns the blueprint sprite + * @returns {AtlasSprite} + */ + getBlueprintSprite() { + return getBuildingDataFromCode(this.code).blueprintSprite; + } + + /** + * Returns the silhouette color + * @returns {string} + */ + getSilhouetteColor() { + return getBuildingDataFromCode(this.code).silhouetteColor; + } + + /** + * Returns the meta building + * @returns {import("../meta_building").MetaBuilding} + */ + getMetaBuilding() { + return getBuildingDataFromCode(this.code).metaInstance; + } + duplicateWithoutContents() { return new StaticMapEntityComponent({ origin: this.origin.copy(), - tileSize: this.tileSize.copy(), rotation: this.rotation, originalRotation: this.originalRotation, - spriteKey: this.spriteKey, - silhouetteColor: this.silhouetteColor, - blueprintSpriteKey: this.blueprintSpriteKey, + code: this.code, }); } @@ -42,18 +79,14 @@ export class StaticMapEntityComponent extends Component { * @param {Vector=} param0.tileSize Size of the entity in tiles * @param {number=} param0.rotation Rotation in degrees. Must be multiple of 90 * @param {number=} param0.originalRotation Original Rotation in degrees. Must be multiple of 90 - * @param {string=} param0.spriteKey Optional sprite - * @param {string} param0.blueprintSpriteKey Blueprint sprite, required - * @param {string=} param0.silhouetteColor Optional silhouette color override + * @param {number=} param0.code Building code */ constructor({ origin = new Vector(), tileSize = new Vector(1, 1), rotation = 0, originalRotation = 0, - spriteKey = null, - silhouetteColor = null, - blueprintSpriteKey = null, + code = 0, }) { super(); assert( @@ -62,12 +95,9 @@ export class StaticMapEntityComponent extends Component { ); this.origin = origin; - this.tileSize = tileSize; - this.spriteKey = spriteKey; this.rotation = rotation; + this.code = code; this.originalRotation = originalRotation; - this.silhouetteColor = silhouetteColor; - this.blueprintSpriteKey = blueprintSpriteKey; } /** @@ -75,30 +105,16 @@ export class StaticMapEntityComponent extends Component { * @returns {Rectangle} */ getTileSpaceBounds() { + const size = this.getTileSize(); switch (this.rotation) { case 0: - return new Rectangle(this.origin.x, this.origin.y, this.tileSize.x, this.tileSize.y); + return new Rectangle(this.origin.x, this.origin.y, size.x, size.y); case 90: - return new Rectangle( - this.origin.x - this.tileSize.y + 1, - this.origin.y, - this.tileSize.y, - this.tileSize.x - ); + return new Rectangle(this.origin.x - size.y + 1, this.origin.y, size.y, size.x); case 180: - return new Rectangle( - this.origin.x - this.tileSize.x + 1, - this.origin.y - this.tileSize.y + 1, - this.tileSize.x, - this.tileSize.y - ); + return new Rectangle(this.origin.x - size.x + 1, this.origin.y - size.y + 1, size.x, size.y); case 270: - return new Rectangle( - this.origin.x, - this.origin.y - this.tileSize.x + 1, - this.tileSize.y, - this.tileSize.x - ); + return new Rectangle(this.origin.x, this.origin.y - size.x + 1, size.y, size.x); default: assert(false, "Invalid rotation"); } @@ -146,8 +162,9 @@ export class StaticMapEntityComponent extends Component { * @returns {Vector} */ localTileToWorld(localTile) { - const result = this.applyRotationToVector(localTile); - result.addInplace(this.origin); + const result = localTile.rotateFastMultipleOf90(this.rotation); + result.x += this.origin.x; + result.y += this.origin.y; return result; } @@ -169,34 +186,35 @@ export class StaticMapEntityComponent extends Component { let y = 0; let w = 0; let h = 0; + const size = this.getTileSize(); switch (this.rotation) { case 0: { x = this.origin.x; y = this.origin.y; - w = this.tileSize.x; - h = this.tileSize.y; + w = size.x; + h = size.y; break; } case 90: { - x = this.origin.x - this.tileSize.y + 1; + x = this.origin.x - size.y + 1; y = this.origin.y; - w = this.tileSize.y; - h = this.tileSize.x; + w = size.y; + h = size.x; break; } case 180: { - x = this.origin.x - this.tileSize.x + 1; - y = this.origin.y - this.tileSize.y + 1; - w = this.tileSize.x; - h = this.tileSize.y; + x = this.origin.x - size.x + 1; + y = this.origin.y - size.y + 1; + w = size.x; + h = size.y; break; } case 270: { x = this.origin.x; - y = this.origin.y - this.tileSize.x + 1; - w = this.tileSize.y; - h = this.tileSize.x; + y = this.origin.y - size.x + 1; + w = size.y; + h = size.x; break; } default: @@ -216,19 +234,13 @@ export class StaticMapEntityComponent extends Component { * @param {DrawParameters} parameters * @param {AtlasSprite} sprite * @param {number=} extrudePixels How many pixels to extrude the sprite - * @param {boolean=} clipping Whether to clip * @param {Vector=} overridePosition Whether to drwa the entity at a different location */ - drawSpriteOnFullEntityBounds( - parameters, - sprite, - extrudePixels = 0, - clipping = true, - overridePosition = null - ) { + drawSpriteOnBoundsClipped(parameters, sprite, extrudePixels = 0, overridePosition = null) { if (!this.shouldBeDrawn(parameters) && !overridePosition) { return; } + const size = this.getTileSize(); let worldX = this.origin.x * globalConfig.tileSize; let worldY = this.origin.y * globalConfig.tileSize; @@ -241,11 +253,10 @@ export class StaticMapEntityComponent extends Component { // Early out, is faster sprite.drawCached( parameters, - worldX - extrudePixels * this.tileSize.x, - worldY - extrudePixels * this.tileSize.y, - globalConfig.tileSize * this.tileSize.x + 2 * extrudePixels * this.tileSize.x, - globalConfig.tileSize * this.tileSize.y + 2 * extrudePixels * this.tileSize.y, - false + worldX - extrudePixels * size.x, + worldY - extrudePixels * size.y, + globalConfig.tileSize * size.x + 2 * extrudePixels * size.x, + globalConfig.tileSize * size.y + 2 * extrudePixels * size.y ); } else { const rotationCenterX = worldX + globalConfig.halfTileSize; @@ -253,16 +264,14 @@ export class StaticMapEntityComponent extends Component { parameters.context.translate(rotationCenterX, rotationCenterY); parameters.context.rotate(Math.radians(this.rotation)); - sprite.drawCached( parameters, - -globalConfig.halfTileSize - extrudePixels * this.tileSize.x, - -globalConfig.halfTileSize - extrudePixels * this.tileSize.y, - globalConfig.tileSize * this.tileSize.x + 2 * extrudePixels * this.tileSize.x, - globalConfig.tileSize * this.tileSize.y + 2 * extrudePixels * this.tileSize.y, - false + -globalConfig.halfTileSize - extrudePixels * size.x, + -globalConfig.halfTileSize - extrudePixels * size.y, + globalConfig.tileSize * size.x + 2 * extrudePixels * size.x, + globalConfig.tileSize * size.y + 2 * extrudePixels * size.y, + false // no clipping possible here ); - parameters.context.rotate(-Math.radians(this.rotation)); parameters.context.translate(-rotationCenterX, -rotationCenterY); } diff --git a/src/js/game/components/storage.js b/src/js/game/components/storage.js index e7b40a77..3b32f6a3 100644 --- a/src/js/game/components/storage.js +++ b/src/js/game/components/storage.js @@ -1,7 +1,7 @@ -import { Component } from "../component"; import { types } from "../../savegame/serialization"; -import { gItemRegistry } from "../../core/global_registries"; -import { BaseItem, enumItemType } from "../base_item"; +import { BaseItem } from "../base_item"; +import { Component } from "../component"; +import { typeItemSingleton } from "../item_resolver"; import { ColorItem } from "../items/color_item"; import { ShapeItem } from "../items/shape_item"; @@ -12,10 +12,8 @@ export class StorageComponent extends Component { static getSchema() { return { - maximumStorage: types.uint, storedCount: types.uint, - storedItem: types.nullable(types.obj(gItemRegistry)), - overlayOpacity: types.ufloat, + storedItem: types.nullable(typeItemSingleton), }; } @@ -67,11 +65,11 @@ export class StorageComponent extends Component { return false; } - if (itemType === enumItemType.color) { + if (itemType === "color") { return /** @type {ColorItem} */ (this.storedItem).color === /** @type {ColorItem} */ (item).color; } - if (itemType === enumItemType.shape) { + if (itemType === "shape") { return ( /** @type {ShapeItem} */ (this.storedItem).definition.getHash() === /** @type {ShapeItem} */ (item).definition.getHash() @@ -80,6 +78,14 @@ export class StorageComponent extends Component { return false; } + /** + * Returns whether the storage is full + * @returns {boolean} + */ + getIsFull() { + return this.storedCount >= this.maximumStorage; + } + /** * @param {BaseItem} item */ diff --git a/src/js/game/components/underground_belt.js b/src/js/game/components/underground_belt.js index e94b7cb1..74351aac 100644 --- a/src/js/game/components/underground_belt.js +++ b/src/js/game/components/underground_belt.js @@ -1,10 +1,9 @@ -import { BaseItem } from "../base_item"; -import { Component } from "../component"; import { globalConfig } from "../../core/config"; import { types } from "../../savegame/serialization"; -import { gItemRegistry } from "../../core/global_registries"; +import { BaseItem } from "../base_item"; +import { Component } from "../component"; import { Entity } from "../entity"; -import { enumLayer } from "../root"; +import { typeItemSingleton } from "../item_resolver"; /** @enum {string} */ export const enumUndergroundBeltMode = { @@ -26,9 +25,7 @@ export class UndergroundBeltComponent extends Component { static getSchema() { return { - mode: types.enum(enumUndergroundBeltMode), - pendingItems: types.array(types.pair(types.obj(gItemRegistry), types.float)), - tier: types.uint, + pendingItems: types.array(types.pair(typeItemSingleton, types.float)), }; } @@ -103,8 +100,7 @@ export class UndergroundBeltComponent extends Component { } // Notice: We assume that for all items the travel distance is the same - const maxItemsInTunnel = - (2 + travelDistance) / globalConfig.beltItemSpacingByLayer[enumLayer.regular]; + const maxItemsInTunnel = (2 + travelDistance) / globalConfig.itemSpacingOnBelts; if (this.pendingItems.length >= maxItemsInTunnel) { // Simulate a real belt which gets full at some point return false; @@ -114,8 +110,7 @@ export class UndergroundBeltComponent extends Component { // This corresponds to the item ejector - it needs 0.5 additional tiles to eject the item. // So instead of adding 1 we add 0.5 only. // Additionally it takes 1 tile for the acceptor which we just add on top. - const travelDuration = - (travelDistance + 1.5) / beltSpeed / globalConfig.beltItemSpacingByLayer[enumLayer.regular]; + const travelDuration = (travelDistance + 1.5) / beltSpeed / globalConfig.itemSpacingOnBelts; this.pendingItems.push([item, travelDuration]); diff --git a/src/js/game/components/unremovable.js b/src/js/game/components/unremovable.js deleted file mode 100644 index f3864cf8..00000000 --- a/src/js/game/components/unremovable.js +++ /dev/null @@ -1,15 +0,0 @@ -import { Component } from "../component"; - -export class UnremovableComponent extends Component { - static getId() { - return "Unremovable"; - } - - static getSchema() { - return {}; - } - - duplicateWithoutContents() { - return new UnremovableComponent(); - } -} diff --git a/src/js/game/components/wire.js b/src/js/game/components/wire.js new file mode 100644 index 00000000..88c56249 --- /dev/null +++ b/src/js/game/components/wire.js @@ -0,0 +1,73 @@ +import { Component } from "../component"; + +/** @enum {string} */ +export const enumWireType = { + regular: "regular", + turn: "turn", + split: "split", + cross: "cross", +}; + +export class WireComponent extends Component { + static getId() { + return "Wire"; + } + + duplicateWithoutContents() { + return new WireComponent({ type: this.type }); + } + + /** + * @param {object} param0 + * @param {enumWireType=} param0.type + */ + constructor({ type = enumWireType.regular }) { + super(); + this.type = type; + + /** + * @type {import("../systems/wire").WireNetwork} + */ + this.linkedNetwork = null; + } + + /** + * Returns the local connections + * @returns {import("../../core/utils").DirectionalObject} + */ + getLocalConnections() { + return { + top: true, + right: false, + bottom: true, + left: false, + }; + + // switch (this.type) { + // case enumWireType.regular: + // return { + // top: true, + // right: false, + // bottom: true, + // left: false, + // }; + // case enumWireType.turn: + // return { + // top: false, + // right: true, + // bottom: true, + // left: false, + // }; + // case enumWireType.split: + // return { + // top: false, + // right: true, + // bottom: true, + // left: true, + // }; + + // default: + // assertAlways(false, "Invalid wire type: " + this.type); + // } + } +} diff --git a/src/js/game/components/wire_tunnel.js b/src/js/game/components/wire_tunnel.js new file mode 100644 index 00000000..dfb38f1f --- /dev/null +++ b/src/js/game/components/wire_tunnel.js @@ -0,0 +1,26 @@ +import { Component } from "../component"; + +export class WireTunnelComponent extends Component { + static getId() { + return "WireTunnel"; + } + + duplicateWithoutContents() { + return new WireTunnelComponent({ multipleDirections: this.multipleDirections }); + } + + /** + * @param {object} param0 + * @param {boolean=} param0.multipleDirections + */ + constructor({ multipleDirections = true }) { + super(); + this.multipleDirections = multipleDirections; + + /** + * Linked network, only if its not multiple directions + * @type {Array} + */ + this.linkedNetworks = []; + } +} diff --git a/src/js/game/components/wired_pins.js b/src/js/game/components/wired_pins.js index 0d331a68..9a19c2b0 100644 --- a/src/js/game/components/wired_pins.js +++ b/src/js/game/components/wired_pins.js @@ -1,13 +1,13 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { BaseItem } from "../base_item"; import { Component } from "../component"; -import { Vector, enumDirection } from "../../core/vector"; import { types } from "../../savegame/serialization"; +import { typeItemSingleton } from "../item_resolver"; /** @enum {string} */ export const enumPinSlotType = { - positiveEnergyEjector: "positiveEnergyEjector", - negativeEnergyEjector: "negativeEnergyEjector", - positiveEnergyAcceptor: "positiveEnergyAcceptor", - negativeEnergyAcceptor: "negativeEnergyAcceptor", + logicalEjector: "logicalEjector", + logicalAcceptor: "logicalAcceptor", }; /** @typedef {{ @@ -19,7 +19,9 @@ export const enumPinSlotType = { /** @typedef {{ * pos: Vector, * type: enumPinSlotType, - * direction: enumDirection + * direction: enumDirection, + * value: BaseItem, + * linkedNetwork: import("../systems/wire").WireNetwork * }} WirePinSlot */ export class WiredPinsComponent extends Component { @@ -31,8 +33,7 @@ export class WiredPinsComponent extends Component { return { slots: types.array( types.structured({ - pos: types.vector, - type: types.enum(enumPinSlotType), + value: types.nullable(typeItemSingleton), }) ), }; @@ -76,6 +77,8 @@ export class WiredPinsComponent extends Component { pos: slotData.pos, type: slotData.type, direction: slotData.direction, + value: null, + linkedNetwork: null, }); } } diff --git a/src/js/game/core.js b/src/js/game/core.js index 960a83e3..642d8d9d 100644 --- a/src/js/game/core.js +++ b/src/js/game/core.js @@ -1,480 +1,525 @@ -/* typehints:start */ -import { InGameState } from "../states/ingame"; -import { Application } from "../application"; -/* typehints:end */ - -import { BufferMaintainer } from "../core/buffer_maintainer"; -import { disableImageSmoothing, enableImageSmoothing, registerCanvas } from "../core/buffer_utils"; -import { globalConfig } from "../core/config"; -import { getDeviceDPI, resizeHighDPICanvas } from "../core/dpi_manager"; -import { DrawParameters } from "../core/draw_parameters"; -import { gMetaBuildingRegistry } from "../core/global_registries"; -import { createLogger } from "../core/logging"; -import { Vector } from "../core/vector"; -import { Savegame } from "../savegame/savegame"; -import { SavegameSerializer } from "../savegame/savegame_serializer"; -import { AutomaticSave } from "./automatic_save"; -import { MetaHubBuilding } from "./buildings/hub"; -import { Camera } from "./camera"; -import { EntityManager } from "./entity_manager"; -import { GameSystemManager } from "./game_system_manager"; -import { HubGoals } from "./hub_goals"; -import { GameHUD } from "./hud/hud"; -import { KeyActionMapper } from "./key_action_mapper"; -import { GameLogic } from "./logic"; -import { MapView } from "./map_view"; -import { GameRoot, enumLayer } from "./root"; -import { ShapeDefinitionManager } from "./shape_definition_manager"; -import { SoundProxy } from "./sound_proxy"; -import { GameTime } from "./time/game_time"; -import { ProductionAnalytics } from "./production_analytics"; -import { randomInt } from "../core/utils"; -import { defaultBuildingVariant } from "./meta_building"; -import { DynamicTickrate } from "./dynamic_tickrate"; - -const logger = createLogger("ingame/core"); - -// Store the canvas so we can reuse it later -/** @type {HTMLCanvasElement} */ -let lastCanvas = null; -/** @type {CanvasRenderingContext2D} */ -let lastContext = null; - -/** - * The core manages the root and represents the whole game. It wraps the root, since - * the root class is just a data holder. - */ -export class GameCore { - /** @param {Application} app */ - constructor(app) { - this.app = app; - - /** @type {GameRoot} */ - this.root = null; - - /** - * Set to true at the beginning of a logic update and cleared when its finished. - * This is to prevent doing a recursive logic update which can lead to unexpected - * behaviour. - */ - this.duringLogicUpdate = false; - - // Cached - this.boundInternalTick = this.updateLogic.bind(this); - } - - /** - * Initializes the root object which stores all game related data. The state - * is required as a back reference (used sometimes) - * @param {InGameState} parentState - * @param {Savegame} savegame - */ - initializeRoot(parentState, savegame) { - // Construct the root element, this is the data representation of the game - this.root = new GameRoot(this.app); - this.root.gameState = parentState; - this.root.keyMapper = parentState.keyActionMapper; - this.root.savegame = savegame; - this.root.gameWidth = this.app.screenWidth; - this.root.gameHeight = this.app.screenHeight; - - // Initialize canvas element & context - this.internalInitCanvas(); - - // Members - const root = this.root; - - // This isn't nice, but we need it right here - root.keyMapper = new KeyActionMapper(root, this.root.gameState.inputReciever); - - // Needs to come first - root.dynamicTickrate = new DynamicTickrate(root); - - // Init classes - root.camera = new Camera(root); - root.map = new MapView(root); - root.logic = new GameLogic(root); - root.hud = new GameHUD(root); - root.time = new GameTime(root); - root.automaticSave = new AutomaticSave(root); - root.soundProxy = new SoundProxy(root); - - // Init managers - root.entityMgr = new EntityManager(root); - root.systemMgr = new GameSystemManager(root); - root.shapeDefinitionMgr = new ShapeDefinitionManager(root); - root.hubGoals = new HubGoals(root); - root.productionAnalytics = new ProductionAnalytics(root); - root.buffers = new BufferMaintainer(root); - - // Initialize the hud once everything is loaded - this.root.hud.initialize(); - - // Initial resize event, it might be possible that the screen - // resized later during init tho, which is why will emit it later - // again anyways - this.resize(this.app.screenWidth, this.app.screenHeight); - - if (G_IS_DEV) { - // @ts-ignore - window.globalRoot = root; - } - } - - /** - * Initializes a new game, this means creating a new map and centering on the - * playerbase - * */ - initNewGame() { - logger.log("Initializing new game"); - this.root.gameIsFresh = true; - this.root.map.seed = randomInt(0, 100000); - - // Place the hub - const hub = gMetaBuildingRegistry.findByClass(MetaHubBuilding).createEntity({ - root: this.root, - origin: new Vector(-2, -2), - rotation: 0, - originalRotation: 0, - rotationVariant: 0, - variant: defaultBuildingVariant, - }); - this.root.map.placeStaticEntity(hub); - this.root.entityMgr.registerEntity(hub); - } - - /** - * Inits an existing game by loading the raw savegame data and deserializing it. - * Also runs basic validity checks. - */ - initExistingGame() { - logger.log("Initializing existing game"); - const serializer = new SavegameSerializer(); - - try { - const status = serializer.deserialize(this.root.savegame.getCurrentDump(), this.root); - if (!status.isGood()) { - logger.error("savegame-deserialize-failed:" + status.reason); - return false; - } - } catch (ex) { - logger.error("Exception during deserialization:", ex); - return false; - } - this.root.gameIsFresh = false; - return true; - } - - /** - * Initializes the render canvas - */ - internalInitCanvas() { - let canvas, context; - if (!lastCanvas) { - logger.log("Creating new canvas"); - canvas = document.createElement("canvas"); - canvas.id = "ingame_Canvas"; - canvas.setAttribute("opaque", "true"); - canvas.setAttribute("webkitOpaque", "true"); - canvas.setAttribute("mozOpaque", "true"); - this.root.gameState.getDivElement().appendChild(canvas); - context = canvas.getContext("2d", { alpha: false }); - - lastCanvas = canvas; - lastContext = context; - } else { - logger.log("Reusing canvas"); - if (lastCanvas.parentElement) { - lastCanvas.parentElement.removeChild(lastCanvas); - } - this.root.gameState.getDivElement().appendChild(lastCanvas); - - canvas = lastCanvas; - context = lastContext; - - lastContext.clearRect(0, 0, lastCanvas.width, lastCanvas.height); - } - - // globalConfig.smoothing.smoothMainCanvas = getDeviceDPI() < 1.5; - // globalConfig.smoothing.smoothMainCanvas = true; - - canvas.classList.toggle("smoothed", globalConfig.smoothing.smoothMainCanvas); - - // Oof, use :not() instead - canvas.classList.toggle("unsmoothed", !globalConfig.smoothing.smoothMainCanvas); - - if (globalConfig.smoothing.smoothMainCanvas) { - enableImageSmoothing(context); - } else { - disableImageSmoothing(context); - } - - this.root.canvas = canvas; - this.root.context = context; - - registerCanvas(canvas, context); - } - - /** - * Destructs the root, freeing all resources - */ - destruct() { - if (lastCanvas && lastCanvas.parentElement) { - lastCanvas.parentElement.removeChild(lastCanvas); - } - - this.root.destruct(); - delete this.root; - this.root = null; - this.app = null; - } - - tick(deltaMs) { - const root = this.root; - - if (root.hud.parts.processingOverlay.hasTasks() || root.hud.parts.processingOverlay.isRunning()) { - return true; - } - - // Extract current real time - root.time.updateRealtimeNow(); - - // Camera is always updated, no matter what - root.camera.update(deltaMs); - - // Perform logic ticks - this.root.time.performTicks(deltaMs, this.boundInternalTick); - - // Update analytics - root.productionAnalytics.update(); - - // Update automatic save after everything finished - root.automaticSave.update(); - - return true; - } - - shouldRender() { - if (this.root.queue.requireRedraw) { - return true; - } - if (this.root.hud.shouldPauseRendering()) { - return false; - } - - // Do not render - if (!this.app.isRenderable()) { - return false; - } - - return true; - } - - updateLogic() { - const root = this.root; - - root.dynamicTickrate.beginTick(); - - if (G_IS_DEV && globalConfig.debug.disableLogicTicks) { - root.dynamicTickrate.endTick(); - return true; - } - - this.duringLogicUpdate = true; - - // Update entities, this removes destroyed entities - root.entityMgr.update(); - - // IMPORTANT: At this point, the game might be game over. Stop if this is the case - if (!this.root) { - logger.log("Root destructed, returning false"); - root.dynamicTickrate.endTick(); - - return false; - } - - root.systemMgr.update(); - // root.particleMgr.update(); - - this.duringLogicUpdate = false; - root.dynamicTickrate.endTick(); - return true; - } - - resize(w, h) { - this.root.gameWidth = w; - this.root.gameHeight = h; - resizeHighDPICanvas(this.root.canvas, w, h, globalConfig.smoothing.smoothMainCanvas); - this.root.signals.resized.dispatch(w, h); - this.root.queue.requireRedraw = true; - } - - postLoadHook() { - logger.log("Dispatching post load hook"); - this.root.signals.postLoadHook.dispatch(); - - if (!this.root.gameIsFresh) { - // Also dispatch game restored hook on restored savegames - this.root.signals.gameRestored.dispatch(); - } - - this.root.gameInitialized = true; - } - - draw() { - const root = this.root; - const systems = root.systemMgr.systems; - - const taskRunner = root.hud.parts.processingOverlay; - if (taskRunner.hasTasks()) { - if (!taskRunner.isRunning()) { - taskRunner.process(); - } - return; - } - - this.root.dynamicTickrate.onFrameRendered(); - - if (!this.shouldRender()) { - // Always update hud tho - root.hud.update(); - return; - } - - // Update buffers as the very first - root.buffers.update(); - - root.queue.requireRedraw = false; - - // Gather context and save all state - const context = root.context; - context.save(); - if (G_IS_DEV && globalConfig.debug.testClipping) { - context.clearRect(0, 0, window.innerWidth * 3, window.innerHeight * 3); - } - - // Compute optimal zoom level and atlas scale - const zoomLevel = root.camera.zoomLevel; - const effectiveZoomLevel = - (zoomLevel / globalConfig.assetsDpi) * getDeviceDPI() * globalConfig.assetsSharpness; - - let desiredAtlasScale = "0.1"; - if (effectiveZoomLevel > 0.75) { - desiredAtlasScale = "1"; - } else if (effectiveZoomLevel > 0.5) { - desiredAtlasScale = "0.75"; - } else if (effectiveZoomLevel > 0.25) { - desiredAtlasScale = "0.5"; - } else if (effectiveZoomLevel > 0.1) { - desiredAtlasScale = "0.25"; - } - - // Construct parameters required for drawing - const params = new DrawParameters({ - context: context, - visibleRect: root.camera.getVisibleRect(), - desiredAtlasScale, - zoomLevel, - root: root, - }); - - if (G_IS_DEV && (globalConfig.debug.testCulling || globalConfig.debug.hideFog)) { - context.clearRect(0, 0, root.gameWidth, root.gameHeight); - } - - // Transform to world space - root.camera.transform(context); - - assert(context.globalAlpha === 1.0, "Global alpha not 1 on frame start"); - - // Update hud - root.hud.update(); - - // Main rendering order - // ----- - - // BG / Map Resources / Belt Backgrounds - root.map.drawBackground(params); - - if (!this.root.camera.getIsMapOverlayActive()) { - // Underlays for splitters / balancers - systems.itemAcceptor.drawUnderlays(params, enumLayer.regular); - - // Belt items - systems.belt.drawLayerBeltItems(params, enumLayer.regular); - - // Items being ejected / accepted currently (animations) - systems.itemEjector.drawLayer(params, enumLayer.regular); - systems.itemAcceptor.drawLayer(params, enumLayer.regular); - } - - // Miner & Static map entities - root.map.drawForeground(params); - - if (!this.root.camera.getIsMapOverlayActive()) { - // HUB Overlay - systems.hub.draw(params); - - // Energy generator overlay - systems.energyGenerator.draw(params); - - // Storage items - systems.storage.draw(params); - - // Energy consumer (Battery icons) - systems.energyConsumer.draw(params); - } - - // Green wires overlay (not within the if because it can fade) - root.hud.parts.wiresOverlay.draw(params); - - if (this.root.currentLayer === enumLayer.wires && !this.root.camera.getIsMapOverlayActive()) { - // Belt sprites & Static map entities - root.map.drawWiresLayer(params); - - // Belt items as well as accepted / ejected items - systems.belt.drawLayerBeltItems(params, enumLayer.wires); - systems.itemEjector.drawLayer(params, enumLayer.wires); - systems.itemAcceptor.drawLayer(params, enumLayer.wires); - - root.map.drawWiresForegroundLayer(params); - - // pins - systems.wiredPins.draw(params); - } - - if (G_IS_DEV) { - root.map.drawStaticEntityDebugOverlays(params); - } - - if (G_IS_DEV && globalConfig.debug.renderBeltPaths) { - systems.belt.drawBeltPathDebug(params); - } - - // END OF GAME CONTENT - // ----- - - // Finally, draw the hud. Nothing should come after that - root.hud.draw(params); - - assert(context.globalAlpha === 1.0, "Global alpha not 1 on frame end before restore"); - - // Restore to screen space - context.restore(); - - // Draw overlays, those are screen space - root.hud.drawOverlays(params); - - assert(context.globalAlpha === 1.0, "context.globalAlpha not 1 on frame end"); - - if (G_IS_DEV && globalConfig.debug.simulateSlowRendering) { - let sum = 0; - for (let i = 0; i < 1e8; ++i) { - sum += i; - } - if (Math.random() > 0.95) { - console.log(sum); - } - } - } -} +/* typehints:start */ +import { Application } from "../application"; +/* typehints:end */ +import { BufferMaintainer } from "../core/buffer_maintainer"; +import { disableImageSmoothing, enableImageSmoothing, registerCanvas } from "../core/buffer_utils"; +import { globalConfig } from "../core/config"; +import { getDeviceDPI, resizeHighDPICanvas } from "../core/dpi_manager"; +import { DrawParameters } from "../core/draw_parameters"; +import { gMetaBuildingRegistry } from "../core/global_registries"; +import { createLogger } from "../core/logging"; +import { Rectangle } from "../core/rectangle"; +import { ORIGINAL_SPRITE_SCALE } from "../core/sprites"; +import { lerp, randomInt, round2Digits } from "../core/utils"; +import { Vector } from "../core/vector"; +import { Savegame } from "../savegame/savegame"; +import { SavegameSerializer } from "../savegame/savegame_serializer"; +import { AutomaticSave } from "./automatic_save"; +import { MetaHubBuilding } from "./buildings/hub"; +import { Camera } from "./camera"; +import { DynamicTickrate } from "./dynamic_tickrate"; +import { EntityManager } from "./entity_manager"; +import { GameSystemManager } from "./game_system_manager"; +import { HubGoals } from "./hub_goals"; +import { GameHUD } from "./hud/hud"; +import { KeyActionMapper } from "./key_action_mapper"; +import { GameLogic } from "./logic"; +import { MapView } from "./map_view"; +import { defaultBuildingVariant } from "./meta_building"; +import { ProductionAnalytics } from "./production_analytics"; +import { GameRoot } from "./root"; +import { ShapeDefinitionManager } from "./shape_definition_manager"; +import { SoundProxy } from "./sound_proxy"; +import { GameTime } from "./time/game_time"; + +const logger = createLogger("ingame/core"); + +// Store the canvas so we can reuse it later +/** @type {HTMLCanvasElement} */ +let lastCanvas = null; +/** @type {CanvasRenderingContext2D} */ +let lastContext = null; + +/** + * The core manages the root and represents the whole game. It wraps the root, since + * the root class is just a data holder. + */ +export class GameCore { + /** @param {Application} app */ + constructor(app) { + this.app = app; + + /** @type {GameRoot} */ + this.root = null; + + /** + * Set to true at the beginning of a logic update and cleared when its finished. + * This is to prevent doing a recursive logic update which can lead to unexpected + * behaviour. + */ + this.duringLogicUpdate = false; + + // Cached + this.boundInternalTick = this.updateLogic.bind(this); + + /** + * Opacity of the overview alpha + * @TODO Doesn't belong here + */ + this.overlayAlpha = 0; + } + + /** + * Initializes the root object which stores all game related data. The state + * is required as a back reference (used sometimes) + * @param {import("../states/ingame").InGameState} parentState + * @param {Savegame} savegame + */ + initializeRoot(parentState, savegame) { + // Construct the root element, this is the data representation of the game + this.root = new GameRoot(this.app); + this.root.gameState = parentState; + this.root.keyMapper = parentState.keyActionMapper; + this.root.savegame = savegame; + this.root.gameWidth = this.app.screenWidth; + this.root.gameHeight = this.app.screenHeight; + + // Initialize canvas element & context + this.internalInitCanvas(); + + // Members + const root = this.root; + + // This isn't nice, but we need it right here + root.keyMapper = new KeyActionMapper(root, this.root.gameState.inputReciever); + + // Needs to come first + root.dynamicTickrate = new DynamicTickrate(root); + + // Init classes + root.camera = new Camera(root); + root.map = new MapView(root); + root.logic = new GameLogic(root); + root.hud = new GameHUD(root); + root.time = new GameTime(root); + root.automaticSave = new AutomaticSave(root); + root.soundProxy = new SoundProxy(root); + + // Init managers + root.entityMgr = new EntityManager(root); + root.systemMgr = new GameSystemManager(root); + root.shapeDefinitionMgr = new ShapeDefinitionManager(root); + root.hubGoals = new HubGoals(root); + root.productionAnalytics = new ProductionAnalytics(root); + root.buffers = new BufferMaintainer(root); + + // Initialize the hud once everything is loaded + this.root.hud.initialize(); + + // Initial resize event, it might be possible that the screen + // resized later during init tho, which is why will emit it later + // again anyways + this.resize(this.app.screenWidth, this.app.screenHeight); + + if (G_IS_DEV) { + // @ts-ignore + window.globalRoot = root; + } + + // @todo Find better place + if (G_IS_DEV && globalConfig.debug.manualTickOnly) { + this.root.gameState.inputReciever.keydown.add(key => { + if (key.keyCode === 84) { + // 'T' + + // Extract current real time + this.root.time.updateRealtimeNow(); + + // Perform logic ticks + this.root.time.performTicks(this.root.dynamicTickrate.deltaMs, this.boundInternalTick); + + // Update analytics + root.productionAnalytics.update(); + } + }); + } + } + + /** + * Initializes a new game, this means creating a new map and centering on the + * playerbase + * */ + initNewGame() { + logger.log("Initializing new game"); + this.root.gameIsFresh = true; + this.root.map.seed = randomInt(0, 100000); + + // Place the hub + const hub = gMetaBuildingRegistry.findByClass(MetaHubBuilding).createEntity({ + root: this.root, + origin: new Vector(-2, -2), + rotation: 0, + originalRotation: 0, + rotationVariant: 0, + variant: defaultBuildingVariant, + }); + this.root.map.placeStaticEntity(hub); + this.root.entityMgr.registerEntity(hub); + } + + /** + * Inits an existing game by loading the raw savegame data and deserializing it. + * Also runs basic validity checks. + */ + initExistingGame() { + logger.log("Initializing existing game"); + const serializer = new SavegameSerializer(); + + try { + const status = serializer.deserialize(this.root.savegame.getCurrentDump(), this.root); + if (!status.isGood()) { + logger.error("savegame-deserialize-failed:" + status.reason); + return false; + } + } catch (ex) { + logger.error("Exception during deserialization:", ex); + return false; + } + this.root.gameIsFresh = false; + return true; + } + + /** + * Initializes the render canvas + */ + internalInitCanvas() { + let canvas, context; + if (!lastCanvas) { + logger.log("Creating new canvas"); + canvas = document.createElement("canvas"); + canvas.id = "ingame_Canvas"; + canvas.setAttribute("opaque", "true"); + canvas.setAttribute("webkitOpaque", "true"); + canvas.setAttribute("mozOpaque", "true"); + this.root.gameState.getDivElement().appendChild(canvas); + context = canvas.getContext("2d", { alpha: false }); + + lastCanvas = canvas; + lastContext = context; + } else { + logger.log("Reusing canvas"); + if (lastCanvas.parentElement) { + lastCanvas.parentElement.removeChild(lastCanvas); + } + this.root.gameState.getDivElement().appendChild(lastCanvas); + + canvas = lastCanvas; + context = lastContext; + + lastContext.clearRect(0, 0, lastCanvas.width, lastCanvas.height); + } + + // globalConfig.smoothing.smoothMainCanvas = getDeviceDPI() < 1.5; + // globalConfig.smoothing.smoothMainCanvas = true; + + canvas.classList.toggle("smoothed", globalConfig.smoothing.smoothMainCanvas); + + // Oof, use :not() instead + canvas.classList.toggle("unsmoothed", !globalConfig.smoothing.smoothMainCanvas); + + if (globalConfig.smoothing.smoothMainCanvas) { + enableImageSmoothing(context); + } else { + disableImageSmoothing(context); + } + + this.root.canvas = canvas; + this.root.context = context; + + registerCanvas(canvas, context); + } + + /** + * Destructs the root, freeing all resources + */ + destruct() { + if (lastCanvas && lastCanvas.parentElement) { + lastCanvas.parentElement.removeChild(lastCanvas); + } + + this.root.destruct(); + delete this.root; + this.root = null; + this.app = null; + } + + tick(deltaMs) { + const root = this.root; + + // Extract current real time + root.time.updateRealtimeNow(); + + // Camera is always updated, no matter what + root.camera.update(deltaMs); + + if (!(G_IS_DEV && globalConfig.debug.manualTickOnly)) { + // Perform logic ticks + this.root.time.performTicks(deltaMs, this.boundInternalTick); + + // Update analytics + root.productionAnalytics.update(); + } + + // Update automatic save after everything finished + root.automaticSave.update(); + + return true; + } + + shouldRender() { + if (this.root.queue.requireRedraw) { + return true; + } + if (this.root.hud.shouldPauseRendering()) { + return false; + } + + // Do not render + if (!this.app.isRenderable()) { + return false; + } + + return true; + } + + updateLogic() { + const root = this.root; + + root.dynamicTickrate.beginTick(); + + if (G_IS_DEV && globalConfig.debug.disableLogicTicks) { + root.dynamicTickrate.endTick(); + return true; + } + + this.duringLogicUpdate = true; + + // Update entities, this removes destroyed entities + root.entityMgr.update(); + + // IMPORTANT: At this point, the game might be game over. Stop if this is the case + if (!this.root) { + logger.log("Root destructed, returning false"); + root.dynamicTickrate.endTick(); + + return false; + } + + root.systemMgr.update(); + // root.particleMgr.update(); + + this.duringLogicUpdate = false; + root.dynamicTickrate.endTick(); + return true; + } + + resize(w, h) { + this.root.gameWidth = w; + this.root.gameHeight = h; + resizeHighDPICanvas(this.root.canvas, w, h, globalConfig.smoothing.smoothMainCanvas); + this.root.signals.resized.dispatch(w, h); + this.root.queue.requireRedraw = true; + } + + postLoadHook() { + logger.log("Dispatching post load hook"); + this.root.signals.postLoadHook.dispatch(); + + if (!this.root.gameIsFresh) { + // Also dispatch game restored hook on restored savegames + this.root.signals.gameRestored.dispatch(); + } + + this.root.gameInitialized = true; + } + + draw() { + const root = this.root; + const systems = root.systemMgr.systems; + + this.root.dynamicTickrate.onFrameRendered(); + + if (!this.shouldRender()) { + // Always update hud tho + root.hud.update(); + return; + } + + this.root.signals.gameFrameStarted.dispatch(); + + root.queue.requireRedraw = false; + + // Gather context and save all state + const context = root.context; + context.save(); + if (G_IS_DEV) { + context.fillStyle = "#a10000"; + context.fillRect(0, 0, window.innerWidth * 3, window.innerHeight * 3); + } + + // Compute optimal zoom level and atlas scale + const zoomLevel = root.camera.zoomLevel; + const lowQuality = root.app.settings.getAllSettings().lowQualityTextures; + const effectiveZoomLevel = + (zoomLevel / globalConfig.assetsDpi) * getDeviceDPI() * globalConfig.assetsSharpness; + + let desiredAtlasScale = "0.25"; + if (effectiveZoomLevel > 0.8 && !lowQuality) { + desiredAtlasScale = ORIGINAL_SPRITE_SCALE; + } else if (effectiveZoomLevel > 0.4 && !lowQuality) { + desiredAtlasScale = "0.5"; + } + + // Construct parameters required for drawing + const params = new DrawParameters({ + context: context, + visibleRect: root.camera.getVisibleRect(), + desiredAtlasScale, + zoomLevel, + root: root, + }); + + if (G_IS_DEV && globalConfig.debug.testCulling) { + context.clearRect(0, 0, root.gameWidth, root.gameHeight); + } + + // Transform to world space + + if (G_IS_DEV && globalConfig.debug.testClipping) { + params.visibleRect = params.visibleRect.expandedInAllDirections( + -200 / this.root.camera.zoomLevel + ); + } + + root.camera.transform(context); + + assert(context.globalAlpha === 1.0, "Global alpha not 1 on frame start"); + + // Update hud + root.hud.update(); + + // Main rendering order + // ----- + + const desiredOverlayAlpha = this.root.camera.getIsMapOverlayActive() ? 1 : 0; + this.overlayAlpha = lerp(this.overlayAlpha, desiredOverlayAlpha, 0.25); + + if (this.overlayAlpha < 0.99) { + // Background (grid, resources, etc) + root.map.drawBackground(params); + + // Belt items + systems.belt.drawBeltItems(params); + + // Miner & Static map entities etc. + root.map.drawForeground(params); + + // HUB Overlay + systems.hub.draw(params); + + // Green wires overlay + root.hud.parts.wiresOverlay.draw(params); + + if (this.root.currentLayer === "wires") { + // Static map entities + root.map.drawWiresForegroundLayer(params); + } + } + + if (this.overlayAlpha > 0.01) { + // Map overview + context.globalAlpha = this.overlayAlpha; + root.map.drawOverlay(params); + context.globalAlpha = 1; + } + + if (G_IS_DEV) { + root.map.drawStaticEntityDebugOverlays(params); + } + + if (G_IS_DEV && globalConfig.debug.renderBeltPaths) { + systems.belt.drawBeltPathDebug(params); + } + + // END OF GAME CONTENT + // ----- + + // Finally, draw the hud. Nothing should come after that + root.hud.draw(params); + + assert(context.globalAlpha === 1.0, "Global alpha not 1 on frame end before restore"); + + // Restore to screen space + context.restore(); + + // Restore parameters + params.zoomLevel = 1; + params.desiredAtlasScale = ORIGINAL_SPRITE_SCALE; + params.visibleRect = new Rectangle(0, 0, this.root.gameWidth, this.root.gameHeight); + if (G_IS_DEV && globalConfig.debug.testClipping) { + params.visibleRect = params.visibleRect.expandedInAllDirections(-200); + } + + // Draw overlays, those are screen space + root.hud.drawOverlays(params); + + assert(context.globalAlpha === 1.0, "context.globalAlpha not 1 on frame end"); + + if (G_IS_DEV && globalConfig.debug.simulateSlowRendering) { + let sum = 0; + for (let i = 0; i < 1e8; ++i) { + sum += i; + } + if (Math.random() > 0.95) { + console.log(sum); + } + } + + if (G_IS_DEV && globalConfig.debug.showAtlasInfo) { + context.font = "13px GameFont"; + context.fillStyle = "blue"; + context.fillText( + "Atlas: " + + desiredAtlasScale + + " / Zoom: " + + round2Digits(zoomLevel) + + " / Effective Zoom: " + + round2Digits(effectiveZoomLevel), + 20, + 600 + ); + + const stats = this.root.buffers.getStats(); + context.fillText( + "Buffers: " + + stats.rootKeys + + " root keys, " + + stats.subKeys + + " sub keys / buffers / VRAM: " + + round2Digits(stats.vramBytes / (1024 * 1024)) + + " MB", + + 20, + 620 + ); + } + + if (G_IS_DEV && globalConfig.debug.testClipping) { + context.strokeStyle = "red"; + context.lineWidth = 1; + context.beginPath(); + context.rect(200, 200, this.root.gameWidth - 400, this.root.gameHeight - 400); + context.stroke(); + } + } +} diff --git a/src/js/game/dynamic_tickrate.js b/src/js/game/dynamic_tickrate.js index f289e2c1..3e29aba3 100644 --- a/src/js/game/dynamic_tickrate.js +++ b/src/js/game/dynamic_tickrate.js @@ -1,125 +1,125 @@ -import { GameRoot } from "./root"; -import { createLogger } from "../core/logging"; -import { globalConfig } from "../core/config"; -import { round3Digits } from "../core/utils"; - -const logger = createLogger("dynamic_tickrate"); - -const fpsAccumulationTime = 1000; - -export class DynamicTickrate { - /** - * - * @param {GameRoot} root - */ - constructor(root) { - this.root = root; - - this.currentTickStart = null; - this.capturedTicks = []; - this.averageTickDuration = 0; - - this.accumulatedFps = 0; - this.accumulatedFpsLastUpdate = 0; - - this.averageFps = 60; - - this.setTickRate(60); - - if (G_IS_DEV && globalConfig.debug.renderForTrailer) { - this.setTickRate(300); - } - } - - onFrameRendered() { - ++this.accumulatedFps; - - const now = performance.now(); - const timeDuration = now - this.accumulatedFpsLastUpdate; - if (timeDuration > fpsAccumulationTime) { - const avgFps = (this.accumulatedFps / fpsAccumulationTime) * 1000; - this.averageFps = avgFps; - this.accumulatedFps = 0; - this.accumulatedFpsLastUpdate = now; - } - } - - /** - * Sets the tick rate to N updates per second - * @param {number} rate - */ - setTickRate(rate) { - logger.log("Applying tick-rate of", rate); - this.currentTickRate = rate; - this.deltaMs = 1000.0 / this.currentTickRate; - this.deltaSeconds = 1.0 / this.currentTickRate; - } - - /** - * Increases the tick rate marginally - */ - increaseTickRate() { - if (G_IS_DEV && globalConfig.debug.renderForTrailer) { - return; - } - - const desiredFps = this.root.app.settings.getDesiredFps(); - this.setTickRate(Math.round(Math.min(desiredFps, this.currentTickRate * 1.2))); - } - - /** - * Decreases the tick rate marginally - */ - decreaseTickRate() { - if (G_IS_DEV && globalConfig.debug.renderForTrailer) { - return; - } - - const desiredFps = this.root.app.settings.getDesiredFps(); - this.setTickRate(Math.round(Math.max(desiredFps / 2, this.currentTickRate * 0.8))); - } - - /** - * Call whenever a tick began - */ - beginTick() { - assert(this.currentTickStart === null, "BeginTick called twice"); - this.currentTickStart = performance.now(); - - if (this.capturedTicks.length > this.currentTickRate * 2) { - // Take only a portion of the ticks - this.capturedTicks.sort(); - this.capturedTicks.splice(0, 10); - this.capturedTicks.splice(this.capturedTicks.length - 11, 10); - - let average = 0; - for (let i = 0; i < this.capturedTicks.length; ++i) { - average += this.capturedTicks[i]; - } - average /= this.capturedTicks.length; - - this.averageTickDuration = average; - - const desiredFps = this.root.app.settings.getDesiredFps(); - - if (this.averageFps > desiredFps * 0.9) { - // if (average < maxTickDuration) { - this.increaseTickRate(); - } else if (this.averageFps < desiredFps * 0.7) { - this.decreaseTickRate(); - } - - this.capturedTicks = []; - } - } - - /** - * Call whenever a tick ended - */ - endTick() { - assert(this.currentTickStart !== null, "EndTick called without BeginTick"); - const duration = performance.now() - this.currentTickStart; - this.capturedTicks.push(duration); - this.currentTickStart = null; - } -} +import { GameRoot } from "./root"; +import { createLogger } from "../core/logging"; +import { globalConfig } from "../core/config"; + +const logger = createLogger("dynamic_tickrate"); + +const fpsAccumulationTime = 1000; + +export class DynamicTickrate { + /** + * + * @param {GameRoot} root + */ + constructor(root) { + this.root = root; + + this.currentTickStart = null; + this.capturedTicks = []; + this.averageTickDuration = 0; + + this.accumulatedFps = 0; + this.accumulatedFpsLastUpdate = 0; + + this.averageFps = 60; + + this.setTickRate(this.root.app.settings.getDesiredFps()); + + if (G_IS_DEV && globalConfig.debug.renderForTrailer) { + this.setTickRate(300); + } + } + + onFrameRendered() { + ++this.accumulatedFps; + + const now = performance.now(); + const timeDuration = now - this.accumulatedFpsLastUpdate; + if (timeDuration > fpsAccumulationTime) { + const avgFps = (this.accumulatedFps / fpsAccumulationTime) * 1000; + this.averageFps = avgFps; + this.accumulatedFps = 0; + this.accumulatedFpsLastUpdate = now; + } + } + + /** + * Sets the tick rate to N updates per second + * @param {number} rate + */ + setTickRate(rate) { + logger.log("Applying tick-rate of", rate); + this.currentTickRate = rate; + this.deltaMs = 1000.0 / this.currentTickRate; + this.deltaSeconds = 1.0 / this.currentTickRate; + } + + /** + * Increases the tick rate marginally + */ + increaseTickRate() { + if (G_IS_DEV && globalConfig.debug.renderForTrailer) { + return; + } + + const desiredFps = this.root.app.settings.getDesiredFps(); + this.setTickRate(Math.round(Math.min(desiredFps, this.currentTickRate * 1.2))); + } + + /** + * Decreases the tick rate marginally + */ + decreaseTickRate() { + if (G_IS_DEV && globalConfig.debug.renderForTrailer) { + return; + } + + const desiredFps = this.root.app.settings.getDesiredFps(); + this.setTickRate(Math.round(Math.max(desiredFps / 2, this.currentTickRate * 0.8))); + } + + /** + * Call whenever a tick began + */ + beginTick() { + assert(this.currentTickStart === null, "BeginTick called twice"); + this.currentTickStart = performance.now(); + + if (this.capturedTicks.length > this.currentTickRate * 2) { + // Take only a portion of the ticks + this.capturedTicks.sort(); + this.capturedTicks.splice(0, 10); + this.capturedTicks.splice(this.capturedTicks.length - 11, 10); + + let average = 0; + for (let i = 0; i < this.capturedTicks.length; ++i) { + average += this.capturedTicks[i]; + } + average /= this.capturedTicks.length; + + this.averageTickDuration = average; + + const desiredFps = this.root.app.settings.getDesiredFps(); + + // Disabled for now: Dynamicall adjusting tick rate + // if (this.averageFps > desiredFps * 0.9) { + // // if (average < maxTickDuration) { + // this.increaseTickRate(); + // } else if (this.averageFps < desiredFps * 0.7) { + // this.decreaseTickRate(); + // } + + this.capturedTicks = []; + } + } + + /** + * Call whenever a tick ended + */ + endTick() { + assert(this.currentTickStart !== null, "EndTick called without BeginTick"); + const duration = performance.now() - this.currentTickStart; + this.capturedTicks.push(duration); + this.currentTickStart = null; + } +} diff --git a/src/js/game/entity.js b/src/js/game/entity.js index c86aa3b7..ca21a16d 100644 --- a/src/js/game/entity.js +++ b/src/js/game/entity.js @@ -3,7 +3,7 @@ import { DrawParameters } from "../core/draw_parameters"; import { Component } from "./component"; /* typehints:end */ -import { GameRoot, enumLayer } from "./root"; +import { GameRoot } from "./root"; import { globalConfig } from "../core/config"; import { enumDirectionToVector, enumDirectionToAngle } from "../core/vector"; import { BasicSerializableObject, types } from "../savegame/serialization"; @@ -36,8 +36,9 @@ export class Entity extends BasicSerializableObject { /** * On which layer this entity is + * @type {Layer} */ - this.layer = enumLayer.regular; + this.layer = "regular"; /** * Internal entity unique id, set by the @see EntityManager @@ -76,8 +77,7 @@ export class Entity extends BasicSerializableObject { static getSchema() { return { uid: types.uint, - components: types.keyValueMap(types.objData(gComponentRegistry)), - layer: types.enum(enumLayer), + components: types.keyValueMap(types.objData(gComponentRegistry), false), }; } @@ -162,6 +162,7 @@ export class Entity extends BasicSerializableObject { context.stroke(); } } + if (G_IS_DEV && staticComp && globalConfig.debug.showAcceptorEjectors) { const ejectorComp = this.components.ItemEjector; @@ -169,9 +170,6 @@ export class Entity extends BasicSerializableObject { const ejectorSprite = Loader.getSprite("sprites/debug/ejector_slot.png"); for (let i = 0; i < ejectorComp.slots.length; ++i) { const slot = ejectorComp.slots[i]; - if (slot.layer !== this.root.currentLayer) { - continue; - } const slotTile = staticComp.localTileToWorld(slot.pos); const direction = staticComp.localDirectionToWorld(slot.direction); const directionVector = enumDirectionToVector[direction]; @@ -191,12 +189,9 @@ export class Entity extends BasicSerializableObject { const acceptorComp = this.components.ItemAcceptor; if (acceptorComp) { - const acceptorSprite = Loader.getSprite("sprites/debug/acceptor_slot.png"); + const acceptorSprite = Loader.getSprite("sprites/misc/acceptor_slot.png"); for (let i = 0; i < acceptorComp.slots.length; ++i) { const slot = acceptorComp.slots[i]; - if (slot.layer !== this.root.currentLayer) { - continue; - } const slotTile = staticComp.localTileToWorld(slot.pos); for (let k = 0; k < slot.directions.length; ++k) { const direction = staticComp.localDirectionToWorld(slot.directions[k]); diff --git a/src/js/game/entity_components.js b/src/js/game/entity_components.js index 24430dd2..4a2241e3 100644 --- a/src/js/game/entity_components.js +++ b/src/js/game/entity_components.js @@ -1,70 +1,86 @@ -/* typehints:start */ -import { StaticMapEntityComponent } from "./components/static_map_entity"; -import { BeltComponent } from "./components/belt"; -import { ItemEjectorComponent } from "./components/item_ejector"; -import { ItemAcceptorComponent } from "./components/item_acceptor"; -import { MinerComponent } from "./components/miner"; -import { ItemProcessorComponent } from "./components/item_processor"; -import { ReplaceableMapEntityComponent } from "./components/replaceable_map_entity"; -import { UndergroundBeltComponent } from "./components/underground_belt"; -import { UnremovableComponent } from "./components/unremovable"; -import { HubComponent } from "./components/hub"; -import { StorageComponent } from "./components/storage"; -import { EnergyGeneratorComponent } from "./components/energy_generator"; -import { WiredPinsComponent } from "./components/wired_pins"; -import { EnergyConsumerComponent } from "./components/energy_consumer"; -/* typehints:end */ - -/** - * Typedefs for all entity components. These are not actually present on the entity, - * thus they are undefined by default - */ -export class EntityComponentStorage { - constructor() { - /* typehints:start */ - - /** @type {StaticMapEntityComponent} */ - this.StaticMapEntity; - - /** @type {BeltComponent} */ - this.Belt; - - /** @type {ItemEjectorComponent} */ - this.ItemEjector; - - /** @type {ItemAcceptorComponent} */ - this.ItemAcceptor; - - /** @type {MinerComponent} */ - this.Miner; - - /** @type {ItemProcessorComponent} */ - this.ItemProcessor; - - /** @type {ReplaceableMapEntityComponent} */ - this.ReplaceableMapEntity; - - /** @type {UndergroundBeltComponent} */ - this.UndergroundBelt; - - /** @type {UnremovableComponent} */ - this.Unremovable; - - /** @type {HubComponent} */ - this.Hub; - - /** @type {StorageComponent} */ - this.Storage; - - /** @type {EnergyGeneratorComponent} */ - this.EnergyGenerator; - - /** @type {WiredPinsComponent} */ - this.WiredPins; - - /** @type {EnergyConsumerComponent} */ - this.EnergyConsumer; - - /* typehints:end */ - } -} +/* typehints:start */ +import { BeltComponent } from "./components/belt"; +import { BeltUnderlaysComponent } from "./components/belt_underlays"; +import { HubComponent } from "./components/hub"; +import { ItemAcceptorComponent } from "./components/item_acceptor"; +import { ItemEjectorComponent } from "./components/item_ejector"; +import { ItemProcessorComponent } from "./components/item_processor"; +import { MinerComponent } from "./components/miner"; +import { StaticMapEntityComponent } from "./components/static_map_entity"; +import { StorageComponent } from "./components/storage"; +import { UndergroundBeltComponent } from "./components/underground_belt"; +import { WiredPinsComponent } from "./components/wired_pins"; +import { WireComponent } from "./components/wire"; +import { ConstantSignalComponent } from "./components/constant_signal"; +import { LogicGateComponent } from "./components/logic_gate"; +import { LeverComponent } from "./components/lever"; +import { WireTunnelComponent } from "./components/wire_tunnel"; +import { DisplayComponent } from "./components/display"; +import { BeltReaderComponent } from "./components/belt_reader"; +/* typehints:end */ + +/** + * Typedefs for all entity components. These are not actually present on the entity, + * thus they are undefined by default + */ +export class EntityComponentStorage { + constructor() { + /* typehints:start */ + + /** @type {StaticMapEntityComponent} */ + this.StaticMapEntity; + + /** @type {BeltComponent} */ + this.Belt; + + /** @type {ItemEjectorComponent} */ + this.ItemEjector; + + /** @type {ItemAcceptorComponent} */ + this.ItemAcceptor; + + /** @type {MinerComponent} */ + this.Miner; + + /** @type {ItemProcessorComponent} */ + this.ItemProcessor; + + /** @type {UndergroundBeltComponent} */ + this.UndergroundBelt; + + /** @type {HubComponent} */ + this.Hub; + + /** @type {StorageComponent} */ + this.Storage; + + /** @type {WiredPinsComponent} */ + this.WiredPins; + + /** @type {BeltUnderlaysComponent} */ + this.BeltUnderlays; + + /** @type {WireComponent} */ + this.Wire; + + /** @type {ConstantSignalComponent} */ + this.ConstantSignal; + + /** @type {LogicGateComponent} */ + this.LogicGate; + + /** @type {LeverComponent} */ + this.Lever; + + /** @type {WireTunnelComponent} */ + this.WireTunnel; + + /** @type {DisplayComponent} */ + this.Display; + + /** @type {BeltReaderComponent} */ + this.BeltReader; + + /* typehints:end */ + } +} diff --git a/src/js/game/game_system_manager.js b/src/js/game/game_system_manager.js index ed9d1155..b0ae46f2 100644 --- a/src/js/game/game_system_manager.js +++ b/src/js/game/game_system_manager.js @@ -1,137 +1,175 @@ -/* typehints:start */ -import { GameRoot } from "./root"; -/* typehints:end */ - -import { createLogger } from "../core/logging"; -import { BeltSystem } from "./systems/belt"; -import { ItemEjectorSystem } from "./systems/item_ejector"; -import { MapResourcesSystem } from "./systems/map_resources"; -import { MinerSystem } from "./systems/miner"; -import { ItemProcessorSystem } from "./systems/item_processor"; -import { UndergroundBeltSystem } from "./systems/underground_belt"; -import { HubSystem } from "./systems/hub"; -import { StaticMapEntitySystem } from "./systems/static_map_entity"; -import { ItemAcceptorSystem } from "./systems/item_acceptor"; -import { StorageSystem } from "./systems/storage"; -import { EnergyGeneratorSystem } from "./systems/energy_generator"; -import { WiredPinsSystem } from "./systems/wired_pins"; -import { EnergyConsumerSystem } from "./systems/energy_consumer"; - -const logger = createLogger("game_system_manager"); - -export class GameSystemManager { - /** - * - * @param {GameRoot} root - */ - constructor(root) { - this.root = root; - - this.systems = { - /* typehints:start */ - /** @type {BeltSystem} */ - belt: null, - - /** @type {ItemEjectorSystem} */ - itemEjector: null, - - /** @type {MapResourcesSystem} */ - mapResources: null, - - /** @type {MinerSystem} */ - miner: null, - - /** @type {ItemProcessorSystem} */ - itemProcessor: null, - - /** @type {UndergroundBeltSystem} */ - undergroundBelt: null, - - /** @type {HubSystem} */ - hub: null, - - /** @type {StaticMapEntitySystem} */ - staticMapEntities: null, - - /** @type {ItemAcceptorSystem} */ - itemAcceptor: null, - - /** @type {StorageSystem} */ - storage: null, - - /** @type {EnergyGeneratorSystem} */ - energyGenerator: null, - - /** @type {WiredPinsSystem} */ - wiredPins: null, - - /** @type {EnergyConsumerSystem} */ - energyConsumer: null, - - /* typehints:end */ - }; - this.systemUpdateOrder = []; - - this.internalInitSystems(); - } - - /** - * Initializes all systems - */ - internalInitSystems() { - const add = (id, systemClass) => { - this.systems[id] = new systemClass(this.root); - this.systemUpdateOrder.push(id); - }; - - // Order is important! - - add("belt", BeltSystem); - - add("undergroundBelt", UndergroundBeltSystem); - - add("miner", MinerSystem); - - add("storage", StorageSystem); - - add("itemProcessor", ItemProcessorSystem); - - add("itemEjector", ItemEjectorSystem); - - add("mapResources", MapResourcesSystem); - - add("hub", HubSystem); - - add("energyGenerator", EnergyGeneratorSystem); - - add("staticMapEntities", StaticMapEntitySystem); - - add("wiredPins", WiredPinsSystem); - - add("energyConsumer", EnergyConsumerSystem); - - // IMPORTANT: Must be after belt system since belt system can change the - // orientation of an entity after it is placed -> the item acceptor cache - // then would be invalid - add("itemAcceptor", ItemAcceptorSystem); - - logger.log("📦 There are", this.systemUpdateOrder.length, "game systems"); - } - - /** - * Updates all systems - */ - update() { - for (let i = 0; i < this.systemUpdateOrder.length; ++i) { - const system = this.systems[this.systemUpdateOrder[i]]; - system.update(); - } - } - - refreshCaches() { - for (let i = 0; i < this.systemUpdateOrder.length; ++i) { - const system = this.systems[this.systemUpdateOrder[i]]; - system.refreshCaches(); - } - } -} +/* typehints:start */ +import { GameRoot } from "./root"; +/* typehints:end */ + +import { createLogger } from "../core/logging"; +import { BeltSystem } from "./systems/belt"; +import { ItemEjectorSystem } from "./systems/item_ejector"; +import { MapResourcesSystem } from "./systems/map_resources"; +import { MinerSystem } from "./systems/miner"; +import { ItemProcessorSystem } from "./systems/item_processor"; +import { UndergroundBeltSystem } from "./systems/underground_belt"; +import { HubSystem } from "./systems/hub"; +import { StaticMapEntitySystem } from "./systems/static_map_entity"; +import { ItemAcceptorSystem } from "./systems/item_acceptor"; +import { StorageSystem } from "./systems/storage"; +import { WiredPinsSystem } from "./systems/wired_pins"; +import { BeltUnderlaysSystem } from "./systems/belt_underlays"; +import { WireSystem } from "./systems/wire"; +import { ConstantSignalSystem } from "./systems/constant_signal"; +import { LogicGateSystem } from "./systems/logic_gate"; +import { LeverSystem } from "./systems/lever"; +import { DisplaySystem } from "./systems/display"; +import { ItemProcessorOverlaysSystem } from "./systems/item_processor_overlays"; +import { BeltReaderSystem } from "./systems/belt_reader"; + +const logger = createLogger("game_system_manager"); + +export class GameSystemManager { + /** + * + * @param {GameRoot} root + */ + constructor(root) { + this.root = root; + + this.systems = { + /* typehints:start */ + /** @type {BeltSystem} */ + belt: null, + + /** @type {ItemEjectorSystem} */ + itemEjector: null, + + /** @type {MapResourcesSystem} */ + mapResources: null, + + /** @type {MinerSystem} */ + miner: null, + + /** @type {ItemProcessorSystem} */ + itemProcessor: null, + + /** @type {UndergroundBeltSystem} */ + undergroundBelt: null, + + /** @type {HubSystem} */ + hub: null, + + /** @type {StaticMapEntitySystem} */ + staticMapEntities: null, + + /** @type {ItemAcceptorSystem} */ + itemAcceptor: null, + + /** @type {StorageSystem} */ + storage: null, + + /** @type {WiredPinsSystem} */ + wiredPins: null, + + /** @type {BeltUnderlaysSystem} */ + beltUnderlays: null, + + /** @type {WireSystem} */ + wire: null, + + /** @type {ConstantSignalSystem} */ + constantSignal: null, + + /** @type {LogicGateSystem} */ + logicGate: null, + + /** @type {LeverSystem} */ + lever: null, + + /** @type {DisplaySystem} */ + display: null, + + /** @type {ItemProcessorOverlaysSystem} */ + itemProcessorOverlays: null, + + /** @type {BeltReaderSystem} */ + beltReader: null, + + /* typehints:end */ + }; + this.systemUpdateOrder = []; + + this.internalInitSystems(); + } + + /** + * Initializes all systems + */ + internalInitSystems() { + const add = (id, systemClass) => { + this.systems[id] = new systemClass(this.root); + this.systemUpdateOrder.push(id); + }; + + // Order is important! + + // IMPORTANT: Item acceptor must be before the belt, because it may not tick after the belt + // has put in the item into the acceptor animation, otherwise its off + add("itemAcceptor", ItemAcceptorSystem); + + add("belt", BeltSystem); + + add("undergroundBelt", UndergroundBeltSystem); + + add("miner", MinerSystem); + + add("storage", StorageSystem); + + add("itemProcessor", ItemProcessorSystem); + + add("itemEjector", ItemEjectorSystem); + + add("mapResources", MapResourcesSystem); + + add("hub", HubSystem); + + add("staticMapEntities", StaticMapEntitySystem); + + add("wiredPins", WiredPinsSystem); + + add("beltUnderlays", BeltUnderlaysSystem); + + add("constantSignal", ConstantSignalSystem); + + // WIRES section + add("lever", LeverSystem); + + // Wires must be before all gate, signal etc logic! + add("wire", WireSystem); + + // IMPORTANT: We have 2 phases: In phase 1 we compute the output values of all gates, + // processors etc. In phase 2 we propagate it through the wires network + add("logicGate", LogicGateSystem); + add("beltReader", BeltReaderSystem); + + add("display", DisplaySystem); + + add("itemProcessorOverlays", ItemProcessorOverlaysSystem); + + logger.log("📦 There are", this.systemUpdateOrder.length, "game systems"); + } + + /** + * Updates all systems + */ + update() { + for (let i = 0; i < this.systemUpdateOrder.length; ++i) { + const system = this.systems[this.systemUpdateOrder[i]]; + system.update(); + } + } + + refreshCaches() { + for (let i = 0; i < this.systemUpdateOrder.length; ++i) { + const system = this.systems[this.systemUpdateOrder[i]]; + system.refreshCaches(); + } + } +} diff --git a/src/js/game/game_system_with_filter.js b/src/js/game/game_system_with_filter.js index 82ab4c22..7b1ffbf0 100644 --- a/src/js/game/game_system_with_filter.js +++ b/src/js/game/game_system_with_filter.js @@ -3,11 +3,10 @@ import { Component } from "./component"; import { Entity } from "./entity"; /* typehints:end */ -import { GameRoot, enumLayer } from "./root"; +import { GameRoot } from "./root"; import { GameSystem } from "./game_system"; import { arrayDelete, arrayDeleteValue } from "../core/utils"; -import { DrawParameters } from "../core/draw_parameters"; -import { globalConfig } from "../core/config"; + export class GameSystemWithFilter extends GameSystem { /** * Constructs a new game system with the given component filter. It will process @@ -35,88 +34,6 @@ export class GameSystemWithFilter extends GameSystem { this.root.signals.bulkOperationFinished.add(this.refreshCaches, this); } - /** - * Calls a function for each matching entity on the screen, useful for drawing them - * @param {DrawParameters} parameters - * @param {function} callback - * @param {enumLayer=} layerFilter Can be null for no filter - */ - forEachMatchingEntityOnScreen(parameters, callback, layerFilter = null) { - const cullRange = parameters.visibleRect.toTileCullRectangle(); - if (this.allEntities.length < 100) { - // So, its much quicker to simply perform per-entity checking - - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - if (cullRange.containsRect(entity.components.StaticMapEntity.getTileSpaceBounds())) { - if (!layerFilter || entity.layer === layerFilter) { - callback(parameters, entity); - } - } - } - return; - } - - const top = cullRange.top(); - const right = cullRange.right(); - const bottom = cullRange.bottom(); - const left = cullRange.left(); - - const border = 1; - const minY = top - border; - const maxY = bottom + border; - const minX = left - border; - const maxX = right + border - 1; - - const map = this.root.map; - - let seenUids = new Set(); - - const chunkStartX = Math.floor(minX / globalConfig.mapChunkSize); - const chunkStartY = Math.floor(minY / globalConfig.mapChunkSize); - - const chunkEndX = Math.ceil(maxX / globalConfig.mapChunkSize); - const chunkEndY = Math.ceil(maxY / globalConfig.mapChunkSize); - - const requiredComponents = this.requiredComponentIds; - - // Render y from top down for proper blending - for (let chunkX = chunkStartX; chunkX <= chunkEndX; ++chunkX) { - for (let chunkY = chunkStartY; chunkY <= chunkEndY; ++chunkY) { - const chunk = map.getChunk(chunkX, chunkY, false); - if (!chunk) { - continue; - } - - // BIG TODO: CULLING ON AN ENTITY BASIS - - const entities = chunk.containedEntities; - entityLoop: for (let i = 0; i < entities.length; ++i) { - const entity = entities[i]; - - // Avoid drawing non-layer contents - if (layerFilter && entity.layer !== layerFilter) { - continue; - } - - // Avoid drawing twice - if (seenUids.has(entity.uid)) { - continue; - } - - seenUids.add(entity.uid); - - for (let i = 0; i < requiredComponents.length; ++i) { - if (!entity.components[requiredComponents[i]]) { - continue entityLoop; - } - } - callback(parameters, entity); - } - } - } - } - /** * @param {Entity} entity */ diff --git a/src/js/game/hub_goals.js b/src/js/game/hub_goals.js index 612bc124..71817ebd 100644 --- a/src/js/game/hub_goals.js +++ b/src/js/game/hub_goals.js @@ -1,454 +1,448 @@ -import { globalConfig } from "../core/config"; -import { queryParamOptions } from "../core/query_parameters"; -import { clamp, findNiceIntegerValue, randomChoice, randomInt } from "../core/utils"; -import { BasicSerializableObject, types } from "../savegame/serialization"; -import { enumColors } from "./colors"; -import { enumItemProcessorTypes } from "./components/item_processor"; -import { GameRoot, enumLayer } from "./root"; -import { enumSubShape, ShapeDefinition } from "./shape_definition"; -import { enumHubGoalRewards, tutorialGoals } from "./tutorial_goals"; -import { UPGRADES, blueprintShape } from "./upgrades"; - -export class HubGoals extends BasicSerializableObject { - static getId() { - return "HubGoals"; - } - - static getSchema() { - return { - level: types.uint, - storedShapes: types.keyValueMap(types.uint), - upgradeLevels: types.keyValueMap(types.uint), - - currentGoal: types.structured({ - definition: types.knownType(ShapeDefinition), - required: types.uint, - reward: types.nullable(types.enum(enumHubGoalRewards)), - }), - }; - } - - deserialize(data) { - const errorCode = super.deserialize(data); - if (errorCode) { - return errorCode; - } - - // Compute gained rewards - for (let i = 0; i < this.level - 1; ++i) { - if (i < tutorialGoals.length) { - const reward = tutorialGoals[i].reward; - this.gainedRewards[reward] = (this.gainedRewards[reward] || 0) + 1; - } - } - - // Compute upgrade improvements - for (const upgradeId in UPGRADES) { - const upgradeHandle = UPGRADES[upgradeId]; - const level = this.upgradeLevels[upgradeId] || 0; - let totalImprovement = upgradeHandle.baseValue || 1; - for (let i = 0; i < level; ++i) { - totalImprovement += upgradeHandle.tiers[i].improvement; - } - this.upgradeImprovements[upgradeId] = totalImprovement; - } - - // Compute current goal - const goal = tutorialGoals[this.level - 1]; - if (goal) { - this.currentGoal = { - /** @type {ShapeDefinition} */ - definition: this.root.shapeDefinitionMgr.getShapeFromShortKey(goal.shape), - required: goal.required, - reward: goal.reward, - }; - } - } - - /** - * @param {GameRoot} root - */ - constructor(root) { - super(); - - this.root = root; - - this.level = 1; - - /** - * Which story rewards we already gained - * @type {Object.} - */ - this.gainedRewards = {}; - - /** - * Mapping from shape hash -> amount - * @type {Object} - */ - this.storedShapes = {}; - - /** - * Stores the levels for all upgrades - * @type {Object} - */ - this.upgradeLevels = {}; - - /** - * Stores the improvements for all upgrades - * @type {Object} - */ - this.upgradeImprovements = {}; - for (const key in UPGRADES) { - this.upgradeImprovements[key] = UPGRADES[key].baseValue || 1; - } - - this.createNextGoal(); - - // Allow quickly switching goals in dev mode - if (G_IS_DEV) { - window.addEventListener("keydown", ev => { - if (ev.key === "b") { - // root is not guaranteed to exist within ~0.5s after loading in - if (this.root && this.root.app && this.root.app.gameAnalytics) { - this.onGoalCompleted(); - } - } - }); - } - } - - /** - * Returns how much of the current shape is stored - * @param {ShapeDefinition} definition - * @returns {number} - */ - getShapesStored(definition) { - return this.storedShapes[definition.getHash()] || 0; - } - - /** - * @param {string} key - * @param {number} amount - */ - takeShapeByKey(key, amount) { - assert(this.getShapesStoredByKey(key) >= amount, "Can not afford: " + key + " x " + amount); - assert(amount >= 0, "Amount < 0 for " + key); - assert(Number.isInteger(amount), "Invalid amount: " + amount); - this.storedShapes[key] = (this.storedShapes[key] || 0) - amount; - return; - } - - /** - * Returns how much of the current shape is stored - * @param {string} key - * @returns {number} - */ - getShapesStoredByKey(key) { - return this.storedShapes[key] || 0; - } - - /** - * Returns how much of the current goal was already delivered - */ - getCurrentGoalDelivered() { - return this.getShapesStored(this.currentGoal.definition); - } - - /** - * Returns the current level of a given upgrade - * @param {string} upgradeId - */ - getUpgradeLevel(upgradeId) { - return this.upgradeLevels[upgradeId] || 0; - } - - /** - * Returns whether the given reward is already unlocked - * @param {enumHubGoalRewards} reward - */ - isRewardUnlocked(reward) { - if (G_IS_DEV && globalConfig.debug.allBuildingsUnlocked) { - return true; - } - return !!this.gainedRewards[reward]; - } - - /** - * Handles the given definition, by either accounting it towards the - * goal or otherwise granting some points - * @param {ShapeDefinition} definition - */ - handleDefinitionDelivered(definition) { - const hash = definition.getHash(); - this.storedShapes[hash] = (this.storedShapes[hash] || 0) + 1; - - this.root.signals.shapeDelivered.dispatch(definition); - - // Check if we have enough for the next level - const targetHash = this.currentGoal.definition.getHash(); - if ( - this.storedShapes[targetHash] >= this.currentGoal.required || - (G_IS_DEV && globalConfig.debug.rewardsInstant) - ) { - this.onGoalCompleted(); - } - } - - /** - * Creates the next goal - */ - createNextGoal() { - const storyIndex = this.level - 1; - if (storyIndex < tutorialGoals.length) { - const { shape, required, reward } = tutorialGoals[storyIndex]; - this.currentGoal = { - /** @type {ShapeDefinition} */ - definition: this.root.shapeDefinitionMgr.getShapeFromShortKey(shape), - required, - reward, - }; - return; - } - - this.currentGoal = { - /** @type {ShapeDefinition} */ - definition: this.createRandomShape(), - required: 10000 + findNiceIntegerValue(this.level * 2000), - reward: enumHubGoalRewards.no_reward_freeplay, - }; - } - - /** - * Called when the level was completed - */ - onGoalCompleted() { - const reward = this.currentGoal.reward; - this.gainedRewards[reward] = (this.gainedRewards[reward] || 0) + 1; - - this.root.app.gameAnalytics.handleLevelCompleted(this.level); - ++this.level; - this.createNextGoal(); - - this.root.signals.storyGoalCompleted.dispatch(this.level - 1, reward); - } - - /** - * Returns whether we are playing in free-play - */ - isFreePlay() { - return this.level >= tutorialGoals.length; - } - - /** - * Returns whether a given upgrade can be unlocked - * @param {string} upgradeId - */ - canUnlockUpgrade(upgradeId) { - const handle = UPGRADES[upgradeId]; - const currentLevel = this.getUpgradeLevel(upgradeId); - - if (currentLevel >= handle.tiers.length) { - // Max level - return false; - } - - if (G_IS_DEV && globalConfig.debug.upgradesNoCost) { - return true; - } - - const tierData = handle.tiers[currentLevel]; - - for (let i = 0; i < tierData.required.length; ++i) { - const requirement = tierData.required[i]; - if ((this.storedShapes[requirement.shape] || 0) < requirement.amount) { - return false; - } - } - return true; - } - - /** - * Returns the number of available upgrades - * @returns {number} - */ - getAvailableUpgradeCount() { - let count = 0; - for (const upgradeId in UPGRADES) { - if (this.canUnlockUpgrade(upgradeId)) { - ++count; - } - } - return count; - } - - /** - * Tries to unlock the given upgrade - * @param {string} upgradeId - * @returns {boolean} - */ - tryUnlockUpgrade(upgradeId) { - if (!this.canUnlockUpgrade(upgradeId)) { - return false; - } - - const handle = UPGRADES[upgradeId]; - const currentLevel = this.getUpgradeLevel(upgradeId); - - const tierData = handle.tiers[currentLevel]; - if (!tierData) { - return false; - } - - if (G_IS_DEV && globalConfig.debug.upgradesNoCost) { - // Dont take resources - } else { - for (let i = 0; i < tierData.required.length; ++i) { - const requirement = tierData.required[i]; - - // Notice: Don't have to check for hash here - this.storedShapes[requirement.shape] -= requirement.amount; - } - } - - this.upgradeLevels[upgradeId] = (this.upgradeLevels[upgradeId] || 0) + 1; - this.upgradeImprovements[upgradeId] += tierData.improvement; - - this.root.signals.upgradePurchased.dispatch(upgradeId); - - this.root.app.gameAnalytics.handleUpgradeUnlocked(upgradeId, currentLevel); - - return true; - } - - /** - * @returns {ShapeDefinition} - */ - createRandomShape() { - const layerCount = clamp(this.level / 25, 2, 4); - /** @type {Array} */ - let layers = []; - - // @ts-ignore - const randomColor = () => randomChoice(Object.values(enumColors)); - // @ts-ignore - const randomShape = () => randomChoice(Object.values(enumSubShape)); - - let anyIsMissingTwo = false; - - for (let i = 0; i < layerCount; ++i) { - /** @type {import("./shape_definition").ShapeLayer} */ - const layer = [null, null, null, null]; - - for (let quad = 0; quad < 4; ++quad) { - layer[quad] = { - subShape: randomShape(), - color: randomColor(), - }; - } - - // Sometimes shapes are missing - if (Math.random() > 0.85) { - layer[randomInt(0, 3)] = null; - } - - // Sometimes they actually are missing *two* ones! - // Make sure at max only one layer is missing it though, otherwise we could - // create an uncreateable shape - if (Math.random() > 0.95 && !anyIsMissingTwo) { - layer[randomInt(0, 3)] = null; - anyIsMissingTwo = true; - } - - layers.push(layer); - } - - const definition = new ShapeDefinition({ layers }); - return this.root.shapeDefinitionMgr.registerOrReturnHandle(definition); - } - - ////////////// HELPERS - - /** - * Belt speed - * @param {enumLayer} layer - * @returns {number} items / sec - */ - getBeltBaseSpeed(layer) { - if (layer === enumLayer.wires) { - return globalConfig.wiresSpeedItemsPerSecond; - } - return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt; - } - - /** - * Underground belt speed - * @returns {number} items / sec - */ - getUndergroundBeltBaseSpeed() { - return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt; - } - - /** - * Miner speed - * @returns {number} items / sec - */ - getMinerBaseSpeed() { - return globalConfig.minerSpeedItemsPerSecond * this.upgradeImprovements.miner; - } - - /** - * Processor speed - * @param {enumItemProcessorTypes} processorType - * @returns {number} items / sec - */ - getProcessorBaseSpeed(processorType) { - switch (processorType) { - case enumItemProcessorTypes.splitterWires: - return globalConfig.wiresSpeedItemsPerSecond * 2; - - case enumItemProcessorTypes.trash: - case enumItemProcessorTypes.hub: - return 1e30; - case enumItemProcessorTypes.splitter: - return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt * 2; - - case enumItemProcessorTypes.mixer: - case enumItemProcessorTypes.painter: - case enumItemProcessorTypes.painterDouble: - case enumItemProcessorTypes.painterQuad: { - assert( - globalConfig.buildingSpeeds[processorType], - "Processor type has no speed set in globalConfig.buildingSpeeds: " + processorType - ); - return ( - globalConfig.beltSpeedItemsPerSecond * - this.upgradeImprovements.painting * - globalConfig.buildingSpeeds[processorType] - ); - } - - case enumItemProcessorTypes.cutter: - case enumItemProcessorTypes.cutterQuad: - case enumItemProcessorTypes.rotater: - case enumItemProcessorTypes.rotaterCCW: - case enumItemProcessorTypes.stacker: { - assert( - globalConfig.buildingSpeeds[processorType], - "Processor type has no speed set in globalConfig.buildingSpeeds: " + processorType - ); - return ( - globalConfig.beltSpeedItemsPerSecond * - this.upgradeImprovements.processors * - globalConfig.buildingSpeeds[processorType] - ); - } - case enumItemProcessorTypes.advancedProcessor: { - return globalConfig.beltSpeedItemsPerSecond * globalConfig.buildingSpeeds[processorType]; - } - default: - assertAlways(false, "invalid processor type: " + processorType); - } - - return 1 / globalConfig.beltSpeedItemsPerSecond; - } -} +import { globalConfig } from "../core/config"; +import { clamp, findNiceIntegerValue, randomChoice, randomInt } from "../core/utils"; +import { BasicSerializableObject, types } from "../savegame/serialization"; +import { enumColors } from "./colors"; +import { enumItemProcessorTypes } from "./components/item_processor"; +import { GameRoot } from "./root"; +import { enumSubShape, ShapeDefinition } from "./shape_definition"; +import { enumHubGoalRewards, tutorialGoals } from "./tutorial_goals"; +import { UPGRADES } from "./upgrades"; + +export class HubGoals extends BasicSerializableObject { + static getId() { + return "HubGoals"; + } + + static getSchema() { + return { + level: types.uint, + storedShapes: types.keyValueMap(types.uint), + upgradeLevels: types.keyValueMap(types.uint), + + currentGoal: types.structured({ + definition: types.knownType(ShapeDefinition), + required: types.uint, + reward: types.nullable(types.enum(enumHubGoalRewards)), + }), + }; + } + + deserialize(data) { + const errorCode = super.deserialize(data); + if (errorCode) { + return errorCode; + } + + // Compute gained rewards + for (let i = 0; i < this.level - 1; ++i) { + if (i < tutorialGoals.length) { + const reward = tutorialGoals[i].reward; + this.gainedRewards[reward] = (this.gainedRewards[reward] || 0) + 1; + } + } + + // Compute upgrade improvements + for (const upgradeId in UPGRADES) { + const upgradeHandle = UPGRADES[upgradeId]; + const level = this.upgradeLevels[upgradeId] || 0; + let totalImprovement = upgradeHandle.baseValue || 1; + for (let i = 0; i < level; ++i) { + totalImprovement += upgradeHandle.tiers[i].improvement; + } + this.upgradeImprovements[upgradeId] = totalImprovement; + } + + // Compute current goal + const goal = tutorialGoals[this.level - 1]; + if (goal) { + this.currentGoal = { + /** @type {ShapeDefinition} */ + definition: this.root.shapeDefinitionMgr.getShapeFromShortKey(goal.shape), + required: goal.required, + reward: goal.reward, + }; + } + } + + /** + * @param {GameRoot} root + */ + constructor(root) { + super(); + + this.root = root; + + this.level = 1; + + /** + * Which story rewards we already gained + * @type {Object.} + */ + this.gainedRewards = {}; + + /** + * Mapping from shape hash -> amount + * @type {Object} + */ + this.storedShapes = {}; + + /** + * Stores the levels for all upgrades + * @type {Object} + */ + this.upgradeLevels = {}; + + /** + * Stores the improvements for all upgrades + * @type {Object} + */ + this.upgradeImprovements = {}; + for (const key in UPGRADES) { + this.upgradeImprovements[key] = UPGRADES[key].baseValue || 1; + } + + this.createNextGoal(); + + // Allow quickly switching goals in dev mode + if (G_IS_DEV) { + window.addEventListener("keydown", ev => { + if (ev.key === "b") { + // root is not guaranteed to exist within ~0.5s after loading in + if (this.root && this.root.app && this.root.app.gameAnalytics) { + this.onGoalCompleted(); + } + } + }); + } + } + + /** + * Returns how much of the current shape is stored + * @param {ShapeDefinition} definition + * @returns {number} + */ + getShapesStored(definition) { + return this.storedShapes[definition.getHash()] || 0; + } + + /** + * @param {string} key + * @param {number} amount + */ + takeShapeByKey(key, amount) { + assert(this.getShapesStoredByKey(key) >= amount, "Can not afford: " + key + " x " + amount); + assert(amount >= 0, "Amount < 0 for " + key); + assert(Number.isInteger(amount), "Invalid amount: " + amount); + this.storedShapes[key] = (this.storedShapes[key] || 0) - amount; + return; + } + + /** + * Returns how much of the current shape is stored + * @param {string} key + * @returns {number} + */ + getShapesStoredByKey(key) { + return this.storedShapes[key] || 0; + } + + /** + * Returns how much of the current goal was already delivered + */ + getCurrentGoalDelivered() { + return this.getShapesStored(this.currentGoal.definition); + } + + /** + * Returns the current level of a given upgrade + * @param {string} upgradeId + */ + getUpgradeLevel(upgradeId) { + return this.upgradeLevels[upgradeId] || 0; + } + + /** + * Returns whether the given reward is already unlocked + * @param {enumHubGoalRewards} reward + */ + isRewardUnlocked(reward) { + if (G_IS_DEV && globalConfig.debug.allBuildingsUnlocked) { + return true; + } + return !!this.gainedRewards[reward]; + } + + /** + * Handles the given definition, by either accounting it towards the + * goal or otherwise granting some points + * @param {ShapeDefinition} definition + */ + handleDefinitionDelivered(definition) { + const hash = definition.getHash(); + this.storedShapes[hash] = (this.storedShapes[hash] || 0) + 1; + + this.root.signals.shapeDelivered.dispatch(definition); + + // Check if we have enough for the next level + const targetHash = this.currentGoal.definition.getHash(); + if ( + this.storedShapes[targetHash] >= this.currentGoal.required || + (G_IS_DEV && globalConfig.debug.rewardsInstant) + ) { + this.onGoalCompleted(); + } + } + + /** + * Creates the next goal + */ + createNextGoal() { + const storyIndex = this.level - 1; + if (storyIndex < tutorialGoals.length) { + const { shape, required, reward } = tutorialGoals[storyIndex]; + this.currentGoal = { + /** @type {ShapeDefinition} */ + definition: this.root.shapeDefinitionMgr.getShapeFromShortKey(shape), + required, + reward, + }; + return; + } + + this.currentGoal = { + /** @type {ShapeDefinition} */ + definition: this.createRandomShape(), + required: 10000 + findNiceIntegerValue(this.level * 2000), + reward: enumHubGoalRewards.no_reward_freeplay, + }; + } + + /** + * Called when the level was completed + */ + onGoalCompleted() { + const reward = this.currentGoal.reward; + this.gainedRewards[reward] = (this.gainedRewards[reward] || 0) + 1; + + this.root.app.gameAnalytics.handleLevelCompleted(this.level); + ++this.level; + this.createNextGoal(); + + this.root.signals.storyGoalCompleted.dispatch(this.level - 1, reward); + } + + /** + * Returns whether we are playing in free-play + */ + isFreePlay() { + return this.level >= tutorialGoals.length; + } + + /** + * Returns whether a given upgrade can be unlocked + * @param {string} upgradeId + */ + canUnlockUpgrade(upgradeId) { + const handle = UPGRADES[upgradeId]; + const currentLevel = this.getUpgradeLevel(upgradeId); + + if (currentLevel >= handle.tiers.length) { + // Max level + return false; + } + + if (G_IS_DEV && globalConfig.debug.upgradesNoCost) { + return true; + } + + const tierData = handle.tiers[currentLevel]; + + for (let i = 0; i < tierData.required.length; ++i) { + const requirement = tierData.required[i]; + if ((this.storedShapes[requirement.shape] || 0) < requirement.amount) { + return false; + } + } + return true; + } + + /** + * Returns the number of available upgrades + * @returns {number} + */ + getAvailableUpgradeCount() { + let count = 0; + for (const upgradeId in UPGRADES) { + if (this.canUnlockUpgrade(upgradeId)) { + ++count; + } + } + return count; + } + + /** + * Tries to unlock the given upgrade + * @param {string} upgradeId + * @returns {boolean} + */ + tryUnlockUpgrade(upgradeId) { + if (!this.canUnlockUpgrade(upgradeId)) { + return false; + } + + const handle = UPGRADES[upgradeId]; + const currentLevel = this.getUpgradeLevel(upgradeId); + + const tierData = handle.tiers[currentLevel]; + if (!tierData) { + return false; + } + + if (G_IS_DEV && globalConfig.debug.upgradesNoCost) { + // Dont take resources + } else { + for (let i = 0; i < tierData.required.length; ++i) { + const requirement = tierData.required[i]; + + // Notice: Don't have to check for hash here + this.storedShapes[requirement.shape] -= requirement.amount; + } + } + + this.upgradeLevels[upgradeId] = (this.upgradeLevels[upgradeId] || 0) + 1; + this.upgradeImprovements[upgradeId] += tierData.improvement; + + this.root.signals.upgradePurchased.dispatch(upgradeId); + + this.root.app.gameAnalytics.handleUpgradeUnlocked(upgradeId, currentLevel); + + return true; + } + + /** + * @returns {ShapeDefinition} + */ + createRandomShape() { + const layerCount = clamp(this.level / 25, 2, 4); + /** @type {Array} */ + let layers = []; + + const randomColor = () => randomChoice(Object.values(enumColors)); + const randomShape = () => randomChoice(Object.values(enumSubShape)); + + let anyIsMissingTwo = false; + + for (let i = 0; i < layerCount; ++i) { + /** @type {import("./shape_definition").ShapeLayer} */ + const layer = [null, null, null, null]; + + for (let quad = 0; quad < 4; ++quad) { + layer[quad] = { + subShape: randomShape(), + color: randomColor(), + }; + } + + // Sometimes shapes are missing + if (Math.random() > 0.85) { + layer[randomInt(0, 3)] = null; + } + + // Sometimes they actually are missing *two* ones! + // Make sure at max only one layer is missing it though, otherwise we could + // create an uncreateable shape + if (Math.random() > 0.95 && !anyIsMissingTwo) { + layer[randomInt(0, 3)] = null; + anyIsMissingTwo = true; + } + + layers.push(layer); + } + + const definition = new ShapeDefinition({ layers }); + return this.root.shapeDefinitionMgr.registerOrReturnHandle(definition); + } + + ////////////// HELPERS + + /** + * Belt speed + * @returns {number} items / sec + */ + getBeltBaseSpeed() { + return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt; + } + + /** + * Underground belt speed + * @returns {number} items / sec + */ + getUndergroundBeltBaseSpeed() { + return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt; + } + + /** + * Miner speed + * @returns {number} items / sec + */ + getMinerBaseSpeed() { + return globalConfig.minerSpeedItemsPerSecond * this.upgradeImprovements.miner; + } + + /** + * Processor speed + * @param {enumItemProcessorTypes} processorType + * @returns {number} items / sec + */ + getProcessorBaseSpeed(processorType) { + switch (processorType) { + case enumItemProcessorTypes.splitterWires: + return globalConfig.wiresSpeedItemsPerSecond * 2; + + case enumItemProcessorTypes.trash: + case enumItemProcessorTypes.hub: + return 1e30; + case enumItemProcessorTypes.splitter: + return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt * 2; + case enumItemProcessorTypes.filter: + case enumItemProcessorTypes.reader: + return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt; + + case enumItemProcessorTypes.mixer: + case enumItemProcessorTypes.painter: + case enumItemProcessorTypes.painterDouble: + case enumItemProcessorTypes.painterQuad: { + assert( + globalConfig.buildingSpeeds[processorType], + "Processor type has no speed set in globalConfig.buildingSpeeds: " + processorType + ); + return ( + globalConfig.beltSpeedItemsPerSecond * + this.upgradeImprovements.painting * + globalConfig.buildingSpeeds[processorType] + ); + } + + case enumItemProcessorTypes.cutter: + case enumItemProcessorTypes.cutterQuad: + case enumItemProcessorTypes.rotater: + case enumItemProcessorTypes.rotaterCCW: + case enumItemProcessorTypes.rotaterFL: + case enumItemProcessorTypes.stacker: { + assert( + globalConfig.buildingSpeeds[processorType], + "Processor type has no speed set in globalConfig.buildingSpeeds: " + processorType + ); + return ( + globalConfig.beltSpeedItemsPerSecond * + this.upgradeImprovements.processors * + globalConfig.buildingSpeeds[processorType] + ); + } + default: + assertAlways(false, "invalid processor type: " + processorType); + } + + return 1 / globalConfig.beltSpeedItemsPerSecond; + } +} diff --git a/src/js/game/hud/dynamic_dom_attach.js b/src/js/game/hud/dynamic_dom_attach.js index 68f09052..2b150448 100644 --- a/src/js/game/hud/dynamic_dom_attach.js +++ b/src/js/game/hud/dynamic_dom_attach.js @@ -1,3 +1,4 @@ +import { TrackedState } from "../../core/tracked_state"; import { GameRoot } from "../root"; // Automatically attaches and detaches elements from the dom @@ -7,15 +8,28 @@ import { GameRoot } from "../root"; // Also attaches a class name if desired export class DynamicDomAttach { - constructor(root, element, { timeToKeepSeconds = 0, attachClass = null } = {}) { + /** + * + * @param {GameRoot} root + * @param {HTMLElement} element + * @param {object} param2 + * @param {number=} param2.timeToKeepSeconds How long to keep the element visible (in ms) after it should be hidden. + * Useful for fade-out effects + * @param {string=} param2.attachClass If set, attaches a class while the element is visible + * @param {boolean=} param2.trackHover If set, attaches the 'hovered' class if the cursor is above the element. Useful + * for fading out the element if its below the cursor for example. + */ + constructor(root, element, { timeToKeepSeconds = 0, attachClass = null, trackHover = false } = {}) { /** @type {GameRoot} */ this.root = root; /** @type {HTMLElement} */ this.element = element; this.parent = this.element.parentElement; + assert(this.parent, "Dom attach created without parent"); this.attachClass = attachClass; + this.trackHover = trackHover; this.timeToKeepSeconds = timeToKeepSeconds; this.lastVisibleTime = 0; @@ -26,8 +40,19 @@ export class DynamicDomAttach { this.internalIsClassAttached = false; this.classAttachTimeout = null; + + // Store the last bounds we computed + /** @type {DOMRect} */ + this.lastComputedBounds = null; + this.lastComputedBoundsTime = -1; + + // Track the 'hovered' class + this.trackedIsHovered = new TrackedState(this.setIsHoveredClass, this); } + /** + * Internal method to attach the element + */ internalAttach() { if (!this.attached) { this.parent.appendChild(this.element); @@ -36,6 +61,9 @@ export class DynamicDomAttach { } } + /** + * Internal method to detach the element + */ internalDetach() { if (this.attached) { assert(this.element.parentElement === this.parent, "Invalid parent #2"); @@ -44,14 +72,50 @@ export class DynamicDomAttach { } } + /** + * Returns whether the element is currently attached + */ isAttached() { return this.attached; } + /** + * Actually sets the 'hovered' class + * @param {boolean} isHovered + */ + setIsHoveredClass(isHovered) { + this.element.classList.toggle("hovered", isHovered); + } + + /** + * Call this every frame, and the dom attach class will take care of + * everything else + * @param {boolean} isVisible Whether the element should currently be visible or not + */ update(isVisible) { if (isVisible) { this.lastVisibleTime = this.root ? this.root.time.realtimeNow() : 0; this.internalAttach(); + + if (this.trackHover && this.root) { + let bounds = this.lastComputedBounds; + + // Recompute bounds only once in a while + if (!bounds || this.root.time.realtimeNow() - this.lastComputedBoundsTime > 1.0) { + bounds = this.lastComputedBounds = this.element.getBoundingClientRect(); + this.lastComputedBoundsTime = this.root.time.realtimeNow(); + } + + const mousePos = this.root.app.mousePosition; + if (mousePos) { + this.trackedIsHovered.set( + mousePos.x > bounds.left && + mousePos.x < bounds.right && + mousePos.y > bounds.top && + mousePos.y < bounds.bottom + ); + } + } } else { if (!this.root || this.root.time.realtimeNow() - this.lastVisibleTime >= this.timeToKeepSeconds) { this.internalDetach(); diff --git a/src/js/game/hud/hud.js b/src/js/game/hud/hud.js index 1d72deb5..3edc4e17 100644 --- a/src/js/game/hud/hud.js +++ b/src/js/game/hud/hud.js @@ -1,274 +1,281 @@ -/* typehints:start */ -import { GameRoot } from "../root"; -/* typehints:end */ - -/* dev:start */ -import { TrailerMaker } from "./trailer_maker"; -/* dev:end */ - -import { Signal } from "../../core/signal"; -import { DrawParameters } from "../../core/draw_parameters"; -import { HUDProcessingOverlay } from "./parts/processing_overlay"; -import { HUDBuildingsToolbar } from "./parts/buildings_toolbar"; -import { HUDBuildingPlacer } from "./parts/building_placer"; -import { HUDBlueprintPlacer } from "./parts/blueprint_placer"; -import { HUDKeybindingOverlay } from "./parts/keybinding_overlay"; -import { HUDUnlockNotification } from "./parts/unlock_notification"; -import { HUDGameMenu } from "./parts/game_menu"; -import { HUDShop } from "./parts/shop"; -import { IS_MOBILE, globalConfig, IS_DEMO } from "../../core/config"; -import { HUDMassSelector } from "./parts/mass_selector"; -import { HUDVignetteOverlay } from "./parts/vignette_overlay"; -import { HUDStatistics } from "./parts/statistics"; -import { MetaBuilding } from "../meta_building"; -import { HUDPinnedShapes } from "./parts/pinned_shapes"; -import { ShapeDefinition } from "../shape_definition"; -import { HUDNotifications, enumNotificationType } from "./parts/notifications"; -import { HUDSettingsMenu } from "./parts/settings_menu"; -import { HUDDebugInfo } from "./parts/debug_info"; -import { HUDEntityDebugger } from "./parts/entity_debugger"; -import { KEYMAPPINGS } from "../key_action_mapper"; -import { HUDWatermark } from "./parts/watermark"; -import { HUDModalDialogs } from "./parts/modal_dialogs"; -import { HUDPartTutorialHints } from "./parts/tutorial_hints"; -import { HUDWaypoints } from "./parts/waypoints"; -import { HUDInteractiveTutorial } from "./parts/interactive_tutorial"; -import { HUDScreenshotExporter } from "./parts/screenshot_exporter"; -import { HUDColorBlindHelper } from "./parts/color_blind_helper"; -import { HUDShapeViewer } from "./parts/shape_viewer"; -import { HUDWiresOverlay } from "./parts/wires_overlay"; -import { HUDChangesDebugger } from "./parts/debug_changes"; -import { queryParamOptions } from "../../core/query_parameters"; -import { HUDSandboxController } from "./parts/sandbox_controller"; -import { HUDWiresToolbar } from "./parts/wires_toolbar"; - -export class GameHUD { - /** - * @param {GameRoot} root - */ - constructor(root) { - this.root = root; - } - - /** - * Initializes the hud parts - */ - initialize() { - this.parts = { - processingOverlay: new HUDProcessingOverlay(this.root), - buildingsToolbar: new HUDBuildingsToolbar(this.root), - wiresToolbar: new HUDWiresToolbar(this.root), - blueprintPlacer: new HUDBlueprintPlacer(this.root), - buildingPlacer: new HUDBuildingPlacer(this.root), - unlockNotification: new HUDUnlockNotification(this.root), - gameMenu: new HUDGameMenu(this.root), - massSelector: new HUDMassSelector(this.root), - shop: new HUDShop(this.root), - statistics: new HUDStatistics(this.root), - waypoints: new HUDWaypoints(this.root), - - // Must always exist - pinnedShapes: new HUDPinnedShapes(this.root), - notifications: new HUDNotifications(this.root), - settingsMenu: new HUDSettingsMenu(this.root), - // betaOverlay: new HUDBetaOverlay(this.root), - debugInfo: new HUDDebugInfo(this.root), - dialogs: new HUDModalDialogs(this.root), - screenshotExporter: new HUDScreenshotExporter(this.root), - shapeViewer: new HUDShapeViewer(this.root), - - wiresOverlay: new HUDWiresOverlay(this.root), - - // Typing hints - /* typehints:start */ - /** @type {HUDChangesDebugger} */ - changesDebugger: null, - /* typehints:end */ - }; - - this.signals = { - buildingSelectedForPlacement: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()), - selectedPlacementBuildingChanged: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()), - shapePinRequested: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()), - shapeUnpinRequested: /** @type {TypedSignal<[string]>} */ (new Signal()), - notification: /** @type {TypedSignal<[string, enumNotificationType]>} */ (new Signal()), - buildingsSelectedForCopy: /** @type {TypedSignal<[Array]>} */ (new Signal()), - pasteBlueprintRequested: /** @type {TypedSignal<[]>} */ (new Signal()), - viewShapeDetailsRequested: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()), - }; - - if (!IS_MOBILE) { - this.parts.keybindingOverlay = new HUDKeybindingOverlay(this.root); - } - - if (G_IS_DEV && globalConfig.debug.enableEntityInspector) { - this.parts.entityDebugger = new HUDEntityDebugger(this.root); - } - - if (IS_DEMO) { - this.parts.watermark = new HUDWatermark(this.root); - } - - if (G_IS_DEV && globalConfig.debug.renderChanges) { - this.parts.changesDebugger = new HUDChangesDebugger(this.root); - } - - if (this.root.app.settings.getAllSettings().offerHints) { - this.parts.tutorialHints = new HUDPartTutorialHints(this.root); - this.parts.interactiveTutorial = new HUDInteractiveTutorial(this.root); - } - - if (this.root.app.settings.getAllSettings().vignette) { - this.parts.vignetteOverlay = new HUDVignetteOverlay(this.root); - } - - if (this.root.app.settings.getAllSettings().enableColorBlindHelper) { - this.parts.colorBlindHelper = new HUDColorBlindHelper(this.root); - } - - if (queryParamOptions.sandboxMode || G_IS_DEV) { - this.parts.sandboxController = new HUDSandboxController(this.root); - } - - const frag = document.createDocumentFragment(); - for (const key in this.parts) { - this.parts[key].createElements(frag); - } - - document.body.appendChild(frag); - - for (const key in this.parts) { - this.parts[key].initialize(); - } - - this.root.keyMapper.getBinding(KEYMAPPINGS.ingame.toggleHud).add(this.toggleUi, this); - - /* dev:start */ - if (G_IS_DEV && globalConfig.debug.renderForTrailer) { - this.trailerMaker = new TrailerMaker(this.root); - } - /* dev:end*/ - } - - /** - * Attempts to close all overlays - */ - closeAllOverlays() { - for (const key in this.parts) { - this.parts[key].close(); - } - } - - /** - * Returns true if the game logic should be paused - */ - shouldPauseGame() { - for (const key in this.parts) { - if (this.parts[key].shouldPauseGame()) { - return true; - } - } - return false; - } - - /** - * Returns true if the rendering can be paused - */ - shouldPauseRendering() { - for (const key in this.parts) { - if (this.parts[key].shouldPauseRendering()) { - return true; - } - } - return false; - } - - /** - * Returns true if the rendering can be paused - */ - hasBlockingOverlayOpen() { - if (this.root.camera.getIsMapOverlayActive()) { - return true; - } - for (const key in this.parts) { - if (this.parts[key].isBlockingOverlay()) { - return true; - } - } - return false; - } - - /** - * Toggles the ui - */ - toggleUi() { - document.body.classList.toggle("uiHidden"); - } - - /** - * Updates all parts - */ - update() { - if (!this.root.gameInitialized) { - return; - } - - for (const key in this.parts) { - this.parts[key].update(); - } - - /* dev:start */ - if (this.trailerMaker) { - this.trailerMaker.update(); - } - /* dev:end*/ - } - - /** - * Draws all parts - * @param {DrawParameters} parameters - */ - draw(parameters) { - const partsOrder = [ - "waypoints", - "massSelector", - "buildingPlacer", - "blueprintPlacer", - "colorBlindHelper", - "changesDebugger", - ]; - - for (let i = 0; i < partsOrder.length; ++i) { - if (this.parts[partsOrder[i]]) { - this.parts[partsOrder[i]].draw(parameters); - } - } - } - - /** - * Draws all part overlays - * @param {DrawParameters} parameters - */ - drawOverlays(parameters) { - const partsOrder = ["watermark"]; - - for (let i = 0; i < partsOrder.length; ++i) { - if (this.parts[partsOrder[i]]) { - this.parts[partsOrder[i]].drawOverlays(parameters); - } - } - } - - /** - * Cleans up everything - */ - cleanup() { - for (const key in this.parts) { - this.parts[key].cleanup(); - } - - for (const key in this.signals) { - this.signals[key].removeAll(); - } - } -} +/* typehints:start */ +import { GameRoot } from "../root"; +/* typehints:end */ + +/* dev:start */ +import { TrailerMaker } from "./trailer_maker"; +/* dev:end */ + +import { Signal } from "../../core/signal"; +import { DrawParameters } from "../../core/draw_parameters"; +import { HUDBuildingsToolbar } from "./parts/buildings_toolbar"; +import { HUDBuildingPlacer } from "./parts/building_placer"; +import { HUDBlueprintPlacer } from "./parts/blueprint_placer"; +import { HUDKeybindingOverlay } from "./parts/keybinding_overlay"; +import { HUDUnlockNotification } from "./parts/unlock_notification"; +import { HUDGameMenu } from "./parts/game_menu"; +import { HUDShop } from "./parts/shop"; +import { IS_MOBILE, globalConfig, IS_DEMO } from "../../core/config"; +import { HUDMassSelector } from "./parts/mass_selector"; +import { HUDVignetteOverlay } from "./parts/vignette_overlay"; +import { HUDStatistics } from "./parts/statistics"; +import { MetaBuilding } from "../meta_building"; +import { HUDPinnedShapes } from "./parts/pinned_shapes"; +import { ShapeDefinition } from "../shape_definition"; +import { HUDNotifications, enumNotificationType } from "./parts/notifications"; +import { HUDSettingsMenu } from "./parts/settings_menu"; +import { HUDDebugInfo } from "./parts/debug_info"; +import { HUDEntityDebugger } from "./parts/entity_debugger"; +import { KEYMAPPINGS } from "../key_action_mapper"; +import { HUDWatermark } from "./parts/watermark"; +import { HUDModalDialogs } from "./parts/modal_dialogs"; +import { HUDPartTutorialHints } from "./parts/tutorial_hints"; +import { HUDWaypoints } from "./parts/waypoints"; +import { HUDInteractiveTutorial } from "./parts/interactive_tutorial"; +import { HUDScreenshotExporter } from "./parts/screenshot_exporter"; +import { HUDColorBlindHelper } from "./parts/color_blind_helper"; +import { HUDShapeViewer } from "./parts/shape_viewer"; +import { HUDWiresOverlay } from "./parts/wires_overlay"; +import { HUDChangesDebugger } from "./parts/debug_changes"; +import { queryParamOptions } from "../../core/query_parameters"; +import { HUDSandboxController } from "./parts/sandbox_controller"; +import { HUDWiresToolbar } from "./parts/wires_toolbar"; +import { HUDWireInfo } from "./parts/wire_info"; +import { HUDLeverToggle } from "./parts/lever_toggle"; +import { HUDLayerPreview } from "./parts/layer_preview"; +import { HUDMinerHighlight } from "./parts/miner_highlight"; + +export class GameHUD { + /** + * @param {GameRoot} root + */ + constructor(root) { + this.root = root; + } + + /** + * Initializes the hud parts + */ + initialize() { + this.parts = { + buildingsToolbar: new HUDBuildingsToolbar(this.root), + wiresToolbar: new HUDWiresToolbar(this.root), + blueprintPlacer: new HUDBlueprintPlacer(this.root), + buildingPlacer: new HUDBuildingPlacer(this.root), + unlockNotification: new HUDUnlockNotification(this.root), + gameMenu: new HUDGameMenu(this.root), + massSelector: new HUDMassSelector(this.root), + shop: new HUDShop(this.root), + statistics: new HUDStatistics(this.root), + waypoints: new HUDWaypoints(this.root), + wireInfo: new HUDWireInfo(this.root), + leverToggle: new HUDLeverToggle(this.root), + + // Must always exist + pinnedShapes: new HUDPinnedShapes(this.root), + notifications: new HUDNotifications(this.root), + settingsMenu: new HUDSettingsMenu(this.root), + // betaOverlay: new HUDBetaOverlay(this.root), + debugInfo: new HUDDebugInfo(this.root), + dialogs: new HUDModalDialogs(this.root), + screenshotExporter: new HUDScreenshotExporter(this.root), + shapeViewer: new HUDShapeViewer(this.root), + + wiresOverlay: new HUDWiresOverlay(this.root), + layerPreview: new HUDLayerPreview(this.root), + + minerHighlight: new HUDMinerHighlight(this.root), + + // Typing hints + /* typehints:start */ + /** @type {HUDChangesDebugger} */ + changesDebugger: null, + /* typehints:end */ + }; + + this.signals = { + buildingSelectedForPlacement: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()), + selectedPlacementBuildingChanged: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()), + shapePinRequested: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()), + shapeUnpinRequested: /** @type {TypedSignal<[string]>} */ (new Signal()), + notification: /** @type {TypedSignal<[string, enumNotificationType]>} */ (new Signal()), + buildingsSelectedForCopy: /** @type {TypedSignal<[Array]>} */ (new Signal()), + pasteBlueprintRequested: /** @type {TypedSignal<[]>} */ (new Signal()), + viewShapeDetailsRequested: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()), + }; + + if (!IS_MOBILE) { + this.parts.keybindingOverlay = new HUDKeybindingOverlay(this.root); + } + + if (G_IS_DEV && globalConfig.debug.enableEntityInspector) { + this.parts.entityDebugger = new HUDEntityDebugger(this.root); + } + + if (IS_DEMO) { + this.parts.watermark = new HUDWatermark(this.root); + } + + if (G_IS_DEV && globalConfig.debug.renderChanges) { + this.parts.changesDebugger = new HUDChangesDebugger(this.root); + } + + if (this.root.app.settings.getAllSettings().offerHints) { + this.parts.tutorialHints = new HUDPartTutorialHints(this.root); + this.parts.interactiveTutorial = new HUDInteractiveTutorial(this.root); + } + + if (this.root.app.settings.getAllSettings().vignette) { + this.parts.vignetteOverlay = new HUDVignetteOverlay(this.root); + } + + if (this.root.app.settings.getAllSettings().enableColorBlindHelper) { + this.parts.colorBlindHelper = new HUDColorBlindHelper(this.root); + } + + if (queryParamOptions.sandboxMode || G_IS_DEV) { + this.parts.sandboxController = new HUDSandboxController(this.root); + } + + const frag = document.createDocumentFragment(); + for (const key in this.parts) { + this.parts[key].createElements(frag); + } + + document.body.appendChild(frag); + + for (const key in this.parts) { + this.parts[key].initialize(); + } + + this.root.keyMapper.getBinding(KEYMAPPINGS.ingame.toggleHud).add(this.toggleUi, this); + + /* dev:start */ + if (G_IS_DEV && globalConfig.debug.renderForTrailer) { + this.trailerMaker = new TrailerMaker(this.root); + } + /* dev:end*/ + } + + /** + * Attempts to close all overlays + */ + closeAllOverlays() { + for (const key in this.parts) { + this.parts[key].close(); + } + } + + /** + * Returns true if the game logic should be paused + */ + shouldPauseGame() { + for (const key in this.parts) { + if (this.parts[key].shouldPauseGame()) { + return true; + } + } + return false; + } + + /** + * Returns true if the rendering can be paused + */ + shouldPauseRendering() { + for (const key in this.parts) { + if (this.parts[key].shouldPauseRendering()) { + return true; + } + } + return false; + } + + /** + * Returns true if the rendering can be paused + */ + hasBlockingOverlayOpen() { + if (this.root.camera.getIsMapOverlayActive()) { + return true; + } + for (const key in this.parts) { + if (this.parts[key].isBlockingOverlay()) { + return true; + } + } + return false; + } + + /** + * Toggles the ui + */ + toggleUi() { + document.body.classList.toggle("uiHidden"); + } + + /** + * Updates all parts + */ + update() { + if (!this.root.gameInitialized) { + return; + } + + for (const key in this.parts) { + this.parts[key].update(); + } + + /* dev:start */ + if (this.trailerMaker) { + this.trailerMaker.update(); + } + /* dev:end*/ + } + + /** + * Draws all parts + * @param {DrawParameters} parameters + */ + draw(parameters) { + const partsOrder = [ + "massSelector", + "buildingPlacer", + "blueprintPlacer", + "colorBlindHelper", + "changesDebugger", + "minerHighlight", + ]; + + for (let i = 0; i < partsOrder.length; ++i) { + if (this.parts[partsOrder[i]]) { + this.parts[partsOrder[i]].draw(parameters); + } + } + } + + /** + * Draws all part overlays + * @param {DrawParameters} parameters + */ + drawOverlays(parameters) { + const partsOrder = ["waypoints", "watermark", "wireInfo"]; + + for (let i = 0; i < partsOrder.length; ++i) { + if (this.parts[partsOrder[i]]) { + this.parts[partsOrder[i]].drawOverlays(parameters); + } + } + } + + /** + * Cleans up everything + */ + cleanup() { + for (const key in this.parts) { + this.parts[key].cleanup(); + } + + for (const key in this.signals) { + this.signals[key].removeAll(); + } + } +} diff --git a/src/js/game/hud/parts/blueprint_placer.js b/src/js/game/hud/parts/blueprint_placer.js index 38341395..47bf1363 100644 --- a/src/js/game/hud/parts/blueprint_placer.js +++ b/src/js/game/hud/parts/blueprint_placer.js @@ -11,7 +11,6 @@ import { BaseHUDPart } from "../base_hud_part"; import { DynamicDomAttach } from "../dynamic_dom_attach"; import { Blueprint } from "../../blueprint"; import { SOUNDS } from "../../../platform/sound"; -import { enumLayer } from "../../root"; export class HUDBlueprintPlacer extends BaseHUDPart { createElements(parent) { @@ -60,7 +59,7 @@ export class HUDBlueprintPlacer extends BaseHUDPart { /** * Called when the layer was changed - * @param {enumLayer} layer + * @param {Layer} layer */ onEditModeChanged(layer) { // Check if the layer of the blueprint differs and thus we have to deselect it diff --git a/src/js/game/hud/parts/building_placer.js b/src/js/game/hud/parts/building_placer.js index d3a3c7ac..fcce54b2 100644 --- a/src/js/game/hud/parts/building_placer.js +++ b/src/js/game/hud/parts/building_placer.js @@ -1,580 +1,610 @@ -import { ClickDetector } from "../../../core/click_detector"; -import { globalConfig, THIRDPARTY_URLS } from "../../../core/config"; -import { DrawParameters } from "../../../core/draw_parameters"; -import { drawRotatedSprite, rotateTrapezRightFaced } from "../../../core/draw_utils"; -import { Loader } from "../../../core/loader"; -import { clamp, makeDiv, removeAllChildren } from "../../../core/utils"; -import { - enumDirectionToAngle, - enumDirectionToVector, - enumInvertedDirections, - Vector, -} from "../../../core/vector"; -import { T } from "../../../translations"; -import { KEYMAPPINGS } from "../../key_action_mapper"; -import { defaultBuildingVariant } from "../../meta_building"; -import { THEME } from "../../theme"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; -import { HUDBuildingPlacerLogic } from "./building_placer_logic"; -import { makeOffscreenBuffer } from "../../../core/buffer_utils"; -import { enumLayer } from "../../root"; - -export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { - /** - * @param {HTMLElement} parent - */ - createElements(parent) { - this.element = makeDiv(parent, "ingame_HUD_PlacementHints", [], ``); - - this.buildingInfoElements = {}; - this.buildingInfoElements.label = makeDiv(this.element, null, ["buildingLabel"], "Extract"); - this.buildingInfoElements.desc = makeDiv(this.element, null, ["description"], ""); - this.buildingInfoElements.descText = makeDiv(this.buildingInfoElements.desc, null, ["text"], ""); - this.buildingInfoElements.additionalInfo = makeDiv( - this.buildingInfoElements.desc, - null, - ["additionalInfo"], - "" - ); - this.buildingInfoElements.hotkey = makeDiv(this.buildingInfoElements.desc, null, ["hotkey"], ""); - this.buildingInfoElements.tutorialImage = makeDiv(this.element, null, ["buildingImage"]); - - this.variantsElement = makeDiv(parent, "ingame_HUD_PlacerVariants"); - - const compact = this.root.app.settings.getAllSettings().compactBuildingInfo; - this.element.classList.toggle("compact", compact); - this.variantsElement.classList.toggle("compact", compact); - } - - initialize() { - super.initialize(); - - // Bind to signals - this.signals.variantChanged.add(this.rerenderVariants, this); - this.root.hud.signals.buildingSelectedForPlacement.add(this.startSelection, this); - - this.domAttach = new DynamicDomAttach(this.root, this.element, {}); - this.variantsAttach = new DynamicDomAttach(this.root, this.variantsElement, {}); - - this.currentInterpolatedCornerTile = new Vector(); - - this.lockIndicatorSprites = {}; - for (const layerId in enumLayer) { - this.lockIndicatorSprites[layerId] = this.makeLockIndicatorSprite(layerId); - } - - // - - /** - * Stores the click detectors for the variants so we can clean them up later - * @type {Array} - */ - this.variantClickDetectors = []; - } - - /** - * Makes the lock indicator sprite for the given layer - * @param {enumLayer} layer - */ - makeLockIndicatorSprite(layer) { - const dims = 48; - const [canvas, context] = makeOffscreenBuffer(dims, dims, { - smooth: true, - reusable: false, - label: "lock-direction-indicator", - }); - - // Loader.getSprite("sprites/misc/lock_direction_indicator.png").draw(context, 0, 0, 48, 48); - context.fillStyle = THEME.map.directionLock[enumLayer.wires].color; - context.strokeStyle = THEME.map.directionLock[enumLayer.wires].color; - context.lineWidth = 2; - - const padding = 5; - const height = dims * 0.5; - const bottom = (dims + height) / 2; - - context.moveTo(padding, bottom); - context.lineTo(dims / 2, bottom - height); - context.lineTo(dims - padding, bottom); - context.closePath(); - context.stroke(); - context.fill(); - - return canvas; - } - - /** - * Rerenders the building info dialog - */ - rerenderInfoDialog() { - const metaBuilding = this.currentMetaBuilding.get(); - - if (!metaBuilding) { - return; - } - - const variant = this.currentVariant.get(); - - this.buildingInfoElements.label.innerHTML = T.buildings[metaBuilding.id][variant].name; - this.buildingInfoElements.descText.innerHTML = T.buildings[metaBuilding.id][variant].description; - - const binding = this.root.keyMapper.getBinding(KEYMAPPINGS.buildings[metaBuilding.getId()]); - this.buildingInfoElements.hotkey.innerHTML = T.ingame.buildingPlacement.hotkeyLabel.replace( - "", - "" + binding.getKeyCodeString() + "" - ); - - this.buildingInfoElements.tutorialImage.setAttribute( - "data-icon", - "building_tutorials/" + - metaBuilding.getId() + - (variant === defaultBuildingVariant ? "" : "-" + variant) + - ".png" - ); - - removeAllChildren(this.buildingInfoElements.additionalInfo); - const additionalInfo = metaBuilding.getAdditionalStatistics(this.root, this.currentVariant.get()); - for (let i = 0; i < additionalInfo.length; ++i) { - const [label, contents] = additionalInfo[i]; - this.buildingInfoElements.additionalInfo.innerHTML += ` - - ${contents} - `; - } - } - - cleanup() { - super.cleanup(); - this.cleanupVariantClickDetectors(); - } - - /** - * Cleans up all variant click detectors - */ - cleanupVariantClickDetectors() { - for (let i = 0; i < this.variantClickDetectors.length; ++i) { - const detector = this.variantClickDetectors[i]; - detector.cleanup(); - } - this.variantClickDetectors = []; - } - - /** - * Rerenders the variants displayed - */ - rerenderVariants() { - removeAllChildren(this.variantsElement); - this.rerenderInfoDialog(); - - const metaBuilding = this.currentMetaBuilding.get(); - - // First, clear up all click detectors - this.cleanupVariantClickDetectors(); - - if (!metaBuilding) { - return; - } - const availableVariants = metaBuilding.getAvailableVariants(this.root); - if (availableVariants.length === 1) { - return; - } - - makeDiv( - this.variantsElement, - null, - ["explanation"], - T.ingame.buildingPlacement.cycleBuildingVariants.replace( - "", - "" + - this.root.keyMapper - .getBinding(KEYMAPPINGS.placement.cycleBuildingVariants) - .getKeyCodeString() + - "" - ) - ); - - const container = makeDiv(this.variantsElement, null, ["variants"]); - - for (let i = 0; i < availableVariants.length; ++i) { - const variant = availableVariants[i]; - - const element = makeDiv(container, null, ["variant"]); - element.classList.toggle("active", variant === this.currentVariant.get()); - makeDiv(element, null, ["label"], variant); - - const iconSize = 64; - - const dimensions = metaBuilding.getDimensions(variant); - const sprite = metaBuilding.getPreviewSprite(0, variant); - const spriteWrapper = makeDiv(element, null, ["iconWrap"]); - spriteWrapper.setAttribute("data-tile-w", dimensions.x); - spriteWrapper.setAttribute("data-tile-h", dimensions.y); - - spriteWrapper.innerHTML = sprite.getAsHTML(iconSize * dimensions.x, iconSize * dimensions.y); - - const detector = new ClickDetector(element, { - consumeEvents: true, - targetOnly: true, - }); - detector.click.add(() => this.setVariant(variant)); - } - } - - /** - * - * @param {DrawParameters} parameters - */ - draw(parameters) { - if (this.root.camera.zoomLevel < globalConfig.mapChunkOverviewMinZoom) { - // Dont allow placing in overview mode - this.domAttach.update(false); - this.variantsAttach.update(false); - return; - } - - this.domAttach.update(this.currentMetaBuilding.get()); - this.variantsAttach.update(this.currentMetaBuilding.get()); - const metaBuilding = this.currentMetaBuilding.get(); - - if (!metaBuilding) { - return; - } - - // Draw direction lock - if (this.isDirectionLockActive) { - this.drawDirectionLock(parameters); - } else { - this.drawRegularPlacement(parameters); - } - } - - /** - * @param {DrawParameters} parameters - */ - drawRegularPlacement(parameters) { - const mousePosition = this.root.app.mousePosition; - if (!mousePosition) { - // Not on screen - return; - } - - const metaBuilding = this.currentMetaBuilding.get(); - - const worldPos = this.root.camera.screenToWorld(mousePosition); - const mouseTile = worldPos.toTileSpace(); - - // Compute best rotation variant - const { - rotation, - rotationVariant, - connectedEntities, - } = metaBuilding.computeOptimalDirectionAndRotationVariantAtTile({ - root: this.root, - tile: mouseTile, - rotation: this.currentBaseRotation, - variant: this.currentVariant.get(), - layer: metaBuilding.getLayer(), - }); - - // Check if there are connected entities - if (connectedEntities) { - for (let i = 0; i < connectedEntities.length; ++i) { - const connectedEntity = connectedEntities[i]; - const connectedWsPoint = connectedEntity.components.StaticMapEntity.getTileSpaceBounds() - .getCenter() - .toWorldSpace(); - - const startWsPoint = mouseTile.toWorldSpaceCenterOfTile(); - - const startOffset = connectedWsPoint - .sub(startWsPoint) - .normalize() - .multiplyScalar(globalConfig.tileSize * 0.3); - const effectiveStartPoint = startWsPoint.add(startOffset); - const effectiveEndPoint = connectedWsPoint.sub(startOffset); - - parameters.context.globalAlpha = 0.6; - - // parameters.context.lineCap = "round"; - parameters.context.strokeStyle = "#7f7"; - parameters.context.lineWidth = 10; - parameters.context.beginPath(); - parameters.context.moveTo(effectiveStartPoint.x, effectiveStartPoint.y); - parameters.context.lineTo(effectiveEndPoint.x, effectiveEndPoint.y); - parameters.context.stroke(); - parameters.context.globalAlpha = 1; - // parameters.context.lineCap = "square"; - } - } - - // Synchronize rotation and origin - const staticComp = this.fakeEntity.components.StaticMapEntity; - staticComp.origin = mouseTile; - staticComp.rotation = rotation; - staticComp.tileSize = metaBuilding.getDimensions(this.currentVariant.get()); - metaBuilding.updateVariants(this.fakeEntity, rotationVariant, this.currentVariant.get()); - - const canBuild = this.root.logic.checkCanPlaceEntity(this.fakeEntity); - - // Fade in / out - parameters.context.lineWidth = 1; - // parameters.context.globalAlpha = 0.3 + pulseAnimation(this.root.time.realtimeNow(), 0.9) * 0.7; - - // Determine the bounds and visualize them - const entityBounds = staticComp.getTileSpaceBounds(); - const drawBorder = -3; - if (canBuild) { - parameters.context.strokeStyle = "rgba(56, 235, 111, 0.5)"; - parameters.context.fillStyle = "rgba(56, 235, 111, 0.2)"; - } else { - parameters.context.strokeStyle = "rgba(255, 0, 0, 0.2)"; - parameters.context.fillStyle = "rgba(255, 0, 0, 0.2)"; - } - - parameters.context.beginRoundedRect( - entityBounds.x * globalConfig.tileSize - drawBorder, - entityBounds.y * globalConfig.tileSize - drawBorder, - entityBounds.w * globalConfig.tileSize + 2 * drawBorder, - entityBounds.h * globalConfig.tileSize + 2 * drawBorder, - 4 - ); - parameters.context.stroke(); - // parameters.context.fill(); - parameters.context.globalAlpha = 1; - - // HACK to draw the entity sprite - const previewSprite = metaBuilding.getBlueprintSprite(rotationVariant, this.currentVariant.get()); - staticComp.origin = worldPos.divideScalar(globalConfig.tileSize).subScalars(0.5, 0.5); - staticComp.drawSpriteOnFullEntityBounds(parameters, previewSprite); - staticComp.origin = mouseTile; - - // Draw ejectors - if (canBuild) { - this.drawMatchingAcceptorsAndEjectors(parameters); - } - } - - /** - * @param {DrawParameters} parameters - */ - drawDirectionLock(parameters) { - const mousePosition = this.root.app.mousePosition; - if (!mousePosition) { - // Not on screen - return; - } - - const mouseWorld = this.root.camera.screenToWorld(mousePosition); - const mouseTile = mouseWorld.toTileSpace(); - parameters.context.fillStyle = THEME.map.directionLock[this.root.currentLayer].color; - parameters.context.strokeStyle = THEME.map.directionLock[this.root.currentLayer].background; - parameters.context.lineWidth = 10; - - parameters.context.beginCircle(mouseWorld.x, mouseWorld.y, 4); - parameters.context.fill(); - - if (this.lastDragTile) { - const startLine = this.lastDragTile.toWorldSpaceCenterOfTile(); - const endLine = mouseTile.toWorldSpaceCenterOfTile(); - const midLine = this.currentDirectionLockCorner.toWorldSpaceCenterOfTile(); - - parameters.context.beginCircle(startLine.x, startLine.y, 8); - parameters.context.fill(); - - parameters.context.beginPath(); - parameters.context.moveTo(startLine.x, startLine.y); - parameters.context.lineTo(midLine.x, midLine.y); - parameters.context.lineTo(endLine.x, endLine.y); - parameters.context.stroke(); - - parameters.context.beginCircle(endLine.x, endLine.y, 5); - parameters.context.fill(); - - // Draw arrow - const arrowSprite = this.lockIndicatorSprites[this.root.currentLayer]; - const path = this.computeDirectionLockPath(); - for (let i = 0; i < path.length - 1; i += 1) { - const { rotation, tile } = path[i]; - const worldPos = tile.toWorldSpaceCenterOfTile(); - const angle = Math.radians(rotation); - - parameters.context.translate(worldPos.x, worldPos.y); - parameters.context.rotate(angle); - parameters.context.drawImage( - arrowSprite, - -6, - -globalConfig.halfTileSize - - clamp((this.root.time.realtimeNow() * 1.5) % 1.0, 0, 1) * 1 * globalConfig.tileSize + - globalConfig.halfTileSize - - 6, - 12, - 12 - ); - parameters.context.rotate(-angle); - parameters.context.translate(-worldPos.x, -worldPos.y); - } - } - } - - /** - * @param {DrawParameters} parameters - */ - drawMatchingAcceptorsAndEjectors(parameters) { - const acceptorComp = this.fakeEntity.components.ItemAcceptor; - const ejectorComp = this.fakeEntity.components.ItemEjector; - const staticComp = this.fakeEntity.components.StaticMapEntity; - - const goodArrowSprite = Loader.getSprite("sprites/misc/slot_good_arrow.png"); - const badArrowSprite = Loader.getSprite("sprites/misc/slot_bad_arrow.png"); - - // Just ignore the following code please ... thanks! - - const offsetShift = 10; - - if (acceptorComp) { - const slots = acceptorComp.slots; - for (let acceptorSlotIndex = 0; acceptorSlotIndex < slots.length; ++acceptorSlotIndex) { - const slot = slots[acceptorSlotIndex]; - - // Only draw same layer slots - if (slot.layer !== this.root.currentLayer) { - continue; - } - - const acceptorSlotWsTile = staticComp.localTileToWorld(slot.pos); - const acceptorSlotWsPos = acceptorSlotWsTile.toWorldSpaceCenterOfTile(); - - // Go over all slots - for ( - let acceptorDirectionIndex = 0; - acceptorDirectionIndex < slot.directions.length; - ++acceptorDirectionIndex - ) { - const direction = slot.directions[acceptorDirectionIndex]; - const worldDirection = staticComp.localDirectionToWorld(direction); - - // Figure out which tile ejects to this slot - const sourceTile = acceptorSlotWsTile.add(enumDirectionToVector[worldDirection]); - - let isBlocked = false; - let isConnected = false; - - // Find all entities which are on that tile - const sourceEntities = this.root.map.getLayersContentsMultipleXY( - sourceTile.x, - sourceTile.y - ); - - // Check for every entity: - for (let i = 0; i < sourceEntities.length; ++i) { - const sourceEntity = sourceEntities[i]; - const sourceEjector = sourceEntity.components.ItemEjector; - const sourceStaticComp = sourceEntity.components.StaticMapEntity; - const ejectorAcceptLocalTile = sourceStaticComp.worldToLocalTile(acceptorSlotWsTile); - - // If this entity is on the same layer as the slot - if so, it can either be - // connected, or it can not be connected and thus block the input - if (sourceEntity.layer === slot.layer) { - if ( - sourceEjector && - sourceEjector.anySlotEjectsToLocalTile( - ejectorAcceptLocalTile, - this.root.currentLayer - ) - ) { - // This one is connected, all good - isConnected = true; - } else { - // This one is blocked - isBlocked = true; - } - } - } - - const alpha = isConnected || isBlocked ? 1.0 : 0.3; - const sprite = isBlocked ? badArrowSprite : goodArrowSprite; - - parameters.context.globalAlpha = alpha; - drawRotatedSprite({ - parameters, - sprite, - x: acceptorSlotWsPos.x, - y: acceptorSlotWsPos.y, - angle: Math.radians(enumDirectionToAngle[enumInvertedDirections[worldDirection]]), - size: 13, - offsetY: offsetShift + 13, - }); - parameters.context.globalAlpha = 1; - } - } - } - - if (ejectorComp) { - const slots = ejectorComp.slots; - - // Go over all slots - for (let ejectorSlotIndex = 0; ejectorSlotIndex < slots.length; ++ejectorSlotIndex) { - const slot = slots[ejectorSlotIndex]; - - // Only draw same layer slots - if (slot.layer !== this.root.currentLayer) { - continue; - } - - const ejectorSlotWsTile = staticComp.localTileToWorld( - ejectorComp.getSlotTargetLocalTile(ejectorSlotIndex) - ); - const ejectorSLotWsPos = ejectorSlotWsTile.toWorldSpaceCenterOfTile(); - const ejectorSlotWsDirection = staticComp.localDirectionToWorld(slot.direction); - - let isBlocked = false; - let isConnected = false; - - // Find all entities which are on that tile - const destEntities = this.root.map.getLayersContentsMultipleXY( - ejectorSlotWsTile.x, - ejectorSlotWsTile.y - ); - - // Check for every entity: - for (let i = 0; i < destEntities.length; ++i) { - const destEntity = destEntities[i]; - const destAcceptor = destEntity.components.ItemAcceptor; - const destStaticComp = destEntity.components.StaticMapEntity; - - // If this entity is on the same layer as the slot - if so, it can either be - // connected, or it can not be connected and thus block the input - if (destEntity.layer === slot.layer) { - const destLocalTile = destStaticComp.worldToLocalTile(ejectorSlotWsTile); - const destLocalDir = destStaticComp.worldDirectionToLocal(ejectorSlotWsDirection); - if ( - destAcceptor && - destAcceptor.findMatchingSlot(destLocalTile, destLocalDir, this.root.currentLayer) - ) { - // This one is connected, all good - isConnected = true; - } else { - // This one is blocked - isBlocked = true; - } - } - } - - const alpha = isConnected || isBlocked ? 1.0 : 0.3; - const sprite = isBlocked ? badArrowSprite : goodArrowSprite; - - parameters.context.globalAlpha = alpha; - drawRotatedSprite({ - parameters, - sprite, - x: ejectorSLotWsPos.x, - y: ejectorSLotWsPos.y, - angle: Math.radians(enumDirectionToAngle[ejectorSlotWsDirection]), - size: 13, - offsetY: offsetShift, - }); - parameters.context.globalAlpha = 1; - } - } - } -} +import { ClickDetector } from "../../../core/click_detector"; +import { globalConfig } from "../../../core/config"; +import { DrawParameters } from "../../../core/draw_parameters"; +import { drawRotatedSprite } from "../../../core/draw_utils"; +import { Loader } from "../../../core/loader"; +import { clamp, makeDiv, removeAllChildren } from "../../../core/utils"; +import { + enumDirectionToAngle, + enumDirectionToVector, + enumInvertedDirections, + Vector, + enumDirection, +} from "../../../core/vector"; +import { T } from "../../../translations"; +import { KEYMAPPINGS } from "../../key_action_mapper"; +import { defaultBuildingVariant } from "../../meta_building"; +import { THEME } from "../../theme"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; +import { HUDBuildingPlacerLogic } from "./building_placer_logic"; +import { makeOffscreenBuffer } from "../../../core/buffer_utils"; +import { layers } from "../../root"; +import { getCodeFromBuildingData } from "../../building_codes"; + +export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { + /** + * @param {HTMLElement} parent + */ + createElements(parent) { + this.element = makeDiv(parent, "ingame_HUD_PlacementHints", [], ``); + + this.buildingInfoElements = {}; + this.buildingInfoElements.label = makeDiv(this.element, null, ["buildingLabel"], "Extract"); + this.buildingInfoElements.desc = makeDiv(this.element, null, ["description"], ""); + this.buildingInfoElements.descText = makeDiv(this.buildingInfoElements.desc, null, ["text"], ""); + this.buildingInfoElements.additionalInfo = makeDiv( + this.buildingInfoElements.desc, + null, + ["additionalInfo"], + "" + ); + this.buildingInfoElements.hotkey = makeDiv(this.buildingInfoElements.desc, null, ["hotkey"], ""); + this.buildingInfoElements.tutorialImage = makeDiv(this.element, null, ["buildingImage"]); + + this.variantsElement = makeDiv(parent, "ingame_HUD_PlacerVariants"); + + const compact = this.root.app.settings.getAllSettings().compactBuildingInfo; + this.element.classList.toggle("compact", compact); + this.variantsElement.classList.toggle("compact", compact); + } + + initialize() { + super.initialize(); + + // Bind to signals + this.signals.variantChanged.add(this.rerenderVariants, this); + this.root.hud.signals.buildingSelectedForPlacement.add(this.startSelection, this); + + this.domAttach = new DynamicDomAttach(this.root, this.element, { trackHover: true }); + this.variantsAttach = new DynamicDomAttach(this.root, this.variantsElement, {}); + + this.currentInterpolatedCornerTile = new Vector(); + + this.lockIndicatorSprites = {}; + layers.forEach(layer => { + this.lockIndicatorSprites[layer] = this.makeLockIndicatorSprite(layer); + }); + + // + + /** + * Stores the click detectors for the variants so we can clean them up later + * @type {Array} + */ + this.variantClickDetectors = []; + } + + /** + * Makes the lock indicator sprite for the given layer + * @param {Layer} layer + */ + makeLockIndicatorSprite(layer) { + const dims = 48; + const [canvas, context] = makeOffscreenBuffer(dims, dims, { + smooth: true, + reusable: false, + label: "lock-direction-indicator", + }); + + context.fillStyle = THEME.map.directionLock[layer].color; + context.strokeStyle = THEME.map.directionLock[layer].color; + context.lineWidth = 2; + + const padding = 5; + const height = dims * 0.5; + const bottom = (dims + height) / 2; + + context.moveTo(padding, bottom); + context.lineTo(dims / 2, bottom - height); + context.lineTo(dims - padding, bottom); + context.closePath(); + context.stroke(); + context.fill(); + + return canvas; + } + + /** + * Rerenders the building info dialog + */ + rerenderInfoDialog() { + const metaBuilding = this.currentMetaBuilding.get(); + + if (!metaBuilding) { + return; + } + + const variant = this.currentVariant.get(); + + this.buildingInfoElements.label.innerHTML = T.buildings[metaBuilding.id][variant].name; + this.buildingInfoElements.descText.innerHTML = T.buildings[metaBuilding.id][variant].description; + + const binding = this.root.keyMapper.getBinding(KEYMAPPINGS.buildings[metaBuilding.getId()]); + this.buildingInfoElements.hotkey.innerHTML = T.ingame.buildingPlacement.hotkeyLabel.replace( + "", + "" + binding.getKeyCodeString() + "" + ); + + this.buildingInfoElements.tutorialImage.setAttribute( + "data-icon", + "building_tutorials/" + + metaBuilding.getId() + + (variant === defaultBuildingVariant ? "" : "-" + variant) + + ".png" + ); + + removeAllChildren(this.buildingInfoElements.additionalInfo); + const additionalInfo = metaBuilding.getAdditionalStatistics(this.root, this.currentVariant.get()); + for (let i = 0; i < additionalInfo.length; ++i) { + const [label, contents] = additionalInfo[i]; + this.buildingInfoElements.additionalInfo.innerHTML += ` + + ${contents} + `; + } + } + + cleanup() { + super.cleanup(); + this.cleanupVariantClickDetectors(); + } + + /** + * Cleans up all variant click detectors + */ + cleanupVariantClickDetectors() { + for (let i = 0; i < this.variantClickDetectors.length; ++i) { + const detector = this.variantClickDetectors[i]; + detector.cleanup(); + } + this.variantClickDetectors = []; + } + + /** + * Rerenders the variants displayed + */ + rerenderVariants() { + removeAllChildren(this.variantsElement); + this.rerenderInfoDialog(); + + const metaBuilding = this.currentMetaBuilding.get(); + + // First, clear up all click detectors + this.cleanupVariantClickDetectors(); + + if (!metaBuilding) { + return; + } + const availableVariants = metaBuilding.getAvailableVariants(this.root); + if (availableVariants.length === 1) { + return; + } + + makeDiv( + this.variantsElement, + null, + ["explanation"], + T.ingame.buildingPlacement.cycleBuildingVariants.replace( + "", + "" + + this.root.keyMapper + .getBinding(KEYMAPPINGS.placement.cycleBuildingVariants) + .getKeyCodeString() + + "" + ) + ); + + const container = makeDiv(this.variantsElement, null, ["variants"]); + + for (let i = 0; i < availableVariants.length; ++i) { + const variant = availableVariants[i]; + + const element = makeDiv(container, null, ["variant"]); + element.classList.toggle("active", variant === this.currentVariant.get()); + makeDiv(element, null, ["label"], variant); + + const iconSize = 64; + + const dimensions = metaBuilding.getDimensions(variant); + const sprite = metaBuilding.getPreviewSprite(0, variant); + const spriteWrapper = makeDiv(element, null, ["iconWrap"]); + spriteWrapper.setAttribute("data-tile-w", dimensions.x); + spriteWrapper.setAttribute("data-tile-h", dimensions.y); + + spriteWrapper.innerHTML = sprite.getAsHTML(iconSize * dimensions.x, iconSize * dimensions.y); + + const detector = new ClickDetector(element, { + consumeEvents: true, + targetOnly: true, + }); + detector.click.add(() => this.setVariant(variant)); + } + } + + /** + * + * @param {DrawParameters} parameters + */ + draw(parameters) { + if (this.root.camera.zoomLevel < globalConfig.mapChunkOverviewMinZoom) { + // Dont allow placing in overview mode + this.domAttach.update(false); + this.variantsAttach.update(false); + return; + } + + this.domAttach.update(!!this.currentMetaBuilding.get()); + this.variantsAttach.update(!!this.currentMetaBuilding.get()); + const metaBuilding = this.currentMetaBuilding.get(); + + if (!metaBuilding) { + return; + } + + // Draw direction lock + if (this.isDirectionLockActive) { + this.drawDirectionLock(parameters); + } else { + this.drawRegularPlacement(parameters); + } + + if (metaBuilding.getShowWiresLayerPreview()) { + this.drawLayerPeek(parameters); + } + } + + /** + * + * @param {DrawParameters} parameters + */ + drawLayerPeek(parameters) { + const mousePosition = this.root.app.mousePosition; + if (!mousePosition) { + // Not on screen + return; + } + + const worldPosition = this.root.camera.screenToWorld(mousePosition); + + // Draw peeker + this.root.hud.parts.layerPreview.renderPreview( + parameters, + worldPosition, + 1 / this.root.camera.zoomLevel + ); + } + + /** + * @param {DrawParameters} parameters + */ + drawRegularPlacement(parameters) { + const mousePosition = this.root.app.mousePosition; + if (!mousePosition) { + // Not on screen + return; + } + + const metaBuilding = this.currentMetaBuilding.get(); + + const worldPos = this.root.camera.screenToWorld(mousePosition); + const mouseTile = worldPos.toTileSpace(); + + // Compute best rotation variant + const { + rotation, + rotationVariant, + connectedEntities, + } = metaBuilding.computeOptimalDirectionAndRotationVariantAtTile({ + root: this.root, + tile: mouseTile, + rotation: this.currentBaseRotation, + variant: this.currentVariant.get(), + layer: metaBuilding.getLayer(), + }); + + // Check if there are connected entities + if (connectedEntities) { + for (let i = 0; i < connectedEntities.length; ++i) { + const connectedEntity = connectedEntities[i]; + const connectedWsPoint = connectedEntity.components.StaticMapEntity.getTileSpaceBounds() + .getCenter() + .toWorldSpace(); + + const startWsPoint = mouseTile.toWorldSpaceCenterOfTile(); + + const startOffset = connectedWsPoint + .sub(startWsPoint) + .normalize() + .multiplyScalar(globalConfig.tileSize * 0.3); + const effectiveStartPoint = startWsPoint.add(startOffset); + const effectiveEndPoint = connectedWsPoint.sub(startOffset); + + parameters.context.globalAlpha = 0.6; + + // parameters.context.lineCap = "round"; + parameters.context.strokeStyle = "#7f7"; + parameters.context.lineWidth = 10; + parameters.context.beginPath(); + parameters.context.moveTo(effectiveStartPoint.x, effectiveStartPoint.y); + parameters.context.lineTo(effectiveEndPoint.x, effectiveEndPoint.y); + parameters.context.stroke(); + parameters.context.globalAlpha = 1; + // parameters.context.lineCap = "square"; + } + } + + // Synchronize rotation and origin + this.fakeEntity.layer = metaBuilding.getLayer(); + const staticComp = this.fakeEntity.components.StaticMapEntity; + staticComp.origin = mouseTile; + staticComp.rotation = rotation; + metaBuilding.updateVariants(this.fakeEntity, rotationVariant, this.currentVariant.get()); + staticComp.code = getCodeFromBuildingData( + this.currentMetaBuilding.get(), + this.currentVariant.get(), + rotationVariant + ); + + const canBuild = this.root.logic.checkCanPlaceEntity(this.fakeEntity); + + // Fade in / out + parameters.context.lineWidth = 1; + + // Determine the bounds and visualize them + const entityBounds = staticComp.getTileSpaceBounds(); + const drawBorder = -3; + if (canBuild) { + parameters.context.strokeStyle = "rgba(56, 235, 111, 0.5)"; + parameters.context.fillStyle = "rgba(56, 235, 111, 0.2)"; + } else { + parameters.context.strokeStyle = "rgba(255, 0, 0, 0.2)"; + parameters.context.fillStyle = "rgba(255, 0, 0, 0.2)"; + } + + parameters.context.beginRoundedRect( + entityBounds.x * globalConfig.tileSize - drawBorder, + entityBounds.y * globalConfig.tileSize - drawBorder, + entityBounds.w * globalConfig.tileSize + 2 * drawBorder, + entityBounds.h * globalConfig.tileSize + 2 * drawBorder, + 4 + ); + parameters.context.stroke(); + // parameters.context.fill(); + parameters.context.globalAlpha = 1; + + // HACK to draw the entity sprite + const previewSprite = metaBuilding.getBlueprintSprite(rotationVariant, this.currentVariant.get()); + staticComp.origin = worldPos.divideScalar(globalConfig.tileSize).subScalars(0.5, 0.5); + staticComp.drawSpriteOnBoundsClipped(parameters, previewSprite); + staticComp.origin = mouseTile; + + // Draw ejectors + if (canBuild) { + this.drawMatchingAcceptorsAndEjectors(parameters); + } + } + + /** + * @param {DrawParameters} parameters + */ + drawDirectionLock(parameters) { + const mousePosition = this.root.app.mousePosition; + if (!mousePosition) { + // Not on screen + return; + } + + const mouseWorld = this.root.camera.screenToWorld(mousePosition); + const mouseTile = mouseWorld.toTileSpace(); + parameters.context.fillStyle = THEME.map.directionLock[this.root.currentLayer].color; + parameters.context.strokeStyle = THEME.map.directionLock[this.root.currentLayer].background; + parameters.context.lineWidth = 10; + + parameters.context.beginCircle(mouseWorld.x, mouseWorld.y, 4); + parameters.context.fill(); + + if (this.lastDragTile) { + const startLine = this.lastDragTile.toWorldSpaceCenterOfTile(); + const endLine = mouseTile.toWorldSpaceCenterOfTile(); + const midLine = this.currentDirectionLockCorner.toWorldSpaceCenterOfTile(); + + parameters.context.beginCircle(startLine.x, startLine.y, 8); + parameters.context.fill(); + + parameters.context.beginPath(); + parameters.context.moveTo(startLine.x, startLine.y); + parameters.context.lineTo(midLine.x, midLine.y); + parameters.context.lineTo(endLine.x, endLine.y); + parameters.context.stroke(); + + parameters.context.beginCircle(endLine.x, endLine.y, 5); + parameters.context.fill(); + + // Draw arrow + const arrowSprite = this.lockIndicatorSprites[this.root.currentLayer]; + const path = this.computeDirectionLockPath(); + for (let i = 0; i < path.length - 1; i += 1) { + const { rotation, tile } = path[i]; + const worldPos = tile.toWorldSpaceCenterOfTile(); + const angle = Math.radians(rotation); + + parameters.context.translate(worldPos.x, worldPos.y); + parameters.context.rotate(angle); + parameters.context.drawImage( + arrowSprite, + -6, + -globalConfig.halfTileSize - + clamp((this.root.time.realtimeNow() * 1.5) % 1.0, 0, 1) * 1 * globalConfig.tileSize + + globalConfig.halfTileSize - + 6, + 12, + 12 + ); + parameters.context.rotate(-angle); + parameters.context.translate(-worldPos.x, -worldPos.y); + } + } + } + + /** + * @param {DrawParameters} parameters + */ + drawMatchingAcceptorsAndEjectors(parameters) { + const acceptorComp = this.fakeEntity.components.ItemAcceptor; + const ejectorComp = this.fakeEntity.components.ItemEjector; + const staticComp = this.fakeEntity.components.StaticMapEntity; + const beltComp = this.fakeEntity.components.Belt; + const minerComp = this.fakeEntity.components.Miner; + + const goodArrowSprite = Loader.getSprite("sprites/misc/slot_good_arrow.png"); + const badArrowSprite = Loader.getSprite("sprites/misc/slot_bad_arrow.png"); + + // Just ignore the following code please ... thanks! + + const offsetShift = 10; + + let acceptorSlots = []; + let ejectorSlots = []; + + if (ejectorComp) { + ejectorSlots = ejectorComp.slots.slice(); + } + + if (acceptorComp) { + acceptorSlots = acceptorComp.slots.slice(); + } + + if (beltComp) { + const fakeEjectorSlot = beltComp.getFakeEjectorSlot(); + const fakeAcceptorSlot = beltComp.getFakeAcceptorSlot(); + ejectorSlots.push(fakeEjectorSlot); + acceptorSlots.push(fakeAcceptorSlot); + } + + for (let acceptorSlotIndex = 0; acceptorSlotIndex < acceptorSlots.length; ++acceptorSlotIndex) { + const slot = acceptorSlots[acceptorSlotIndex]; + + const acceptorSlotWsTile = staticComp.localTileToWorld(slot.pos); + const acceptorSlotWsPos = acceptorSlotWsTile.toWorldSpaceCenterOfTile(); + + // Go over all slots + for ( + let acceptorDirectionIndex = 0; + acceptorDirectionIndex < slot.directions.length; + ++acceptorDirectionIndex + ) { + const direction = slot.directions[acceptorDirectionIndex]; + const worldDirection = staticComp.localDirectionToWorld(direction); + + // Figure out which tile ejects to this slot + const sourceTile = acceptorSlotWsTile.add(enumDirectionToVector[worldDirection]); + + let isBlocked = false; + let isConnected = false; + + // Find all entities which are on that tile + const sourceEntities = this.root.map.getLayersContentsMultipleXY(sourceTile.x, sourceTile.y); + + // Check for every entity: + for (let i = 0; i < sourceEntities.length; ++i) { + const sourceEntity = sourceEntities[i]; + const sourceEjector = sourceEntity.components.ItemEjector; + const sourceBeltComp = sourceEntity.components.Belt; + const sourceStaticComp = sourceEntity.components.StaticMapEntity; + const ejectorAcceptLocalTile = sourceStaticComp.worldToLocalTile(acceptorSlotWsTile); + + // If this entity is on the same layer as the slot - if so, it can either be + // connected, or it can not be connected and thus block the input + if (sourceEjector && sourceEjector.anySlotEjectsToLocalTile(ejectorAcceptLocalTile)) { + // This one is connected, all good + isConnected = true; + } else if ( + sourceBeltComp && + sourceStaticComp.localDirectionToWorld(sourceBeltComp.direction) === + enumInvertedDirections[worldDirection] + ) { + // Belt connected + isConnected = true; + } else { + // This one is blocked + isBlocked = true; + } + } + + const alpha = isConnected || isBlocked ? 1.0 : 0.3; + const sprite = isBlocked ? badArrowSprite : goodArrowSprite; + + parameters.context.globalAlpha = alpha; + drawRotatedSprite({ + parameters, + sprite, + x: acceptorSlotWsPos.x, + y: acceptorSlotWsPos.y, + angle: Math.radians(enumDirectionToAngle[enumInvertedDirections[worldDirection]]), + size: 13, + offsetY: offsetShift + 13, + }); + parameters.context.globalAlpha = 1; + } + } + + // Go over all slots + for (let ejectorSlotIndex = 0; ejectorSlotIndex < ejectorSlots.length; ++ejectorSlotIndex) { + const slot = ejectorSlots[ejectorSlotIndex]; + + const ejectorSlotLocalTile = slot.pos.add(enumDirectionToVector[slot.direction]); + const ejectorSlotWsTile = staticComp.localTileToWorld(ejectorSlotLocalTile); + + const ejectorSLotWsPos = ejectorSlotWsTile.toWorldSpaceCenterOfTile(); + const ejectorSlotWsDirection = staticComp.localDirectionToWorld(slot.direction); + + let isBlocked = false; + let isConnected = false; + + // Find all entities which are on that tile + const destEntities = this.root.map.getLayersContentsMultipleXY( + ejectorSlotWsTile.x, + ejectorSlotWsTile.y + ); + + // Check for every entity: + for (let i = 0; i < destEntities.length; ++i) { + const destEntity = destEntities[i]; + const destAcceptor = destEntity.components.ItemAcceptor; + const destStaticComp = destEntity.components.StaticMapEntity; + const destMiner = destEntity.components.Miner; + + const destLocalTile = destStaticComp.worldToLocalTile(ejectorSlotWsTile); + const destLocalDir = destStaticComp.worldDirectionToLocal(ejectorSlotWsDirection); + if (destAcceptor && destAcceptor.findMatchingSlot(destLocalTile, destLocalDir)) { + // This one is connected, all good + isConnected = true; + } else if (destEntity.components.Belt && destLocalDir === enumDirection.top) { + // Connected to a belt + isConnected = true; + } else if (minerComp && minerComp.chainable && destMiner && destMiner.chainable) { + // Chainable miners connected to eachother + isConnected = true; + } else { + // This one is blocked + isBlocked = true; + } + } + + const alpha = isConnected || isBlocked ? 1.0 : 0.3; + const sprite = isBlocked ? badArrowSprite : goodArrowSprite; + + parameters.context.globalAlpha = alpha; + drawRotatedSprite({ + parameters, + sprite, + x: ejectorSLotWsPos.x, + y: ejectorSLotWsPos.y, + angle: Math.radians(enumDirectionToAngle[ejectorSlotWsDirection]), + size: 13, + offsetY: offsetShift, + }); + parameters.context.globalAlpha = 1; + } + } +} diff --git a/src/js/game/hud/parts/building_placer_logic.js b/src/js/game/hud/parts/building_placer_logic.js index f0266b77..6031e555 100644 --- a/src/js/game/hud/parts/building_placer_logic.js +++ b/src/js/game/hud/parts/building_placer_logic.js @@ -1,839 +1,778 @@ -import { globalConfig } from "../../../core/config"; -import { gMetaBuildingRegistry } from "../../../core/global_registries"; -import { Signal, STOP_PROPAGATION } from "../../../core/signal"; -import { TrackedState } from "../../../core/tracked_state"; -import { Vector } from "../../../core/vector"; -import { enumMouseButton } from "../../camera"; -import { StaticMapEntityComponent } from "../../components/static_map_entity"; -import { Entity } from "../../entity"; -import { KEYMAPPINGS } from "../../key_action_mapper"; -import { defaultBuildingVariant, MetaBuilding } from "../../meta_building"; -import { BaseHUDPart } from "../base_hud_part"; -import { SOUNDS } from "../../../platform/sound"; -import { MetaMinerBuilding, enumMinerVariants } from "../../buildings/miner"; -import { enumHubGoalRewards } from "../../tutorial_goals"; -import { enumLayer } from "../../root"; - -/** - * Contains all logic for the building placer - this doesn't include the rendering - * of info boxes or drawing. - */ -export class HUDBuildingPlacerLogic extends BaseHUDPart { - /** - * Initializes the logic - * @see BaseHUDPart.initialize - */ - initialize() { - /** - * We use a fake entity to get information about how a building will look - * once placed - * @type {Entity} - */ - this.fakeEntity = null; - - // Signals - this.signals = { - variantChanged: new Signal(), - draggingStarted: new Signal(), - }; - - /** - * The current building - * @type {TypedTrackedState} - */ - this.currentMetaBuilding = new TrackedState(this.onSelectedMetaBuildingChanged, this); - - /** - * The current rotation - * @type {number} - */ - this.currentBaseRotationGeneral = 0; - - /** - * The current rotation preference for each building. - * @type{Object.} - */ - this.preferredBaseRotations = {}; - - /** - * Whether we are currently dragging - * @type {boolean} - */ - this.currentlyDragging = false; - - /** - * Current building variant - * @type {TypedTrackedState} - */ - this.currentVariant = new TrackedState(() => this.signals.variantChanged.dispatch()); - - /** - * Whether we are currently drag-deleting - * @type {boolean} - */ - this.currentlyDeleting = false; - - /** - * Stores which variants for each building we prefer, this is based on what - * the user last selected - * @type {Object.} - */ - this.preferredVariants = {}; - - /** - * The tile we last dragged from - * @type {Vector} - */ - this.lastDragTile = null; - - /** - * The side for direction lock - * @type {number} (0|1) - */ - this.currentDirectionLockSide = 0; - - /** - * Whether the side for direction lock has not yet been determined. - * @type {boolean} - */ - this.currentDirectionLockSideIndeterminate = true; - - this.initializeBindings(); - } - - /** - * Initializes all bindings - */ - initializeBindings() { - // KEYBINDINGS - const keyActionMapper = this.root.keyMapper; - keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.tryRotate, this); - keyActionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildingVariants).add(this.cycleVariants, this); - keyActionMapper - .getBinding(KEYMAPPINGS.placement.switchDirectionLockSide) - .add(this.switchDirectionLockSide, this); - keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this); - keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.startPipette, this); - this.root.gameState.inputReciever.keyup.add(this.checkForDirectionLockSwitch, this); - - // BINDINGS TO GAME EVENTS - this.root.hud.signals.buildingsSelectedForCopy.add(this.abortPlacement, this); - this.root.hud.signals.pasteBlueprintRequested.add(this.abortPlacement, this); - this.root.signals.storyGoalCompleted.add(() => this.signals.variantChanged.dispatch()); - this.root.signals.upgradePurchased.add(() => this.signals.variantChanged.dispatch()); - this.root.signals.editModeChanged.add(this.onEditModeChanged, this); - - // MOUSE BINDINGS - this.root.camera.downPreHandler.add(this.onMouseDown, this); - this.root.camera.movePreHandler.add(this.onMouseMove, this); - this.root.camera.upPostHandler.add(this.onMouseUp, this); - } - - /** - * Called when the edit mode got changed - * @param {enumLayer} editMode - */ - onEditModeChanged(editMode) { - const metaBuilding = this.currentMetaBuilding.get(); - if (metaBuilding) { - if (metaBuilding.getLayer() !== editMode) { - // This layer doesn't fit the edit mode anymore - this.currentMetaBuilding.set(null); - } - } - } - - /** - * Returns the current base rotation for the current meta-building. - * @returns {number} - */ - get currentBaseRotation() { - if (!this.root.app.settings.getAllSettings().rotationByBuilding) { - return this.currentBaseRotationGeneral; - } - const metaBuilding = this.currentMetaBuilding.get(); - if (metaBuilding && this.preferredBaseRotations.hasOwnProperty(metaBuilding.getId())) { - return this.preferredBaseRotations[metaBuilding.getId()]; - } else { - return this.currentBaseRotationGeneral; - } - } - - /** - * Sets the base rotation for the current meta-building. - * @param {number} rotation The new rotation/angle. - */ - set currentBaseRotation(rotation) { - if (!this.root.app.settings.getAllSettings().rotationByBuilding) { - this.currentBaseRotationGeneral = rotation; - } else { - const metaBuilding = this.currentMetaBuilding.get(); - if (metaBuilding) { - this.preferredBaseRotations[metaBuilding.getId()] = rotation; - } else { - this.currentBaseRotationGeneral = rotation; - } - } - } - - /** - * Returns if the direction lock is currently active - * @returns {boolean} - */ - get isDirectionLockActive() { - const metaBuilding = this.currentMetaBuilding.get(); - return ( - metaBuilding && - metaBuilding.getHasDirectionLockAvailable() && - this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.lockBeltDirection).pressed - ); - } - - /** - * Returns the current direction lock corner, that is, the corner between - * mouse and original start point - * @returns {Vector|null} - */ - get currentDirectionLockCorner() { - const mousePosition = this.root.app.mousePosition; - if (!mousePosition) { - // Not on screen - return null; - } - - if (!this.lastDragTile) { - // Haven't dragged yet - return null; - } - - // Figure which points the line visits - const worldPos = this.root.camera.screenToWorld(mousePosition); - const mouseTile = worldPos.toTileSpace(); - - // Figure initial direction - const dx = Math.abs(this.lastDragTile.x - mouseTile.x); - const dy = Math.abs(this.lastDragTile.y - mouseTile.y); - if (dx === 0 && dy === 0) { - // Back at the start. Try a new direction. - this.currentDirectionLockSideIndeterminate = true; - } else if (this.currentDirectionLockSideIndeterminate) { - this.currentDirectionLockSideIndeterminate = false; - this.currentDirectionLockSide = dx <= dy ? 0 : 1; - } - - if (this.currentDirectionLockSide === 0) { - return new Vector(this.lastDragTile.x, mouseTile.y); - } else { - return new Vector(mouseTile.x, this.lastDragTile.y); - } - } - - /** - * Aborts the placement - */ - abortPlacement() { - if (this.currentMetaBuilding.get()) { - this.currentMetaBuilding.set(null); - return STOP_PROPAGATION; - } - } - - /** - * Aborts any dragging - */ - abortDragging() { - this.currentlyDragging = true; - this.currentlyDeleting = false; - this.initialPlacementVector = null; - this.lastDragTile = null; - } - - /** - * @see BaseHUDPart.update - */ - update() { - // Always update since the camera might have moved - const mousePos = this.root.app.mousePosition; - if (mousePos) { - this.onMouseMove(mousePos); - } - - // Make sure we have nothing selected while in overview mode - if (this.root.camera.getIsMapOverlayActive()) { - if (this.currentMetaBuilding.get()) { - this.currentMetaBuilding.set(null); - } - } - } - - /** - * Tries to rotate the current building - */ - tryRotate() { - const selectedBuilding = this.currentMetaBuilding.get(); - if (selectedBuilding) { - if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).pressed) { - this.currentBaseRotation = (this.currentBaseRotation + 270) % 360; - } else { - this.currentBaseRotation = (this.currentBaseRotation + 90) % 360; - } - const staticComp = this.fakeEntity.components.StaticMapEntity; - staticComp.rotation = this.currentBaseRotation; - } - } - /** - * Tries to delete the building under the mouse - */ - deleteBelowCursor() { - const mousePosition = this.root.app.mousePosition; - if (!mousePosition) { - // Not on screen - return; - } - - const worldPos = this.root.camera.screenToWorld(mousePosition); - const tile = worldPos.toTileSpace(); - const contents = this.root.map.getTileContent(tile, this.root.currentLayer); - if (contents) { - if (this.root.logic.tryDeleteBuilding(contents)) { - this.root.soundProxy.playUi(SOUNDS.destroyBuilding); - } - } - } - - /** - * Starts the pipette function - */ - startPipette() { - // Disable in overview - if (this.root.camera.getIsMapOverlayActive()) { - return; - } - - const mousePosition = this.root.app.mousePosition; - if (!mousePosition) { - // Not on screen - return; - } - - const worldPos = this.root.camera.screenToWorld(mousePosition); - const tile = worldPos.toTileSpace(); - - const contents = this.root.map.getTileContent(tile, this.root.currentLayer); - if (!contents) { - const tileBelow = this.root.map.getLowerLayerContentXY(tile.x, tile.y); - - // Check if there's a shape or color item below, if so select the miner - if (tileBelow) { - this.currentMetaBuilding.set(gMetaBuildingRegistry.findByClass(MetaMinerBuilding)); - - // Select chained miner if available, since thats always desired once unlocked - if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_miner_chainable)) { - this.currentVariant.set(enumMinerVariants.chainable); - } - } else { - this.currentMetaBuilding.set(null); - } - return; - } - - // Try to extract the building - const extracted = this.hack_reconstructMetaBuildingAndVariantFromBuilding(contents); - - // If the building we are picking is the same as the one we have, clear the cursor. - if ( - !extracted || - (extracted.metaBuilding === this.currentMetaBuilding.get() && - extracted.variant === this.currentVariant.get()) - ) { - this.currentMetaBuilding.set(null); - return; - } - - this.currentMetaBuilding.set(extracted.metaBuilding); - this.currentVariant.set(extracted.variant); - this.currentBaseRotation = contents.components.StaticMapEntity.rotation; - } - - /** - * HACK! - * - * This attempts to reconstruct the meta building and its variant from a given entity - * @param {Entity} entity - * @returns {{ metaBuilding: MetaBuilding, variant: string }} - */ - hack_reconstructMetaBuildingAndVariantFromBuilding(entity) { - if (entity.components.Hub) { - // Hub is not copyable - return null; - } - - const matches = []; - const metaBuildings = gMetaBuildingRegistry.entries; - for (let i = 0; i < metaBuildings.length; ++i) { - const metaBuilding = metaBuildings[i]; - const availableVariants = metaBuilding.getAvailableVariants(this.root); - checkVariant: for (let k = 0; k < availableVariants.length; ++k) { - const variant = availableVariants[k]; - let unplaced = metaBuilding.createEntity({ - root: this.root, - variant, - origin: new Vector(0, 0), - rotation: 0, - originalRotation: 0, - rotationVariant: 0, - }); - - // Compare if both entities share the same components - for (let component in entity.components) { - if ((entity.components[component] == null) !== (unplaced.components[component] == null)) { - continue checkVariant; - } - } - - // Check for same item processor - if ( - entity.components.ItemProcessor && - entity.components.ItemProcessor.type != unplaced.components.ItemProcessor.type - ) { - continue checkVariant; - } - - // Check for underground belt - if ( - entity.components.UndergroundBelt && - entity.components.UndergroundBelt.tier != unplaced.components.UndergroundBelt.tier - ) { - continue checkVariant; - } - - // Check for same sprite key - except for underground belts - // since the sprite may vary here - if ( - !entity.components.UndergroundBelt && - entity.components.StaticMapEntity.spriteKey != - unplaced.components.StaticMapEntity.spriteKey - ) { - continue checkVariant; - } - matches.push({ metaBuilding, variant }); - } - } - - if (matches.length == 1) { - const staticEntity = entity.components.StaticMapEntity; - const key = staticEntity.spriteKey || staticEntity.blueprintSpriteKey; - assert( - key && - key.includes(matches[0].metaBuilding.id) && - (matches[0].variant === defaultBuildingVariant || key.includes(matches[0].variant)) - ); - return matches[0]; - } - return null; - } - - switchDirectionLockSide() { - this.currentDirectionLockSide = 1 - this.currentDirectionLockSide; - } - - /** - * Checks if the direction lock key got released and if such, resets the placement - * @param {any} args - */ - checkForDirectionLockSwitch({ keyCode }) { - if ( - keyCode === - this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.lockBeltDirection).keyCode - ) { - this.abortDragging(); - } - } - - /** - * Tries to place the current building at the given tile - * @param {Vector} tile - */ - tryPlaceCurrentBuildingAt(tile) { - if (this.root.camera.zoomLevel < globalConfig.mapChunkOverviewMinZoom) { - // Dont allow placing in overview mode - return; - } - - const metaBuilding = this.currentMetaBuilding.get(); - const { rotation, rotationVariant } = metaBuilding.computeOptimalDirectionAndRotationVariantAtTile({ - root: this.root, - tile, - rotation: this.currentBaseRotation, - variant: this.currentVariant.get(), - layer: metaBuilding.getLayer(), - }); - - const entity = this.root.logic.tryPlaceBuilding({ - origin: tile, - rotation, - rotationVariant, - originalRotation: this.currentBaseRotation, - building: this.currentMetaBuilding.get(), - variant: this.currentVariant.get(), - }); - - if (entity) { - // Succesfully placed, find which entity we actually placed - this.root.signals.entityManuallyPlaced.dispatch(entity); - - // Check if we should flip the orientation (used for tunnels) - if ( - metaBuilding.getFlipOrientationAfterPlacement() && - !this.root.keyMapper.getBinding( - KEYMAPPINGS.placementModifiers.placementDisableAutoOrientation - ).pressed - ) { - this.currentBaseRotation = (180 + this.currentBaseRotation) % 360; - } - - // Check if we should stop placement - if ( - !metaBuilding.getStayInPlacementMode() && - !this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeMultiple).pressed && - !this.root.app.settings.getAllSettings().alwaysMultiplace - ) { - // Stop placement - this.currentMetaBuilding.set(null); - } - return true; - } else { - return false; - } - } - - /** - * Cycles through the variants - */ - cycleVariants() { - const metaBuilding = this.currentMetaBuilding.get(); - if (!metaBuilding) { - this.currentVariant.set(defaultBuildingVariant); - } else { - const availableVariants = metaBuilding.getAvailableVariants(this.root); - const index = availableVariants.indexOf(this.currentVariant.get()); - assert( - index >= 0, - "Current variant was invalid: " + this.currentVariant.get() + " out of " + availableVariants - ); - const newIndex = (index + 1) % availableVariants.length; - const newVariant = availableVariants[newIndex]; - this.setVariant(newVariant); - } - } - - /** - * Sets the current variant to the given variant - * @param {string} variant - */ - setVariant(variant) { - const metaBuilding = this.currentMetaBuilding.get(); - this.currentVariant.set(variant); - - this.preferredVariants[metaBuilding.getId()] = variant; - } - - /** - * Performs the direction locked placement between two points after - * releasing the mouse - */ - executeDirectionLockedPlacement() { - const metaBuilding = this.currentMetaBuilding.get(); - if (!metaBuilding) { - // No active building - return; - } - - // Get path to place - const path = this.computeDirectionLockPath(); - - // Store if we placed anything - let anythingPlaced = false; - - // Perform this in bulk to avoid recalculations - this.root.logic.performBulkOperation(() => { - for (let i = 0; i < path.length; ++i) { - const { rotation, tile } = path[i]; - this.currentBaseRotation = rotation; - if (this.tryPlaceCurrentBuildingAt(tile)) { - anythingPlaced = true; - } - } - }); - - if (anythingPlaced) { - this.root.soundProxy.playUi(metaBuilding.getPlacementSound()); - } - } - - /** - * Finds the path which the current direction lock will use - * @returns {Array<{ tile: Vector, rotation: number }>} - */ - computeDirectionLockPath() { - const mousePosition = this.root.app.mousePosition; - if (!mousePosition) { - // Not on screen - return []; - } - - let result = []; - - // Figure which points the line visits - const worldPos = this.root.camera.screenToWorld(mousePosition); - let endTile = worldPos.toTileSpace(); - let startTile = this.lastDragTile; - - // if the alt key is pressed, reverse belt planner direction by switching start and end tile - if (this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeInverse).pressed) { - let tmp = startTile; - startTile = endTile; - endTile = tmp; - } - - // Place from start to corner - const pathToCorner = this.currentDirectionLockCorner.sub(startTile); - const deltaToCorner = pathToCorner.normalize().round(); - const lengthToCorner = Math.round(pathToCorner.length()); - let currentPos = startTile.copy(); - - let rotation = (Math.round(Math.degrees(deltaToCorner.angle()) / 90) * 90 + 360) % 360; - - if (lengthToCorner > 0) { - for (let i = 0; i < lengthToCorner; ++i) { - result.push({ - tile: currentPos.copy(), - rotation, - }); - currentPos.addInplace(deltaToCorner); - } - } - - // Place from corner to end - const pathFromCorner = endTile.sub(this.currentDirectionLockCorner); - const deltaFromCorner = pathFromCorner.normalize().round(); - const lengthFromCorner = Math.round(pathFromCorner.length()); - - if (lengthFromCorner > 0) { - rotation = (Math.round(Math.degrees(deltaFromCorner.angle()) / 90) * 90 + 360) % 360; - for (let i = 0; i < lengthFromCorner + 1; ++i) { - result.push({ - tile: currentPos.copy(), - rotation, - }); - currentPos.addInplace(deltaFromCorner); - } - } else { - // Finish last one - result.push({ - tile: currentPos.copy(), - rotation, - }); - } - return result; - } - - /** - * Selects a given building - * @param {MetaBuilding} metaBuilding - */ - startSelection(metaBuilding) { - this.currentMetaBuilding.set(metaBuilding); - } - - /** - * Called when the selected buildings changed - * @param {MetaBuilding} metaBuilding - */ - onSelectedMetaBuildingChanged(metaBuilding) { - this.abortDragging(); - this.root.hud.signals.selectedPlacementBuildingChanged.dispatch(metaBuilding); - if (metaBuilding) { - const variant = this.preferredVariants[metaBuilding.getId()] || defaultBuildingVariant; - this.currentVariant.set(variant); - - this.fakeEntity = new Entity(null); - metaBuilding.setupEntityComponents(this.fakeEntity, null); - - this.fakeEntity.addComponent( - new StaticMapEntityComponent({ - origin: new Vector(0, 0), - rotation: 0, - tileSize: metaBuilding.getDimensions(this.currentVariant.get()).copy(), - blueprintSpriteKey: "", - }) - ); - metaBuilding.updateVariants(this.fakeEntity, 0, this.currentVariant.get()); - } else { - this.fakeEntity = null; - } - - // Since it depends on both, rerender twice - this.signals.variantChanged.dispatch(); - } - - /** - * mouse down pre handler - * @param {Vector} pos - * @param {enumMouseButton} button - */ - onMouseDown(pos, button) { - if (this.root.camera.getIsMapOverlayActive()) { - // We do not allow dragging if the overlay is active - return; - } - - const metaBuilding = this.currentMetaBuilding.get(); - - // Placement - if (button === enumMouseButton.left && metaBuilding) { - this.currentlyDragging = true; - this.currentlyDeleting = false; - this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace(); - - // Place initial building, but only if direction lock is not active - if (!this.isDirectionLockActive) { - if (this.tryPlaceCurrentBuildingAt(this.lastDragTile)) { - this.root.soundProxy.playUi(metaBuilding.getPlacementSound()); - } - } - return STOP_PROPAGATION; - } - - // Deletion - if (button === enumMouseButton.right && !metaBuilding) { - this.currentlyDragging = true; - this.currentlyDeleting = true; - this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace(); - this.deleteBelowCursor(); - return STOP_PROPAGATION; - } - - // Cancel placement - if (button === enumMouseButton.right && metaBuilding) { - this.currentMetaBuilding.set(null); - } - } - - /** - * mouse move pre handler - * @param {Vector} pos - */ - onMouseMove(pos) { - if (this.root.camera.getIsMapOverlayActive()) { - return; - } - - // Check for direction lock - if (this.isDirectionLockActive) { - return; - } - - const metaBuilding = this.currentMetaBuilding.get(); - if ((metaBuilding || this.currentlyDeleting) && this.lastDragTile) { - const oldPos = this.lastDragTile; - let newPos = this.root.camera.screenToWorld(pos).toTileSpace(); - - // Check if camera is moving, since then we do nothing - if (this.root.camera.desiredCenter) { - this.lastDragTile = newPos; - return; - } - - // Check if anything changed - if (!oldPos.equals(newPos)) { - // Automatic Direction - if ( - metaBuilding && - metaBuilding.getRotateAutomaticallyWhilePlacing(this.currentVariant.get()) && - !this.root.keyMapper.getBinding( - KEYMAPPINGS.placementModifiers.placementDisableAutoOrientation - ).pressed - ) { - const delta = newPos.sub(oldPos); - const angleDeg = Math.degrees(delta.angle()); - this.currentBaseRotation = (Math.round(angleDeg / 90) * 90 + 360) % 360; - - // Holding alt inverts the placement - if (this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeInverse).pressed) { - this.currentBaseRotation = (180 + this.currentBaseRotation) % 360; - } - } - - // bresenham - let x0 = oldPos.x; - let y0 = oldPos.y; - let x1 = newPos.x; - let y1 = newPos.y; - - var dx = Math.abs(x1 - x0); - var dy = Math.abs(y1 - y0); - var sx = x0 < x1 ? 1 : -1; - var sy = y0 < y1 ? 1 : -1; - var err = dx - dy; - - let anythingPlaced = false; - let anythingDeleted = false; - - while (this.currentlyDeleting || this.currentMetaBuilding.get()) { - if (this.currentlyDeleting) { - // Deletion - const contents = this.root.map.getLayerContentXY(x0, y0, this.root.currentLayer); - if (contents && !contents.queuedForDestroy && !contents.destroyed) { - if (this.root.logic.tryDeleteBuilding(contents)) { - anythingDeleted = true; - } - } - } else { - // Placement - if (this.tryPlaceCurrentBuildingAt(new Vector(x0, y0))) { - anythingPlaced = true; - } - } - - if (x0 === x1 && y0 === y1) break; - var e2 = 2 * err; - if (e2 > -dy) { - err -= dy; - x0 += sx; - } - if (e2 < dx) { - err += dx; - y0 += sy; - } - } - - if (anythingPlaced) { - this.root.soundProxy.playUi(metaBuilding.getPlacementSound()); - } - if (anythingDeleted) { - this.root.soundProxy.playUi(SOUNDS.destroyBuilding); - } - } - - this.lastDragTile = newPos; - return STOP_PROPAGATION; - } - } - - /** - * Mouse up handler - */ - onMouseUp() { - if (this.root.camera.getIsMapOverlayActive()) { - return; - } - - // Check for direction lock - if (this.lastDragTile && this.currentlyDragging && this.isDirectionLockActive) { - this.executeDirectionLockedPlacement(); - } - - this.abortDragging(); - } -} +import { globalConfig } from "../../../core/config"; +import { gMetaBuildingRegistry } from "../../../core/global_registries"; +import { Signal, STOP_PROPAGATION } from "../../../core/signal"; +import { TrackedState } from "../../../core/tracked_state"; +import { Vector } from "../../../core/vector"; +import { enumMouseButton } from "../../camera"; +import { StaticMapEntityComponent } from "../../components/static_map_entity"; +import { Entity } from "../../entity"; +import { KEYMAPPINGS } from "../../key_action_mapper"; +import { defaultBuildingVariant, MetaBuilding } from "../../meta_building"; +import { BaseHUDPart } from "../base_hud_part"; +import { SOUNDS } from "../../../platform/sound"; +import { MetaMinerBuilding, enumMinerVariants } from "../../buildings/miner"; +import { enumHubGoalRewards } from "../../tutorial_goals"; +import { getBuildingDataFromCode, getCodeFromBuildingData } from "../../building_codes"; +import { MetaHubBuilding } from "../../buildings/hub"; + +/** + * Contains all logic for the building placer - this doesn't include the rendering + * of info boxes or drawing. + */ +export class HUDBuildingPlacerLogic extends BaseHUDPart { + /** + * Initializes the logic + * @see BaseHUDPart.initialize + */ + initialize() { + /** + * We use a fake entity to get information about how a building will look + * once placed + * @type {Entity} + */ + this.fakeEntity = null; + + // Signals + this.signals = { + variantChanged: new Signal(), + draggingStarted: new Signal(), + }; + + /** + * The current building + * @type {TypedTrackedState} + */ + this.currentMetaBuilding = new TrackedState(this.onSelectedMetaBuildingChanged, this); + + /** + * The current rotation + * @type {number} + */ + this.currentBaseRotationGeneral = 0; + + /** + * The current rotation preference for each building. + * @type{Object.} + */ + this.preferredBaseRotations = {}; + + /** + * Whether we are currently dragging + * @type {boolean} + */ + this.currentlyDragging = false; + + /** + * Current building variant + * @type {TypedTrackedState} + */ + this.currentVariant = new TrackedState(() => this.signals.variantChanged.dispatch()); + + /** + * Whether we are currently drag-deleting + * @type {boolean} + */ + this.currentlyDeleting = false; + + /** + * Stores which variants for each building we prefer, this is based on what + * the user last selected + * @type {Object.} + */ + this.preferredVariants = {}; + + /** + * The tile we last dragged from + * @type {Vector} + */ + this.lastDragTile = null; + + /** + * The side for direction lock + * @type {number} (0|1) + */ + this.currentDirectionLockSide = 0; + + /** + * Whether the side for direction lock has not yet been determined. + * @type {boolean} + */ + this.currentDirectionLockSideIndeterminate = true; + + this.initializeBindings(); + } + + /** + * Initializes all bindings + */ + initializeBindings() { + // KEYBINDINGS + const keyActionMapper = this.root.keyMapper; + keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.tryRotate, this); + keyActionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildingVariants).add(this.cycleVariants, this); + keyActionMapper + .getBinding(KEYMAPPINGS.placement.switchDirectionLockSide) + .add(this.switchDirectionLockSide, this); + keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this); + keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.startPipette, this); + this.root.gameState.inputReciever.keyup.add(this.checkForDirectionLockSwitch, this); + + // BINDINGS TO GAME EVENTS + this.root.hud.signals.buildingsSelectedForCopy.add(this.abortPlacement, this); + this.root.hud.signals.pasteBlueprintRequested.add(this.abortPlacement, this); + this.root.signals.storyGoalCompleted.add(() => this.signals.variantChanged.dispatch()); + this.root.signals.upgradePurchased.add(() => this.signals.variantChanged.dispatch()); + this.root.signals.editModeChanged.add(this.onEditModeChanged, this); + + // MOUSE BINDINGS + this.root.camera.downPreHandler.add(this.onMouseDown, this); + this.root.camera.movePreHandler.add(this.onMouseMove, this); + this.root.camera.upPostHandler.add(this.onMouseUp, this); + } + + /** + * Called when the edit mode got changed + * @param {Layer} layer + */ + onEditModeChanged(layer) { + const metaBuilding = this.currentMetaBuilding.get(); + if (metaBuilding) { + if (metaBuilding.getLayer() !== layer) { + // This layer doesn't fit the edit mode anymore + this.currentMetaBuilding.set(null); + } + } + } + + /** + * Returns the current base rotation for the current meta-building. + * @returns {number} + */ + get currentBaseRotation() { + if (!this.root.app.settings.getAllSettings().rotationByBuilding) { + return this.currentBaseRotationGeneral; + } + const metaBuilding = this.currentMetaBuilding.get(); + if (metaBuilding && this.preferredBaseRotations.hasOwnProperty(metaBuilding.getId())) { + return this.preferredBaseRotations[metaBuilding.getId()]; + } else { + return this.currentBaseRotationGeneral; + } + } + + /** + * Sets the base rotation for the current meta-building. + * @param {number} rotation The new rotation/angle. + */ + set currentBaseRotation(rotation) { + if (!this.root.app.settings.getAllSettings().rotationByBuilding) { + this.currentBaseRotationGeneral = rotation; + } else { + const metaBuilding = this.currentMetaBuilding.get(); + if (metaBuilding) { + this.preferredBaseRotations[metaBuilding.getId()] = rotation; + } else { + this.currentBaseRotationGeneral = rotation; + } + } + } + + /** + * Returns if the direction lock is currently active + * @returns {boolean} + */ + get isDirectionLockActive() { + const metaBuilding = this.currentMetaBuilding.get(); + return ( + metaBuilding && + metaBuilding.getHasDirectionLockAvailable() && + this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.lockBeltDirection).pressed + ); + } + + /** + * Returns the current direction lock corner, that is, the corner between + * mouse and original start point + * @returns {Vector|null} + */ + get currentDirectionLockCorner() { + const mousePosition = this.root.app.mousePosition; + if (!mousePosition) { + // Not on screen + return null; + } + + if (!this.lastDragTile) { + // Haven't dragged yet + return null; + } + + // Figure which points the line visits + const worldPos = this.root.camera.screenToWorld(mousePosition); + const mouseTile = worldPos.toTileSpace(); + + // Figure initial direction + const dx = Math.abs(this.lastDragTile.x - mouseTile.x); + const dy = Math.abs(this.lastDragTile.y - mouseTile.y); + if (dx === 0 && dy === 0) { + // Back at the start. Try a new direction. + this.currentDirectionLockSideIndeterminate = true; + } else if (this.currentDirectionLockSideIndeterminate) { + this.currentDirectionLockSideIndeterminate = false; + this.currentDirectionLockSide = dx <= dy ? 0 : 1; + } + + if (this.currentDirectionLockSide === 0) { + return new Vector(this.lastDragTile.x, mouseTile.y); + } else { + return new Vector(mouseTile.x, this.lastDragTile.y); + } + } + + /** + * Aborts the placement + */ + abortPlacement() { + if (this.currentMetaBuilding.get()) { + this.currentMetaBuilding.set(null); + return STOP_PROPAGATION; + } + } + + /** + * Aborts any dragging + */ + abortDragging() { + this.currentlyDragging = true; + this.currentlyDeleting = false; + this.initialPlacementVector = null; + this.lastDragTile = null; + } + + /** + * @see BaseHUDPart.update + */ + update() { + // Always update since the camera might have moved + const mousePos = this.root.app.mousePosition; + if (mousePos) { + this.onMouseMove(mousePos); + } + + // Make sure we have nothing selected while in overview mode + if (this.root.camera.getIsMapOverlayActive()) { + if (this.currentMetaBuilding.get()) { + this.currentMetaBuilding.set(null); + } + } + } + + /** + * Tries to rotate the current building + */ + tryRotate() { + const selectedBuilding = this.currentMetaBuilding.get(); + if (selectedBuilding) { + if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).pressed) { + this.currentBaseRotation = (this.currentBaseRotation + 270) % 360; + } else { + this.currentBaseRotation = (this.currentBaseRotation + 90) % 360; + } + const staticComp = this.fakeEntity.components.StaticMapEntity; + staticComp.rotation = this.currentBaseRotation; + } + } + /** + * Tries to delete the building under the mouse + */ + deleteBelowCursor() { + const mousePosition = this.root.app.mousePosition; + if (!mousePosition) { + // Not on screen + return false; + } + + const worldPos = this.root.camera.screenToWorld(mousePosition); + const tile = worldPos.toTileSpace(); + const contents = this.root.map.getTileContent(tile, this.root.currentLayer); + if (contents) { + if (this.root.logic.tryDeleteBuilding(contents)) { + this.root.soundProxy.playUi(SOUNDS.destroyBuilding); + return true; + } + } + return false; + } + + /** + * Starts the pipette function + */ + startPipette() { + // Disable in overview + if (this.root.camera.getIsMapOverlayActive()) { + return; + } + + const mousePosition = this.root.app.mousePosition; + if (!mousePosition) { + // Not on screen + return; + } + + const worldPos = this.root.camera.screenToWorld(mousePosition); + const tile = worldPos.toTileSpace(); + + const contents = this.root.map.getTileContent(tile, this.root.currentLayer); + if (!contents) { + const tileBelow = this.root.map.getLowerLayerContentXY(tile.x, tile.y); + + // Check if there's a shape or color item below, if so select the miner + if (tileBelow && this.root.app.settings.getAllSettings().pickMinerOnPatch) { + this.currentMetaBuilding.set(gMetaBuildingRegistry.findByClass(MetaMinerBuilding)); + + // Select chained miner if available, since thats always desired once unlocked + if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_miner_chainable)) { + this.currentVariant.set(enumMinerVariants.chainable); + } + } else { + this.currentMetaBuilding.set(null); + } + return; + } + + // Try to extract the building + const buildingCode = contents.components.StaticMapEntity.code; + const extracted = getBuildingDataFromCode(buildingCode); + + // Disable pipetting the hub + if (extracted.metaInstance.getId() === gMetaBuildingRegistry.findByClass(MetaHubBuilding).getId()) { + this.currentMetaBuilding.set(null); + return; + } + + // If the building we are picking is the same as the one we have, clear the cursor. + if ( + this.currentMetaBuilding.get() && + extracted.metaInstance.getId() === this.currentMetaBuilding.get().getId() && + extracted.variant === this.currentVariant.get() + ) { + this.currentMetaBuilding.set(null); + return; + } + + this.currentMetaBuilding.set(extracted.metaInstance); + this.currentVariant.set(extracted.variant); + this.currentBaseRotation = contents.components.StaticMapEntity.rotation; + } + + /** + * Switches the side for the direction lock manually + */ + switchDirectionLockSide() { + this.currentDirectionLockSide = 1 - this.currentDirectionLockSide; + } + + /** + * Checks if the direction lock key got released and if such, resets the placement + * @param {any} args + */ + checkForDirectionLockSwitch({ keyCode }) { + if ( + keyCode === + this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.lockBeltDirection).keyCode + ) { + this.abortDragging(); + } + } + + /** + * Tries to place the current building at the given tile + * @param {Vector} tile + */ + tryPlaceCurrentBuildingAt(tile) { + if (this.root.camera.zoomLevel < globalConfig.mapChunkOverviewMinZoom) { + // Dont allow placing in overview mode + return; + } + + const metaBuilding = this.currentMetaBuilding.get(); + const { rotation, rotationVariant } = metaBuilding.computeOptimalDirectionAndRotationVariantAtTile({ + root: this.root, + tile, + rotation: this.currentBaseRotation, + variant: this.currentVariant.get(), + layer: metaBuilding.getLayer(), + }); + + const entity = this.root.logic.tryPlaceBuilding({ + origin: tile, + rotation, + rotationVariant, + originalRotation: this.currentBaseRotation, + building: this.currentMetaBuilding.get(), + variant: this.currentVariant.get(), + }); + + if (entity) { + // Succesfully placed, find which entity we actually placed + this.root.signals.entityManuallyPlaced.dispatch(entity); + + // Check if we should flip the orientation (used for tunnels) + if ( + metaBuilding.getFlipOrientationAfterPlacement() && + !this.root.keyMapper.getBinding( + KEYMAPPINGS.placementModifiers.placementDisableAutoOrientation + ).pressed + ) { + this.currentBaseRotation = (180 + this.currentBaseRotation) % 360; + } + + // Check if we should stop placement + if ( + !metaBuilding.getStayInPlacementMode() && + !this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeMultiple).pressed && + !this.root.app.settings.getAllSettings().alwaysMultiplace + ) { + // Stop placement + this.currentMetaBuilding.set(null); + } + return true; + } else { + return false; + } + } + + /** + * Cycles through the variants + */ + cycleVariants() { + const metaBuilding = this.currentMetaBuilding.get(); + if (!metaBuilding) { + this.currentVariant.set(defaultBuildingVariant); + } else { + const availableVariants = metaBuilding.getAvailableVariants(this.root); + const index = availableVariants.indexOf(this.currentVariant.get()); + assert( + index >= 0, + "Current variant was invalid: " + this.currentVariant.get() + " out of " + availableVariants + ); + const newIndex = (index + 1) % availableVariants.length; + const newVariant = availableVariants[newIndex]; + this.setVariant(newVariant); + } + } + + /** + * Sets the current variant to the given variant + * @param {string} variant + */ + setVariant(variant) { + const metaBuilding = this.currentMetaBuilding.get(); + this.currentVariant.set(variant); + + this.preferredVariants[metaBuilding.getId()] = variant; + } + + /** + * Performs the direction locked placement between two points after + * releasing the mouse + */ + executeDirectionLockedPlacement() { + const metaBuilding = this.currentMetaBuilding.get(); + if (!metaBuilding) { + // No active building + return; + } + + // Get path to place + const path = this.computeDirectionLockPath(); + + // Store if we placed anything + let anythingPlaced = false; + + // Perform this in bulk to avoid recalculations + this.root.logic.performBulkOperation(() => { + for (let i = 0; i < path.length; ++i) { + const { rotation, tile } = path[i]; + this.currentBaseRotation = rotation; + if (this.tryPlaceCurrentBuildingAt(tile)) { + anythingPlaced = true; + } + } + }); + + if (anythingPlaced) { + this.root.soundProxy.playUi(metaBuilding.getPlacementSound()); + } + } + + /** + * Finds the path which the current direction lock will use + * @returns {Array<{ tile: Vector, rotation: number }>} + */ + computeDirectionLockPath() { + const mousePosition = this.root.app.mousePosition; + if (!mousePosition) { + // Not on screen + return []; + } + + let result = []; + + // Figure which points the line visits + const worldPos = this.root.camera.screenToWorld(mousePosition); + let endTile = worldPos.toTileSpace(); + let startTile = this.lastDragTile; + + // if the alt key is pressed, reverse belt planner direction by switching start and end tile + if (this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeInverse).pressed) { + let tmp = startTile; + startTile = endTile; + endTile = tmp; + } + + // Place from start to corner + const pathToCorner = this.currentDirectionLockCorner.sub(startTile); + const deltaToCorner = pathToCorner.normalize().round(); + const lengthToCorner = Math.round(pathToCorner.length()); + let currentPos = startTile.copy(); + + let rotation = (Math.round(Math.degrees(deltaToCorner.angle()) / 90) * 90 + 360) % 360; + + if (lengthToCorner > 0) { + for (let i = 0; i < lengthToCorner; ++i) { + result.push({ + tile: currentPos.copy(), + rotation, + }); + currentPos.addInplace(deltaToCorner); + } + } + + // Place from corner to end + const pathFromCorner = endTile.sub(this.currentDirectionLockCorner); + const deltaFromCorner = pathFromCorner.normalize().round(); + const lengthFromCorner = Math.round(pathFromCorner.length()); + + if (lengthFromCorner > 0) { + rotation = (Math.round(Math.degrees(deltaFromCorner.angle()) / 90) * 90 + 360) % 360; + for (let i = 0; i < lengthFromCorner + 1; ++i) { + result.push({ + tile: currentPos.copy(), + rotation, + }); + currentPos.addInplace(deltaFromCorner); + } + } else { + // Finish last one + result.push({ + tile: currentPos.copy(), + rotation, + }); + } + return result; + } + + /** + * Selects a given building + * @param {MetaBuilding} metaBuilding + */ + startSelection(metaBuilding) { + this.currentMetaBuilding.set(metaBuilding); + } + + /** + * Called when the selected buildings changed + * @param {MetaBuilding} metaBuilding + */ + onSelectedMetaBuildingChanged(metaBuilding) { + this.abortDragging(); + this.root.hud.signals.selectedPlacementBuildingChanged.dispatch(metaBuilding); + if (metaBuilding) { + const variant = this.preferredVariants[metaBuilding.getId()] || defaultBuildingVariant; + this.currentVariant.set(variant); + + this.fakeEntity = new Entity(null); + metaBuilding.setupEntityComponents(this.fakeEntity, null); + + this.fakeEntity.addComponent( + new StaticMapEntityComponent({ + origin: new Vector(0, 0), + rotation: 0, + tileSize: metaBuilding.getDimensions(this.currentVariant.get()).copy(), + code: getCodeFromBuildingData(metaBuilding, variant, 0), + }) + ); + metaBuilding.updateVariants(this.fakeEntity, 0, this.currentVariant.get()); + } else { + this.fakeEntity = null; + } + + // Since it depends on both, rerender twice + this.signals.variantChanged.dispatch(); + } + + /** + * mouse down pre handler + * @param {Vector} pos + * @param {enumMouseButton} button + */ + onMouseDown(pos, button) { + if (this.root.camera.getIsMapOverlayActive()) { + // We do not allow dragging if the overlay is active + return; + } + + const metaBuilding = this.currentMetaBuilding.get(); + + // Placement + if (button === enumMouseButton.left && metaBuilding) { + this.currentlyDragging = true; + this.currentlyDeleting = false; + this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace(); + + // Place initial building, but only if direction lock is not active + if (!this.isDirectionLockActive) { + if (this.tryPlaceCurrentBuildingAt(this.lastDragTile)) { + this.root.soundProxy.playUi(metaBuilding.getPlacementSound()); + } + } + return STOP_PROPAGATION; + } + + // Deletion + if ( + button === enumMouseButton.right && + (!metaBuilding || !this.root.app.settings.getAllSettings().clearCursorOnDeleteWhilePlacing) + ) { + this.currentlyDragging = true; + this.currentlyDeleting = true; + this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace(); + if (this.deleteBelowCursor()) { + return STOP_PROPAGATION; + } + } + + // Cancel placement + if (button === enumMouseButton.right && metaBuilding) { + this.currentMetaBuilding.set(null); + } + } + + /** + * mouse move pre handler + * @param {Vector} pos + */ + onMouseMove(pos) { + if (this.root.camera.getIsMapOverlayActive()) { + return; + } + + // Check for direction lock + if (this.isDirectionLockActive) { + return; + } + + const metaBuilding = this.currentMetaBuilding.get(); + if ((metaBuilding || this.currentlyDeleting) && this.lastDragTile) { + const oldPos = this.lastDragTile; + let newPos = this.root.camera.screenToWorld(pos).toTileSpace(); + + // Check if camera is moving, since then we do nothing + if (this.root.camera.desiredCenter) { + this.lastDragTile = newPos; + return; + } + + // Check if anything changed + if (!oldPos.equals(newPos)) { + // Automatic Direction + if ( + metaBuilding && + metaBuilding.getRotateAutomaticallyWhilePlacing(this.currentVariant.get()) && + !this.root.keyMapper.getBinding( + KEYMAPPINGS.placementModifiers.placementDisableAutoOrientation + ).pressed + ) { + const delta = newPos.sub(oldPos); + const angleDeg = Math.degrees(delta.angle()); + this.currentBaseRotation = (Math.round(angleDeg / 90) * 90 + 360) % 360; + + // Holding alt inverts the placement + if (this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeInverse).pressed) { + this.currentBaseRotation = (180 + this.currentBaseRotation) % 360; + } + } + + // bresenham + let x0 = oldPos.x; + let y0 = oldPos.y; + let x1 = newPos.x; + let y1 = newPos.y; + + var dx = Math.abs(x1 - x0); + var dy = Math.abs(y1 - y0); + var sx = x0 < x1 ? 1 : -1; + var sy = y0 < y1 ? 1 : -1; + var err = dx - dy; + + let anythingPlaced = false; + let anythingDeleted = false; + + while (this.currentlyDeleting || this.currentMetaBuilding.get()) { + if (this.currentlyDeleting) { + // Deletion + const contents = this.root.map.getLayerContentXY(x0, y0, this.root.currentLayer); + if (contents && !contents.queuedForDestroy && !contents.destroyed) { + if (this.root.logic.tryDeleteBuilding(contents)) { + anythingDeleted = true; + } + } + } else { + // Placement + if (this.tryPlaceCurrentBuildingAt(new Vector(x0, y0))) { + anythingPlaced = true; + } + } + + if (x0 === x1 && y0 === y1) break; + var e2 = 2 * err; + if (e2 > -dy) { + err -= dy; + x0 += sx; + } + if (e2 < dx) { + err += dx; + y0 += sy; + } + } + + if (anythingPlaced) { + this.root.soundProxy.playUi(metaBuilding.getPlacementSound()); + } + if (anythingDeleted) { + this.root.soundProxy.playUi(SOUNDS.destroyBuilding); + } + } + + this.lastDragTile = newPos; + return STOP_PROPAGATION; + } + } + + /** + * Mouse up handler + */ + onMouseUp() { + if (this.root.camera.getIsMapOverlayActive()) { + return; + } + + // Check for direction lock + if (this.lastDragTile && this.currentlyDragging && this.isDirectionLockActive) { + this.executeDirectionLockedPlacement(); + } + + this.abortDragging(); + } +} diff --git a/src/js/game/hud/parts/buildings_toolbar.js b/src/js/game/hud/parts/buildings_toolbar.js index c46a5c98..f8953204 100644 --- a/src/js/game/hud/parts/buildings_toolbar.js +++ b/src/js/game/hud/parts/buildings_toolbar.js @@ -1,41 +1,43 @@ -import { MetaBeltBaseBuilding } from "../../buildings/belt_base"; -import { MetaCutterBuilding } from "../../buildings/cutter"; -import { MetaEnergyGenerator } from "../../buildings/energy_generator"; -import { MetaMinerBuilding } from "../../buildings/miner"; -import { MetaMixerBuilding } from "../../buildings/mixer"; -import { MetaPainterBuilding } from "../../buildings/painter"; -import { MetaRotaterBuilding } from "../../buildings/rotater"; -import { MetaSplitterBuilding } from "../../buildings/splitter"; -import { MetaStackerBuilding } from "../../buildings/stacker"; -import { MetaTrashBuilding } from "../../buildings/trash"; -import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt"; -import { enumLayer } from "../../root"; -import { HUDBaseToolbar } from "./base_toolbar"; -import { MetaAdvancedProcessorBuilding } from "../../buildings/advanced_processor"; - -const supportedBuildings = [ - MetaBeltBaseBuilding, - MetaSplitterBuilding, - MetaUndergroundBeltBuilding, - MetaMinerBuilding, - MetaCutterBuilding, - MetaRotaterBuilding, - MetaStackerBuilding, - MetaMixerBuilding, - MetaPainterBuilding, - MetaTrashBuilding, - - MetaEnergyGenerator, - MetaAdvancedProcessorBuilding, -]; - -export class HUDBuildingsToolbar extends HUDBaseToolbar { - constructor(root) { - super(root, { - supportedBuildings, - visibilityCondition: () => - !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === enumLayer.regular, - htmlElementId: "ingame_HUD_buildings_toolbar", - }); - } -} +import { MetaBeltBaseBuilding } from "../../buildings/belt_base"; +import { MetaCutterBuilding } from "../../buildings/cutter"; +import { MetaMinerBuilding } from "../../buildings/miner"; +import { MetaMixerBuilding } from "../../buildings/mixer"; +import { MetaPainterBuilding } from "../../buildings/painter"; +import { MetaRotaterBuilding } from "../../buildings/rotater"; +import { MetaSplitterBuilding } from "../../buildings/splitter"; +import { MetaStackerBuilding } from "../../buildings/stacker"; +import { MetaTrashBuilding } from "../../buildings/trash"; +import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt"; +import { HUDBaseToolbar } from "./base_toolbar"; +import { MetaLeverBuilding } from "../../buildings/lever"; +import { MetaFilterBuilding } from "../../buildings/filter"; +import { MetaDisplayBuilding } from "../../buildings/display"; +import { MetaReaderBuilding } from "../../buildings/reader"; + +const supportedBuildings = [ + MetaBeltBaseBuilding, + MetaSplitterBuilding, + MetaUndergroundBeltBuilding, + MetaMinerBuilding, + MetaCutterBuilding, + MetaRotaterBuilding, + MetaStackerBuilding, + MetaMixerBuilding, + MetaPainterBuilding, + MetaTrashBuilding, + MetaLeverBuilding, + MetaFilterBuilding, + MetaDisplayBuilding, + MetaReaderBuilding, +]; + +export class HUDBuildingsToolbar extends HUDBaseToolbar { + constructor(root) { + super(root, { + supportedBuildings, + visibilityCondition: () => + !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "regular", + htmlElementId: "ingame_HUD_buildings_toolbar", + }); + } +} diff --git a/src/js/game/hud/parts/color_blind_helper.js b/src/js/game/hud/parts/color_blind_helper.js index c7dd6288..e5572228 100644 --- a/src/js/game/hud/parts/color_blind_helper.js +++ b/src/js/game/hud/parts/color_blind_helper.js @@ -7,8 +7,6 @@ import { DrawParameters } from "../../../core/draw_parameters"; import { THEME } from "../../theme"; import { globalConfig } from "../../../core/config"; import { T } from "../../../translations"; -import { enumItemType } from "../../base_item"; -import { enumLayer } from "../../root"; export class HUDColorBlindHelper extends BaseHUDPart { createElements(parent) { @@ -41,7 +39,7 @@ export class HUDColorBlindHelper extends BaseHUDPart { return null; } - if (this.root.currentLayer !== enumLayer.regular) { + if (this.root.currentLayer !== "regular") { // Not in regular mode return null; } @@ -56,7 +54,7 @@ export class HUDColorBlindHelper extends BaseHUDPart { // Check if the belt has a color item if (beltComp) { const item = beltComp.assignedPath.findItemAtTile(tile); - if (item && item.getItemType() === enumItemType.color) { + if (item && item.getItemType() === "color") { return /** @type {ColorItem} */ (item).color; } } @@ -66,10 +64,7 @@ export class HUDColorBlindHelper extends BaseHUDPart { if (ejectorComp) { for (let i = 0; i < ejectorComp.slots.length; ++i) { const slot = ejectorComp.slots[i]; - if (slot.layer !== this.root.currentLayer) { - continue; - } - if (slot.item && slot.item.getItemType() === enumItemType.color) { + if (slot.item && slot.item.getItemType() === "color") { return /** @type {ColorItem} */ (slot.item).color; } } @@ -77,7 +72,7 @@ export class HUDColorBlindHelper extends BaseHUDPart { } else { // We hovered a lower layer, show the color there const lowerLayer = this.root.map.getLowerLayerContentXY(tile.x, tile.y); - if (lowerLayer && lowerLayer.getItemType() === enumItemType.color) { + if (lowerLayer && lowerLayer.getItemType() === "color") { return /** @type {ColorItem} */ (lowerLayer).color; } } diff --git a/src/js/game/hud/parts/debug_changes.js b/src/js/game/hud/parts/debug_changes.js index 1502afa2..88de84fe 100644 --- a/src/js/game/hud/parts/debug_changes.js +++ b/src/js/game/hud/parts/debug_changes.js @@ -57,7 +57,7 @@ export class HUDChangesDebugger extends BaseHUDPart { for (let i = 0; i < this.changes.length; ++i) { const change = this.changes[i]; parameters.context.fillStyle = change.fillColor; - parameters.context.globalAlpha = 0.5; + parameters.context.globalAlpha = 0.2; parameters.context.fillRect( change.area.x * globalConfig.tileSize, change.area.y * globalConfig.tileSize, diff --git a/src/js/game/hud/parts/debug_info.js b/src/js/game/hud/parts/debug_info.js index cdd00540..100a19ef 100644 --- a/src/js/game/hud/parts/debug_info.js +++ b/src/js/game/hud/parts/debug_info.js @@ -88,8 +88,8 @@ export class HUDDebugInfo extends BaseHUDPart { const mouseTile = this.root.camera.screenToWorld(mousePos).toTileSpace(); const cameraTile = this.root.camera.center.toTileSpace(); - this.trackedMousePosition.set(`Pos: ${mouseTile.x} / ${mouseTile.y}`); - this.trackedCameraPosition.set(`Center: ${cameraTile.x} / ${cameraTile.y}`); + this.trackedMousePosition.set(`Mouse: ${mouseTile.x} / ${mouseTile.y}`); + this.trackedCameraPosition.set(`Camera: ${cameraTile.x} / ${cameraTile.y}`); } /** diff --git a/src/js/game/hud/parts/entity_debugger.js b/src/js/game/hud/parts/entity_debugger.js index 9fe1bd7c..80f15eea 100644 --- a/src/js/game/hud/parts/entity_debugger.js +++ b/src/js/game/hud/parts/entity_debugger.js @@ -15,7 +15,9 @@ export class HUDEntityDebugger extends BaseHUDPart { ` ); + /** @type {HTMLElement} */ this.mousePosElem = this.element.querySelector(".mousePos"); + /** @type {HTMLElement} */ this.chunkPosElem = this.element.querySelector(".chunkPos"); this.entityInfoElem = this.element.querySelector(".entityInfo"); } diff --git a/src/js/game/hud/parts/game_menu.js b/src/js/game/hud/parts/game_menu.js index 64285624..59ba0232 100644 --- a/src/js/game/hud/parts/game_menu.js +++ b/src/js/game/hud/parts/game_menu.js @@ -1,189 +1,169 @@ -import { BaseHUDPart } from "../base_hud_part"; -import { makeDiv, randomInt } from "../../../core/utils"; -import { SOUNDS } from "../../../platform/sound"; -import { enumNotificationType } from "./notifications"; -import { T } from "../../../translations"; -import { KEYMAPPINGS } from "../../key_action_mapper"; -import { IS_DEMO } from "../../../core/config"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; - -export class HUDGameMenu extends BaseHUDPart { - createElements(parent) { - this.element = makeDiv(parent, "ingame_HUD_GameMenu"); - - const buttons = [ - { - id: "shop", - label: "Upgrades", - handler: () => this.root.hud.parts.shop.show(), - keybinding: KEYMAPPINGS.ingame.menuOpenShop, - badge: () => this.root.hubGoals.getAvailableUpgradeCount(), - notification: /** @type {[string, enumNotificationType]} */ ([ - T.ingame.notifications.newUpgrade, - enumNotificationType.upgrade, - ]), - visible: () => - !this.root.app.settings.getAllSettings().offerHints || this.root.hubGoals.level >= 3, - }, - { - id: "stats", - label: "Stats", - handler: () => this.root.hud.parts.statistics.show(), - keybinding: KEYMAPPINGS.ingame.menuOpenStats, - visible: () => - !this.root.app.settings.getAllSettings().offerHints || this.root.hubGoals.level >= 3, - }, - ]; - - /** @type {Array<{ - * badge: function, - * button: HTMLElement, - * badgeElement: HTMLElement, - * lastRenderAmount: number, - * condition?: function, - * notification: [string, enumNotificationType] - * }>} */ - this.badgesToUpdate = []; - - /** @type {Array<{ - * button: HTMLElement, - * condition: function, - * domAttach: DynamicDomAttach - * }>} */ - this.visibilityToUpdate = []; - - this.buttonsElement = makeDiv(this.element, null, ["buttonContainer"]); - - buttons.forEach(({ id, label, handler, keybinding, badge, notification, visible }) => { - const button = document.createElement("button"); - button.setAttribute("data-button-id", id); - this.buttonsElement.appendChild(button); - this.trackClicks(button, handler); - - if (keybinding) { - const binding = this.root.keyMapper.getBinding(keybinding); - binding.add(handler); - binding.appendLabelToElement(button); - } - - if (visible) { - this.visibilityToUpdate.push({ - button, - condition: visible, - domAttach: new DynamicDomAttach(this.root, button), - }); - } - - if (badge) { - const badgeElement = makeDiv(button, null, ["badge"]); - this.badgesToUpdate.push({ - badge, - lastRenderAmount: 0, - button, - badgeElement, - notification, - condition: visible, - }); - } - }); - - const menuButtons = makeDiv(this.element, null, ["menuButtons"]); - - this.musicButton = makeDiv(menuButtons, null, ["button", "music"]); - this.sfxButton = makeDiv(menuButtons, null, ["button", "sfx"]); - this.saveButton = makeDiv(menuButtons, null, ["button", "save", "animEven"]); - this.settingsButton = makeDiv(menuButtons, null, ["button", "settings"]); - - this.trackClicks(this.musicButton, this.toggleMusic); - this.trackClicks(this.sfxButton, this.toggleSfx); - this.trackClicks(this.saveButton, this.startSave); - this.trackClicks(this.settingsButton, this.openSettings); - - this.musicButton.classList.toggle("muted", this.root.app.settings.getAllSettings().musicMuted); - this.sfxButton.classList.toggle("muted", this.root.app.settings.getAllSettings().soundsMuted); - } - initialize() { - this.root.signals.gameSaved.add(this.onGameSaved, this); - } - - update() { - let playSound = false; - let notifications = new Set(); - - // Update visibility of buttons - for (let i = 0; i < this.visibilityToUpdate.length; ++i) { - const { button, condition, domAttach } = this.visibilityToUpdate[i]; - domAttach.update(condition()); - } - - // Check for notifications and badges - for (let i = 0; i < this.badgesToUpdate.length; ++i) { - const { - badge, - button, - badgeElement, - lastRenderAmount, - notification, - condition, - } = this.badgesToUpdate[i]; - - if (condition && !condition()) { - // Do not show notifications for invisible buttons - continue; - } - - // Check if the amount shown differs from the one shown last frame - const amount = badge(); - if (lastRenderAmount !== amount) { - if (amount > 0) { - badgeElement.innerText = amount; - } - // Check if the badge increased, if so play a notification - if (amount > lastRenderAmount) { - playSound = true; - if (notification) { - notifications.add(notification); - } - } - - // Rerender notifications - this.badgesToUpdate[i].lastRenderAmount = amount; - button.classList.toggle("hasBadge", amount > 0); - } - } - - if (playSound) { - this.root.soundProxy.playUi(SOUNDS.badgeNotification); - } - - notifications.forEach(([notification, type]) => { - this.root.hud.signals.notification.dispatch(notification, type); - }); - } - - onGameSaved() { - this.saveButton.classList.toggle("animEven"); - this.saveButton.classList.toggle("animOdd"); - } - - startSave() { - this.root.gameState.doSave(); - } - - openSettings() { - this.root.hud.parts.settingsMenu.show(); - } - - toggleMusic() { - const newValue = !this.root.app.settings.getAllSettings().musicMuted; - this.root.app.settings.updateSetting("musicMuted", newValue); - - this.musicButton.classList.toggle("muted", newValue); - } - - toggleSfx() { - const newValue = !this.root.app.settings.getAllSettings().soundsMuted; - this.root.app.settings.updateSetting("soundsMuted", newValue); - this.sfxButton.classList.toggle("muted", newValue); - } -} +import { BaseHUDPart } from "../base_hud_part"; +import { makeDiv } from "../../../core/utils"; +import { SOUNDS } from "../../../platform/sound"; +import { enumNotificationType } from "./notifications"; +import { T } from "../../../translations"; +import { KEYMAPPINGS } from "../../key_action_mapper"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; + +export class HUDGameMenu extends BaseHUDPart { + createElements(parent) { + this.element = makeDiv(parent, "ingame_HUD_GameMenu"); + + const buttons = [ + { + id: "shop", + label: "Upgrades", + handler: () => this.root.hud.parts.shop.show(), + keybinding: KEYMAPPINGS.ingame.menuOpenShop, + badge: () => this.root.hubGoals.getAvailableUpgradeCount(), + notification: /** @type {[string, enumNotificationType]} */ ([ + T.ingame.notifications.newUpgrade, + enumNotificationType.upgrade, + ]), + visible: () => + !this.root.app.settings.getAllSettings().offerHints || this.root.hubGoals.level >= 3, + }, + { + id: "stats", + label: "Stats", + handler: () => this.root.hud.parts.statistics.show(), + keybinding: KEYMAPPINGS.ingame.menuOpenStats, + visible: () => + !this.root.app.settings.getAllSettings().offerHints || this.root.hubGoals.level >= 3, + }, + ]; + + /** @type {Array<{ + * badge: function, + * button: HTMLElement, + * badgeElement: HTMLElement, + * lastRenderAmount: number, + * condition?: function, + * notification: [string, enumNotificationType] + * }>} */ + this.badgesToUpdate = []; + + /** @type {Array<{ + * button: HTMLElement, + * condition: function, + * domAttach: DynamicDomAttach + * }>} */ + this.visibilityToUpdate = []; + + this.buttonsElement = makeDiv(this.element, null, ["buttonContainer"]); + + buttons.forEach(({ id, label, handler, keybinding, badge, notification, visible }) => { + const button = document.createElement("button"); + button.setAttribute("data-button-id", id); + this.buttonsElement.appendChild(button); + this.trackClicks(button, handler); + + if (keybinding) { + const binding = this.root.keyMapper.getBinding(keybinding); + binding.add(handler); + binding.appendLabelToElement(button); + } + + if (visible) { + this.visibilityToUpdate.push({ + button, + condition: visible, + domAttach: new DynamicDomAttach(this.root, button), + }); + } + + if (badge) { + const badgeElement = makeDiv(button, null, ["badge"]); + this.badgesToUpdate.push({ + badge, + lastRenderAmount: 0, + button, + badgeElement, + notification, + condition: visible, + }); + } + }); + + const menuButtons = makeDiv(this.element, null, ["menuButtons"]); + + this.saveButton = makeDiv(menuButtons, null, ["button", "save", "animEven"]); + this.settingsButton = makeDiv(menuButtons, null, ["button", "settings"]); + + this.trackClicks(this.saveButton, this.startSave); + this.trackClicks(this.settingsButton, this.openSettings); + } + + initialize() { + this.root.signals.gameSaved.add(this.onGameSaved, this); + } + + update() { + let playSound = false; + let notifications = new Set(); + + // Update visibility of buttons + for (let i = 0; i < this.visibilityToUpdate.length; ++i) { + const { condition, domAttach } = this.visibilityToUpdate[i]; + domAttach.update(condition()); + } + + // Check for notifications and badges + for (let i = 0; i < this.badgesToUpdate.length; ++i) { + const { + badge, + button, + badgeElement, + lastRenderAmount, + notification, + condition, + } = this.badgesToUpdate[i]; + + if (condition && !condition()) { + // Do not show notifications for invisible buttons + continue; + } + + // Check if the amount shown differs from the one shown last frame + const amount = badge(); + if (lastRenderAmount !== amount) { + if (amount > 0) { + badgeElement.innerText = amount; + } + // Check if the badge increased, if so play a notification + if (amount > lastRenderAmount) { + playSound = true; + if (notification) { + notifications.add(notification); + } + } + + // Rerender notifications + this.badgesToUpdate[i].lastRenderAmount = amount; + button.classList.toggle("hasBadge", amount > 0); + } + } + + if (playSound) { + this.root.soundProxy.playUi(SOUNDS.badgeNotification); + } + + notifications.forEach(([notification, type]) => { + this.root.hud.signals.notification.dispatch(notification, type); + }); + } + + onGameSaved() { + this.saveButton.classList.toggle("animEven"); + this.saveButton.classList.toggle("animOdd"); + } + + startSave() { + this.root.gameState.doSave(); + } + + openSettings() { + this.root.hud.parts.settingsMenu.show(); + } +} diff --git a/src/js/game/hud/parts/interactive_tutorial.js b/src/js/game/hud/parts/interactive_tutorial.js index b3d93dcd..ffebc639 100644 --- a/src/js/game/hud/parts/interactive_tutorial.js +++ b/src/js/game/hud/parts/interactive_tutorial.js @@ -1,81 +1,81 @@ -import { BaseHUDPart } from "../base_hud_part"; -import { makeDiv } from "../../../core/utils"; -import { GameRoot } from "../../root"; -import { MinerComponent } from "../../components/miner"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; -import { TrackedState } from "../../../core/tracked_state"; -import { cachebust } from "../../../core/cachebust"; -import { T } from "../../../translations"; - -const tutorialsByLevel = [ - // Level 1 - [ - // 1.1. place an extractor - { - id: "1_1_extractor", - condition: /** @param {GameRoot} root */ root => { - return root.entityMgr.getAllWithComponent(MinerComponent).length === 0; - }, - }, - // 1.2. connect to hub - { - id: "1_2_conveyor", - condition: /** @param {GameRoot} root */ root => { - return root.hubGoals.getCurrentGoalDelivered() === 0; - }, - }, - // 1.3 wait for completion - { - id: "1_3_expand", - condition: () => true, - }, - ], -]; - -export class HUDInteractiveTutorial extends BaseHUDPart { - createElements(parent) { - this.element = makeDiv( - parent, - "ingame_HUD_InteractiveTutorial", - ["animEven"], - ` - ${T.ingame.interactiveTutorial.title} - ` - ); - - this.elementDescription = makeDiv(this.element, null, ["desc"]); - this.elementGif = makeDiv(this.element, null, ["helperGif"]); - } - - initialize() { - this.domAttach = new DynamicDomAttach(this.root, this.element); - this.currentHintId = new TrackedState(this.onHintChanged, this); - } - - onHintChanged(hintId) { - this.elementDescription.innerHTML = T.ingame.interactiveTutorial.hints[hintId]; - this.elementGif.style.backgroundImage = - "url('" + cachebust("res/ui/interactive_tutorial.noinline/" + hintId + ".gif") + "')"; - this.element.classList.toggle("animEven"); - this.element.classList.toggle("animOdd"); - } - - update() { - // Compute current hint - const thisLevelHints = tutorialsByLevel[this.root.hubGoals.level - 1]; - let targetHintId = null; - - if (thisLevelHints) { - for (let i = 0; i < thisLevelHints.length; ++i) { - const hint = thisLevelHints[i]; - if (hint.condition(this.root)) { - targetHintId = hint.id; - break; - } - } - } - - this.currentHintId.set(targetHintId); - this.domAttach.update(!!targetHintId); - } -} +import { BaseHUDPart } from "../base_hud_part"; +import { makeDiv } from "../../../core/utils"; +import { GameRoot } from "../../root"; +import { MinerComponent } from "../../components/miner"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; +import { TrackedState } from "../../../core/tracked_state"; +import { cachebust } from "../../../core/cachebust"; +import { T } from "../../../translations"; + +const tutorialsByLevel = [ + // Level 1 + [ + // 1.1. place an extractor + { + id: "1_1_extractor", + condition: /** @param {GameRoot} root */ root => { + return root.entityMgr.getAllWithComponent(MinerComponent).length === 0; + }, + }, + // 1.2. connect to hub + { + id: "1_2_conveyor", + condition: /** @param {GameRoot} root */ root => { + return root.hubGoals.getCurrentGoalDelivered() === 0; + }, + }, + // 1.3 wait for completion + { + id: "1_3_expand", + condition: () => true, + }, + ], +]; + +export class HUDInteractiveTutorial extends BaseHUDPart { + createElements(parent) { + this.element = makeDiv( + parent, + "ingame_HUD_InteractiveTutorial", + ["animEven"], + ` + ${T.ingame.interactiveTutorial.title} + ` + ); + + this.elementDescription = makeDiv(this.element, null, ["desc"]); + this.elementGif = makeDiv(this.element, null, ["helperGif"]); + } + + initialize() { + this.domAttach = new DynamicDomAttach(this.root, this.element, { trackHover: true }); + this.currentHintId = new TrackedState(this.onHintChanged, this); + } + + onHintChanged(hintId) { + this.elementDescription.innerHTML = T.ingame.interactiveTutorial.hints[hintId]; + this.elementGif.style.backgroundImage = + "url('" + cachebust("res/ui/interactive_tutorial.noinline/" + hintId + ".gif") + "')"; + this.element.classList.toggle("animEven"); + this.element.classList.toggle("animOdd"); + } + + update() { + // Compute current hint + const thisLevelHints = tutorialsByLevel[this.root.hubGoals.level - 1]; + let targetHintId = null; + + if (thisLevelHints) { + for (let i = 0; i < thisLevelHints.length; ++i) { + const hint = thisLevelHints[i]; + if (hint.condition(this.root)) { + targetHintId = hint.id; + break; + } + } + } + + this.currentHintId.set(targetHintId); + this.domAttach.update(!!targetHintId); + } +} diff --git a/src/js/game/hud/parts/keybinding_overlay.js b/src/js/game/hud/parts/keybinding_overlay.js index 995fc5d9..d31ee746 100644 --- a/src/js/game/hud/parts/keybinding_overlay.js +++ b/src/js/game/hud/parts/keybinding_overlay.js @@ -1,323 +1,330 @@ -import { makeDiv } from "../../../core/utils"; -import { T } from "../../../translations"; -import { - getStringForKeyCode, - KEYCODE_LMB, - KEYCODE_MMB, - KEYCODE_RMB, - KEYMAPPINGS, -} from "../../key_action_mapper"; -import { BaseHUDPart } from "../base_hud_part"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; - -const DIVIDER_TOKEN = "/"; -const ADDER_TOKEN = "+"; - -/** - * @typedef {{ keyCode: number }} KeyCode - */ - -/** - * @typedef {{ - * condition: () => boolean, - * keys: Array, - * label: string, - * cachedElement?: HTMLElement, - * cachedVisibility?: boolean - * }} KeyBinding - */ - -export class HUDKeybindingOverlay extends BaseHUDPart { - initialize() {} - - /** - * HELPER / Returns if there is a building selected for placement - * @returns {boolean} - */ - get buildingPlacementActive() { - const placer = this.root.hud.parts.buildingPlacer; - return !this.mapOverviewActive && placer && !!placer.currentMetaBuilding.get(); - } - - /** - * HELPER / Returns if there is a building selected for placement and - * it supports the belt planner - * @returns {boolean} - */ - get buildingPlacementSupportsBeltPlanner() { - const placer = this.root.hud.parts.buildingPlacer; - return ( - !this.mapOverviewActive && - placer && - placer.currentMetaBuilding.get() && - placer.currentMetaBuilding.get().getHasDirectionLockAvailable() - ); - } - - /** - * HELPER / Returns if there is a building selected for placement and - * it has multiplace enabled by default - * @returns {boolean} - */ - get buildingPlacementStaysInPlacement() { - const placer = this.root.hud.parts.buildingPlacer; - return ( - !this.mapOverviewActive && - placer && - placer.currentMetaBuilding.get() && - placer.currentMetaBuilding.get().getStayInPlacementMode() - ); - } - - /** - * HELPER / Returns if there is a blueprint selected for placement - * @returns {boolean} - */ - get blueprintPlacementActive() { - const placer = this.root.hud.parts.blueprintPlacer; - return placer && !!placer.currentBlueprint.get(); - } - - /** - * HELPER / Returns if the belt planner is currently active - * @returns {boolean} - */ - get beltPlannerActive() { - const placer = this.root.hud.parts.buildingPlacer; - return !this.mapOverviewActive && placer && placer.isDirectionLockActive; - } - - /** - * HELPER / Returns if there is a last blueprint available - * @returns {boolean} - */ - get lastBlueprintAvailable() { - const placer = this.root.hud.parts.blueprintPlacer; - return placer && !!placer.lastBlueprintUsed; - } - - /** - * HELPER / Returns if there is anything selected on the map - * @returns {boolean} - */ - get anythingSelectedOnMap() { - const selector = this.root.hud.parts.massSelector; - return selector && selector.selectedUids.size > 0; - } - - /** - * HELPER / Returns if there is a building or blueprint selected for placement - * @returns {boolean} - */ - get anyPlacementActive() { - return this.buildingPlacementActive || this.blueprintPlacementActive; - } - - /** - * HELPER / Returns if the map overview is active - * @returns {boolean} - */ - get mapOverviewActive() { - return this.root.camera.getIsMapOverlayActive(); - } - - /** - * Initializes the element - * @param {HTMLElement} parent - */ - createElements(parent) { - const mapper = this.root.keyMapper; - const k = KEYMAPPINGS; - - /** @type {Array} */ - this.keybindings = [ - { - // Move map - Including mouse - label: T.ingame.keybindingsOverlay.moveMap, - keys: [ - KEYCODE_LMB, - DIVIDER_TOKEN, - k.navigation.mapMoveUp, - k.navigation.mapMoveLeft, - k.navigation.mapMoveDown, - k.navigation.mapMoveRight, - ], - condition: () => !this.anyPlacementActive, - }, - - { - // Move map - No mouse - label: T.ingame.keybindingsOverlay.moveMap, - keys: [ - k.navigation.mapMoveUp, - k.navigation.mapMoveLeft, - k.navigation.mapMoveDown, - k.navigation.mapMoveRight, - ], - condition: () => this.anyPlacementActive, - }, - - { - // [OVERVIEW] Create marker with right click - label: T.ingame.keybindingsOverlay.createMarker, - keys: [KEYCODE_RMB], - condition: () => this.mapOverviewActive && !this.blueprintPlacementActive, - }, - - { - // Pipette - label: T.ingame.keybindingsOverlay.pipette, - keys: [k.placement.pipette], - condition: () => !this.mapOverviewActive && !this.blueprintPlacementActive, - }, - - { - // Cancel placement - label: T.ingame.keybindingsOverlay.stopPlacement, - keys: [KEYCODE_RMB], - condition: () => this.anyPlacementActive, - }, - - { - // Delete with right click - label: T.ingame.keybindingsOverlay.delete, - keys: [KEYCODE_RMB], - condition: () => - !this.anyPlacementActive && !this.mapOverviewActive && !this.anythingSelectedOnMap, - }, - - { - // Area select - label: T.ingame.keybindingsOverlay.selectBuildings, - keys: [k.massSelect.massSelectStart, ADDER_TOKEN, KEYCODE_LMB], - condition: () => !this.anyPlacementActive && !this.anythingSelectedOnMap, - }, - - { - // Place building - label: T.ingame.keybindingsOverlay.placeBuilding, - keys: [KEYCODE_LMB], - condition: () => this.anyPlacementActive, - }, - - { - // Rotate - label: T.ingame.keybindingsOverlay.rotateBuilding, - keys: [k.placement.rotateWhilePlacing], - condition: () => this.anyPlacementActive && !this.beltPlannerActive, - }, - - { - // [BELT PLANNER] Flip Side - label: T.ingame.keybindingsOverlay.plannerSwitchSide, - keys: [k.placement.switchDirectionLockSide], - condition: () => this.beltPlannerActive, - }, - - { - // Place last blueprint - label: T.ingame.keybindingsOverlay.pasteLastBlueprint, - keys: [k.massSelect.pasteLastBlueprint], - condition: () => !this.blueprintPlacementActive && this.lastBlueprintAvailable, - }, - - { - // Belt planner - label: T.ingame.keybindingsOverlay.lockBeltDirection, - keys: [k.placementModifiers.lockBeltDirection], - condition: () => this.buildingPlacementSupportsBeltPlanner && !this.beltPlannerActive, - }, - - { - // [SELECTION] Destroy - label: T.ingame.keybindingsOverlay.delete, - keys: [k.massSelect.confirmMassDelete], - condition: () => this.anythingSelectedOnMap, - }, - - { - // [SELECTION] Cancel - label: T.ingame.keybindingsOverlay.clearSelection, - keys: [k.general.back], - condition: () => this.anythingSelectedOnMap, - }, - { - // [SELECTION] Cut - label: T.ingame.keybindingsOverlay.cutSelection, - keys: [k.massSelect.massSelectCut], - condition: () => this.anythingSelectedOnMap, - }, - - { - // [SELECTION] Copy - label: T.ingame.keybindingsOverlay.copySelection, - keys: [k.massSelect.massSelectCopy], - condition: () => this.anythingSelectedOnMap, - }, - - { - // Switch layers - label: T.ingame.keybindingsOverlay.switchLayers, - keys: [k.ingame.switchLayers], - condition: () => true, - }, - ]; - - if (!this.root.app.settings.getAllSettings().alwaysMultiplace) { - this.keybindings.push({ - // Multiplace - label: T.ingame.keybindingsOverlay.placeMultiple, - keys: [k.placementModifiers.placeMultiple], - condition: () => this.anyPlacementActive && !this.buildingPlacementStaysInPlacement, - }); - } - - this.element = makeDiv(parent, "ingame_HUD_KeybindingOverlay", []); - - for (let i = 0; i < this.keybindings.length; ++i) { - let html = ""; - const handle = this.keybindings[i]; - - for (let k = 0; k < handle.keys.length; ++k) { - const key = handle.keys[k]; - - switch (key) { - case KEYCODE_LMB: - html += ``; - break; - case KEYCODE_RMB: - html += ``; - break; - case KEYCODE_MMB: - html += ``; - break; - case DIVIDER_TOKEN: - html += ``; - break; - case ADDER_TOKEN: - html += `+`; - break; - default: - html += `${getStringForKeyCode( - mapper.getBinding(/** @type {KeyCode} */ (key)).keyCode - )}`; - } - } - html += ``; - - handle.cachedElement = makeDiv(this.element, null, ["binding"], html); - handle.cachedVisibility = false; - } - } - - update() { - for (let i = 0; i < this.keybindings.length; ++i) { - const handle = this.keybindings[i]; - const visibility = handle.condition(); - if (visibility !== handle.cachedVisibility) { - handle.cachedVisibility = visibility; - handle.cachedElement.classList.toggle("visible", visibility); - } - } - } -} +import { makeDiv } from "../../../core/utils"; +import { T } from "../../../translations"; +import { + getStringForKeyCode, + KEYCODE_LMB, + KEYCODE_MMB, + KEYCODE_RMB, + KEYMAPPINGS, +} from "../../key_action_mapper"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; + +const DIVIDER_TOKEN = "/"; +const ADDER_TOKEN = "+"; + +/** + * @typedef {{ keyCode: number }} KeyCode + */ + +/** + * @typedef {{ + * condition: () => boolean, + * keys: Array, + * label: string, + * cachedElement?: HTMLElement, + * cachedVisibility?: boolean + * }} KeyBinding + */ + +export class HUDKeybindingOverlay extends BaseHUDPart { + /** + * HELPER / Returns if there is a building selected for placement + * @returns {boolean} + */ + get buildingPlacementActive() { + const placer = this.root.hud.parts.buildingPlacer; + return !this.mapOverviewActive && placer && !!placer.currentMetaBuilding.get(); + } + + /** + * HELPER / Returns if there is a building selected for placement and + * it supports the belt planner + * @returns {boolean} + */ + get buildingPlacementSupportsBeltPlanner() { + const placer = this.root.hud.parts.buildingPlacer; + return ( + !this.mapOverviewActive && + placer && + placer.currentMetaBuilding.get() && + placer.currentMetaBuilding.get().getHasDirectionLockAvailable() + ); + } + + /** + * HELPER / Returns if there is a building selected for placement and + * it has multiplace enabled by default + * @returns {boolean} + */ + get buildingPlacementStaysInPlacement() { + const placer = this.root.hud.parts.buildingPlacer; + return ( + !this.mapOverviewActive && + placer && + placer.currentMetaBuilding.get() && + placer.currentMetaBuilding.get().getStayInPlacementMode() + ); + } + + /** + * HELPER / Returns if there is a blueprint selected for placement + * @returns {boolean} + */ + get blueprintPlacementActive() { + const placer = this.root.hud.parts.blueprintPlacer; + return placer && !!placer.currentBlueprint.get(); + } + + /** + * HELPER / Returns if the belt planner is currently active + * @returns {boolean} + */ + get beltPlannerActive() { + const placer = this.root.hud.parts.buildingPlacer; + return !this.mapOverviewActive && placer && placer.isDirectionLockActive; + } + + /** + * HELPER / Returns if there is a last blueprint available + * @returns {boolean} + */ + get lastBlueprintAvailable() { + const placer = this.root.hud.parts.blueprintPlacer; + return placer && !!placer.lastBlueprintUsed; + } + + /** + * HELPER / Returns if there is anything selected on the map + * @returns {boolean} + */ + get anythingSelectedOnMap() { + const selector = this.root.hud.parts.massSelector; + return selector && selector.selectedUids.size > 0; + } + + /** + * HELPER / Returns if there is a building or blueprint selected for placement + * @returns {boolean} + */ + get anyPlacementActive() { + return this.buildingPlacementActive || this.blueprintPlacementActive; + } + + /** + * HELPER / Returns if the map overview is active + * @returns {boolean} + */ + get mapOverviewActive() { + return this.root.camera.getIsMapOverlayActive(); + } + + /** + * Initializes the element + * @param {HTMLElement} parent + */ + createElements(parent) { + const mapper = this.root.keyMapper; + const k = KEYMAPPINGS; + + /** @type {Array} */ + this.keybindings = [ + { + // Move map - Including mouse + label: T.ingame.keybindingsOverlay.moveMap, + keys: [ + KEYCODE_LMB, + DIVIDER_TOKEN, + k.navigation.mapMoveUp, + k.navigation.mapMoveLeft, + k.navigation.mapMoveDown, + k.navigation.mapMoveRight, + ], + condition: () => !this.anyPlacementActive, + }, + + { + // Move map - No mouse + label: T.ingame.keybindingsOverlay.moveMap, + keys: [ + k.navigation.mapMoveUp, + k.navigation.mapMoveLeft, + k.navigation.mapMoveDown, + k.navigation.mapMoveRight, + ], + condition: () => this.anyPlacementActive, + }, + + { + // [OVERVIEW] Create marker with right click + label: T.ingame.keybindingsOverlay.createMarker, + keys: [KEYCODE_RMB], + condition: () => this.mapOverviewActive && !this.blueprintPlacementActive, + }, + + { + // Pipette + label: T.ingame.keybindingsOverlay.pipette, + keys: [k.placement.pipette], + condition: () => !this.mapOverviewActive && !this.blueprintPlacementActive, + }, + + { + // Cancel placement + label: T.ingame.keybindingsOverlay.stopPlacement, + keys: [KEYCODE_RMB], + condition: () => this.anyPlacementActive, + }, + + { + // Delete with right click + label: T.ingame.keybindingsOverlay.delete, + keys: [KEYCODE_RMB], + condition: () => + !this.anyPlacementActive && !this.mapOverviewActive && !this.anythingSelectedOnMap, + }, + + { + // Area select + label: T.ingame.keybindingsOverlay.selectBuildings, + keys: [k.massSelect.massSelectStart, ADDER_TOKEN, KEYCODE_LMB], + condition: () => !this.anyPlacementActive && !this.anythingSelectedOnMap, + }, + + { + // Place building + label: T.ingame.keybindingsOverlay.placeBuilding, + keys: [KEYCODE_LMB], + condition: () => this.anyPlacementActive, + }, + + { + // Rotate + label: T.ingame.keybindingsOverlay.rotateBuilding, + keys: [k.placement.rotateWhilePlacing], + condition: () => this.anyPlacementActive && !this.beltPlannerActive, + }, + + { + // [BELT PLANNER] Flip Side + label: T.ingame.keybindingsOverlay.plannerSwitchSide, + keys: [k.placement.switchDirectionLockSide], + condition: () => this.beltPlannerActive, + }, + + { + // Place last blueprint + label: T.ingame.keybindingsOverlay.pasteLastBlueprint, + keys: [k.massSelect.pasteLastBlueprint], + condition: () => !this.blueprintPlacementActive && this.lastBlueprintAvailable, + }, + + { + // Belt planner + label: T.ingame.keybindingsOverlay.lockBeltDirection, + keys: [k.placementModifiers.lockBeltDirection], + condition: () => this.buildingPlacementSupportsBeltPlanner && !this.beltPlannerActive, + }, + + { + // [SELECTION] Destroy + label: T.ingame.keybindingsOverlay.delete, + keys: [k.massSelect.confirmMassDelete], + condition: () => this.anythingSelectedOnMap, + }, + + { + // [SELECTION] Cancel + label: T.ingame.keybindingsOverlay.clearSelection, + keys: [k.general.back], + condition: () => this.anythingSelectedOnMap, + }, + { + // [SELECTION] Cut + label: T.ingame.keybindingsOverlay.cutSelection, + keys: [k.massSelect.massSelectCut], + condition: () => this.anythingSelectedOnMap, + }, + + { + // [SELECTION] Copy + label: T.ingame.keybindingsOverlay.copySelection, + keys: [k.massSelect.massSelectCopy], + condition: () => this.anythingSelectedOnMap, + }, + + { + // Switch layers + label: T.ingame.keybindingsOverlay.switchLayers, + keys: [k.ingame.switchLayers], + condition: () => true, + }, + ]; + + if (!this.root.app.settings.getAllSettings().alwaysMultiplace) { + this.keybindings.push({ + // Multiplace + label: T.ingame.keybindingsOverlay.placeMultiple, + keys: [k.placementModifiers.placeMultiple], + condition: () => this.anyPlacementActive && !this.buildingPlacementStaysInPlacement, + }); + } + + this.element = makeDiv(parent, "ingame_HUD_KeybindingOverlay", []); + + for (let i = 0; i < this.keybindings.length; ++i) { + let html = ""; + const handle = this.keybindings[i]; + + for (let k = 0; k < handle.keys.length; ++k) { + const key = handle.keys[k]; + + switch (key) { + case KEYCODE_LMB: + html += ``; + break; + case KEYCODE_RMB: + html += ``; + break; + case KEYCODE_MMB: + html += ``; + break; + case DIVIDER_TOKEN: + html += ``; + break; + case ADDER_TOKEN: + html += `+`; + break; + default: + html += `${getStringForKeyCode( + mapper.getBinding(/** @type {KeyCode} */ (key)).keyCode + )}`; + } + } + html += ``; + + handle.cachedElement = makeDiv(this.element, null, ["binding"], html); + handle.cachedVisibility = false; + } + } + + initialize() { + this.domAttach = new DynamicDomAttach(this.root, this.element, { + trackHover: true, + }); + } + + update() { + for (let i = 0; i < this.keybindings.length; ++i) { + const handle = this.keybindings[i]; + const visibility = handle.condition(); + if (visibility !== handle.cachedVisibility) { + handle.cachedVisibility = visibility; + handle.cachedElement.classList.toggle("visible", visibility); + } + } + + // Required for hover + this.domAttach.update(true); + } +} diff --git a/src/js/game/hud/parts/layer_preview.js b/src/js/game/hud/parts/layer_preview.js new file mode 100644 index 00000000..36e0ea58 --- /dev/null +++ b/src/js/game/hud/parts/layer_preview.js @@ -0,0 +1,123 @@ +import { freeCanvas, makeOffscreenBuffer } from "../../../core/buffer_utils"; +import { globalConfig } from "../../../core/config"; +import { Loader } from "../../../core/loader"; +import { Vector } from "../../../core/vector"; +import { MapChunkView } from "../../map_chunk_view"; +import { THEME } from "../../theme"; +import { BaseHUDPart } from "../base_hud_part"; + +/** + * Helper class which allows peaking through to the wires layer + */ +export class HUDLayerPreview extends BaseHUDPart { + initialize() { + this.initializeCanvas(); + this.root.signals.aboutToDestruct.add(() => freeCanvas(this.canvas)); + this.root.signals.resized.add(this.initializeCanvas, this); + this.previewOverlay = Loader.getSprite("sprites/wires/wires_preview.png"); + } + + /** + * (re) initializes the canvas + */ + initializeCanvas() { + if (this.canvas) { + freeCanvas(this.canvas); + delete this.canvas; + delete this.context; + } + + // Compute how big the preview should be + this.previewSize = Math.round( + Math.min(1024, Math.min(this.root.gameWidth, this.root.gameHeight) * 0.8) + ); + + const [canvas, context] = makeOffscreenBuffer(this.previewSize, this.previewSize, { + smooth: true, + label: "layerPeeker", + reusable: true, + }); + + context.clearRect(0, 0, this.previewSize, this.previewSize); + this.canvas = canvas; + this.context = context; + } + + /** + * Prepares the canvas to render at the given worldPos and the given camera scale + * + * @param {Vector} worldPos + * @param {number} scale 1 / zoomLevel + */ + prepareCanvasForPreview(worldPos, scale) { + this.context.clearRect(0, 0, this.previewSize, this.previewSize); + this.context.fillStyle = THEME.map.wires.previewColor; + this.context.fillRect(0, 0, this.previewSize, this.previewSize); + + const dimensions = scale * this.previewSize; + + const startWorldX = worldPos.x - dimensions / 2; + const startWorldY = worldPos.y - dimensions / 2; + + const startTileX = Math.floor(startWorldX / globalConfig.tileSize); + const startTileY = Math.floor(startWorldY / globalConfig.tileSize); + const tileDimensions = Math.ceil(dimensions / globalConfig.tileSize); + + this.context.save(); + this.context.scale(1 / scale, 1 / scale); + this.context.translate( + startTileX * globalConfig.tileSize - startWorldX, + startTileY * globalConfig.tileSize - startWorldY + ); + + for (let dx = 0; dx < tileDimensions; ++dx) { + for (let dy = 0; dy < tileDimensions; ++dy) { + const tileX = dx + startTileX; + const tileY = dy + startTileY; + + const content = this.root.map.getLayerContentXY(tileX, tileY, "wires"); + if (content) { + MapChunkView.drawSingleWiresOverviewTile({ + context: this.context, + x: dx * globalConfig.tileSize, + y: dy * globalConfig.tileSize, + entity: content, + tileSizePixels: globalConfig.tileSize, + }); + } + } + } + + this.context.restore(); + this.context.globalCompositeOperation = "destination-in"; + this.previewOverlay.draw(this.context, 0, 0, this.previewSize, this.previewSize); + this.context.globalCompositeOperation = "source-over"; + + return this.canvas; + } + + /** + * Renders the preview at the given position + * @param {import("../../../core/draw_utils").DrawParameters} parameters + * @param {Vector} worldPos + * @param {number} scale 1 / zoomLevel + */ + renderPreview(parameters, worldPos, scale) { + if (this.root.currentLayer !== "regular") { + // Only supporting wires right now + return; + } + + const canvas = this.prepareCanvasForPreview(worldPos, scale); + + parameters.context.globalAlpha = 0.3; + parameters.context.drawImage( + canvas, + worldPos.x - (scale * this.previewSize) / 2, + worldPos.y - (scale * this.previewSize) / 2, + scale * this.previewSize, + scale * this.previewSize + ); + parameters.context.globalAlpha = 1; + } +} diff --git a/src/js/game/hud/parts/lever_toggle.js b/src/js/game/hud/parts/lever_toggle.js new file mode 100644 index 00000000..1859f7ab --- /dev/null +++ b/src/js/game/hud/parts/lever_toggle.js @@ -0,0 +1,31 @@ +import { STOP_PROPAGATION } from "../../../core/signal"; +import { Vector } from "../../../core/vector"; +import { enumMouseButton } from "../../camera"; +import { BaseHUDPart } from "../base_hud_part"; + +export class HUDLeverToggle extends BaseHUDPart { + initialize() { + this.root.camera.downPreHandler.add(this.downPreHandler, this); + } + + /** + * @param {Vector} pos + * @param {enumMouseButton} button + */ + downPreHandler(pos, button) { + const tile = this.root.camera.screenToWorld(pos).toTileSpace(); + const contents = this.root.map.getLayerContentXY(tile.x, tile.y, "regular"); + if (contents) { + const leverComp = contents.components.Lever; + if (leverComp) { + if (button === enumMouseButton.left) { + leverComp.toggled = !leverComp.toggled; + return STOP_PROPAGATION; + } else if (button === enumMouseButton.right) { + this.root.logic.tryDeleteBuilding(contents); + return STOP_PROPAGATION; + } + } + } + } +} diff --git a/src/js/game/hud/parts/mass_selector.js b/src/js/game/hud/parts/mass_selector.js index 68d480e4..a8972434 100644 --- a/src/js/game/hud/parts/mass_selector.js +++ b/src/js/game/hud/parts/mass_selector.js @@ -1,310 +1,317 @@ -import { BaseHUDPart } from "../base_hud_part"; -import { Vector } from "../../../core/vector"; -import { STOP_PROPAGATION } from "../../../core/signal"; -import { DrawParameters } from "../../../core/draw_parameters"; -import { Entity } from "../../entity"; -import { Loader } from "../../../core/loader"; -import { globalConfig } from "../../../core/config"; -import { makeDiv, formatBigNumber, formatBigNumberFull } from "../../../core/utils"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; -import { createLogger } from "../../../core/logging"; -import { enumMouseButton } from "../../camera"; -import { T } from "../../../translations"; -import { KEYMAPPINGS } from "../../key_action_mapper"; -import { THEME } from "../../theme"; -import { enumHubGoalRewards } from "../../tutorial_goals"; -import { Blueprint } from "../../blueprint"; - -const logger = createLogger("hud/mass_selector"); - -export class HUDMassSelector extends BaseHUDPart { - createElements(parent) {} - - initialize() { - this.deletionMarker = Loader.getSprite("sprites/misc/deletion_marker.png"); - - this.currentSelectionStartWorld = null; - this.currentSelectionEnd = null; - this.selectedUids = new Set(); - - this.root.signals.entityQueuedForDestroy.add(this.onEntityDestroyed, this); - this.root.hud.signals.pasteBlueprintRequested.add(this.clearSelection, this); - - this.root.camera.downPreHandler.add(this.onMouseDown, this); - this.root.camera.movePreHandler.add(this.onMouseMove, this); - this.root.camera.upPostHandler.add(this.onMouseUp, this); - - this.root.keyMapper.getBinding(KEYMAPPINGS.general.back).add(this.onBack, this); - this.root.keyMapper - .getBinding(KEYMAPPINGS.massSelect.confirmMassDelete) - .add(this.confirmDelete, this); - this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectCut).add(this.confirmCut, this); - this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectCopy).add(this.startCopy, this); - - this.root.hud.signals.selectedPlacementBuildingChanged.add(this.clearSelection, this); - this.root.signals.editModeChanged.add(this.clearSelection, this); - } - - /** - * Handles the destroy callback and makes sure we clean our list - * @param {Entity} entity - */ - onEntityDestroyed(entity) { - this.selectedUids.delete(entity.uid); - } - - /** - * - */ - onBack() { - // Clear entities on escape - if (this.selectedUids.size > 0) { - this.selectedUids = new Set(); - return STOP_PROPAGATION; - } - } - - /** - * Clears the entire selection - */ - clearSelection() { - this.selectedUids = new Set(); - } - - confirmDelete() { - if ( - !this.root.app.settings.getAllSettings().disableCutDeleteWarnings && - this.selectedUids.size > 100 - ) { - const { ok } = this.root.hud.parts.dialogs.showWarning( - T.dialogs.massDeleteConfirm.title, - T.dialogs.massDeleteConfirm.desc.replace( - "", - "" + formatBigNumberFull(this.selectedUids.size) - ), - ["cancel:good:escape", "ok:bad:enter"] - ); - ok.add(() => this.doDelete()); - } else { - this.doDelete(); - } - } - - doDelete() { - const entityUids = Array.from(this.selectedUids); - for (let i = 0; i < entityUids.length; ++i) { - const uid = entityUids[i]; - const entity = this.root.entityMgr.findByUid(uid); - if (!this.root.logic.tryDeleteBuilding(entity)) { - logger.error("Error in mass delete, could not remove building"); - this.selectedUids.delete(uid); - } - } - } - - startCopy() { - if (this.selectedUids.size > 0) { - if (!this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) { - this.root.hud.parts.dialogs.showInfo( - T.dialogs.blueprintsNotUnlocked.title, - T.dialogs.blueprintsNotUnlocked.desc - ); - return; - } - this.root.hud.signals.buildingsSelectedForCopy.dispatch(Array.from(this.selectedUids)); - this.selectedUids = new Set(); - this.root.soundProxy.playUiClick(); - } else { - this.root.soundProxy.playUiError(); - } - } - - confirmCut() { - if (!this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) { - this.root.hud.parts.dialogs.showInfo( - T.dialogs.blueprintsNotUnlocked.title, - T.dialogs.blueprintsNotUnlocked.desc - ); - } else if ( - !this.root.app.settings.getAllSettings().disableCutDeleteWarnings && - this.selectedUids.size > 100 - ) { - const { ok } = this.root.hud.parts.dialogs.showWarning( - T.dialogs.massCutConfirm.title, - T.dialogs.massCutConfirm.desc.replace( - "", - "" + formatBigNumberFull(this.selectedUids.size) - ), - ["cancel:good:escape", "ok:bad:enter"] - ); - ok.add(() => this.doCut()); - } else { - this.doCut(); - } - } - - doCut() { - if (this.selectedUids.size > 0) { - const entityUids = Array.from(this.selectedUids); - - const cutAction = () => { - // copy code relies on entities still existing, so must copy before deleting. - this.root.hud.signals.buildingsSelectedForCopy.dispatch(entityUids); - - for (let i = 0; i < entityUids.length; ++i) { - const uid = entityUids[i]; - const entity = this.root.entityMgr.findByUid(uid); - if (!this.root.logic.tryDeleteBuilding(entity)) { - logger.error("Error in mass cut, could not remove building"); - this.selectedUids.delete(uid); - } - } - }; - - const blueprint = Blueprint.fromUids(this.root, entityUids); - if (blueprint.canAfford(this.root)) { - cutAction(); - } else { - const { cancel, ok } = this.root.hud.parts.dialogs.showWarning( - T.dialogs.massCutInsufficientConfirm.title, - T.dialogs.massCutInsufficientConfirm.desc, - ["cancel:good:escape", "ok:bad:enter"] - ); - ok.add(cutAction); - } - - this.root.soundProxy.playUiClick(); - } else { - this.root.soundProxy.playUiError(); - } - } - - /** - * mouse down pre handler - * @param {Vector} pos - * @param {enumMouseButton} mouseButton - */ - onMouseDown(pos, mouseButton) { - if (!this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectStart).pressed) { - return; - } - - if (mouseButton !== enumMouseButton.left) { - return; - } - - if (!this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectSelectMultiple).pressed) { - // Start new selection - this.selectedUids = new Set(); - } - - this.currentSelectionStartWorld = this.root.camera.screenToWorld(pos.copy()); - this.currentSelectionEnd = pos.copy(); - return STOP_PROPAGATION; - } - - /** - * mouse move pre handler - * @param {Vector} pos - */ - onMouseMove(pos) { - if (this.currentSelectionStartWorld) { - this.currentSelectionEnd = pos.copy(); - } - } - - onMouseUp() { - if (this.currentSelectionStartWorld) { - const worldStart = this.currentSelectionStartWorld; - const worldEnd = this.root.camera.screenToWorld(this.currentSelectionEnd); - - const tileStart = worldStart.toTileSpace(); - const tileEnd = worldEnd.toTileSpace(); - - const realTileStart = tileStart.min(tileEnd); - const realTileEnd = tileStart.max(tileEnd); - - for (let x = realTileStart.x; x <= realTileEnd.x; ++x) { - for (let y = realTileStart.y; y <= realTileEnd.y; ++y) { - const contents = this.root.map.getLayerContentXY(x, y, this.root.currentLayer); - if (contents && this.root.logic.canDeleteBuilding(contents)) { - this.selectedUids.add(contents.uid); - } - } - } - - this.currentSelectionStartWorld = null; - this.currentSelectionEnd = null; - } - } - - /** - * - * @param {DrawParameters} parameters - */ - draw(parameters) { - const boundsBorder = 2; - - if (this.currentSelectionStartWorld) { - const worldStart = this.currentSelectionStartWorld; - const worldEnd = this.root.camera.screenToWorld(this.currentSelectionEnd); - - const realWorldStart = worldStart.min(worldEnd); - const realWorldEnd = worldStart.max(worldEnd); - - const tileStart = worldStart.toTileSpace(); - const tileEnd = worldEnd.toTileSpace(); - - const realTileStart = tileStart.min(tileEnd); - const realTileEnd = tileStart.max(tileEnd); - - parameters.context.lineWidth = 1; - parameters.context.fillStyle = THEME.map.selectionBackground; - parameters.context.strokeStyle = THEME.map.selectionOutline; - parameters.context.beginPath(); - parameters.context.rect( - realWorldStart.x, - realWorldStart.y, - realWorldEnd.x - realWorldStart.x, - realWorldEnd.y - realWorldStart.y - ); - parameters.context.fill(); - parameters.context.stroke(); - - parameters.context.fillStyle = THEME.map.selectionOverlay; - - for (let x = realTileStart.x; x <= realTileEnd.x; ++x) { - for (let y = realTileStart.y; y <= realTileEnd.y; ++y) { - const contents = this.root.map.getLayerContentXY(x, y, this.root.currentLayer); - if (contents && this.root.logic.canDeleteBuilding(contents)) { - const staticComp = contents.components.StaticMapEntity; - const bounds = staticComp.getTileSpaceBounds(); - parameters.context.beginRoundedRect( - bounds.x * globalConfig.tileSize + boundsBorder, - bounds.y * globalConfig.tileSize + boundsBorder, - bounds.w * globalConfig.tileSize - 2 * boundsBorder, - bounds.h * globalConfig.tileSize - 2 * boundsBorder, - 2 - ); - parameters.context.fill(); - } - } - } - } - - parameters.context.fillStyle = THEME.map.selectionOverlay; - this.selectedUids.forEach(uid => { - const entity = this.root.entityMgr.findByUid(uid); - const staticComp = entity.components.StaticMapEntity; - const bounds = staticComp.getTileSpaceBounds(); - parameters.context.beginRoundedRect( - bounds.x * globalConfig.tileSize + boundsBorder, - bounds.y * globalConfig.tileSize + boundsBorder, - bounds.w * globalConfig.tileSize - 2 * boundsBorder, - bounds.h * globalConfig.tileSize - 2 * boundsBorder, - 2 - ); - parameters.context.fill(); - }); - } -} +import { BaseHUDPart } from "../base_hud_part"; +import { Vector } from "../../../core/vector"; +import { STOP_PROPAGATION } from "../../../core/signal"; +import { DrawParameters } from "../../../core/draw_parameters"; +import { Entity } from "../../entity"; +import { Loader } from "../../../core/loader"; +import { globalConfig } from "../../../core/config"; +import { makeDiv, formatBigNumber, formatBigNumberFull } from "../../../core/utils"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; +import { createLogger } from "../../../core/logging"; +import { enumMouseButton } from "../../camera"; +import { T } from "../../../translations"; +import { KEYMAPPINGS } from "../../key_action_mapper"; +import { THEME } from "../../theme"; +import { enumHubGoalRewards } from "../../tutorial_goals"; +import { Blueprint } from "../../blueprint"; + +const logger = createLogger("hud/mass_selector"); + +export class HUDMassSelector extends BaseHUDPart { + createElements(parent) {} + + initialize() { + this.currentSelectionStartWorld = null; + this.currentSelectionEnd = null; + this.selectedUids = new Set(); + + this.root.signals.entityQueuedForDestroy.add(this.onEntityDestroyed, this); + this.root.hud.signals.pasteBlueprintRequested.add(this.clearSelection, this); + + this.root.camera.downPreHandler.add(this.onMouseDown, this); + this.root.camera.movePreHandler.add(this.onMouseMove, this); + this.root.camera.upPostHandler.add(this.onMouseUp, this); + + this.root.keyMapper.getBinding(KEYMAPPINGS.general.back).add(this.onBack, this); + this.root.keyMapper + .getBinding(KEYMAPPINGS.massSelect.confirmMassDelete) + .add(this.confirmDelete, this); + this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectCut).add(this.confirmCut, this); + this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectCopy).add(this.startCopy, this); + + this.root.hud.signals.selectedPlacementBuildingChanged.add(this.clearSelection, this); + this.root.signals.editModeChanged.add(this.clearSelection, this); + } + + /** + * Handles the destroy callback and makes sure we clean our list + * @param {Entity} entity + */ + onEntityDestroyed(entity) { + this.selectedUids.delete(entity.uid); + } + + /** + * + */ + onBack() { + // Clear entities on escape + if (this.selectedUids.size > 0) { + this.selectedUids = new Set(); + return STOP_PROPAGATION; + } + } + + /** + * Clears the entire selection + */ + clearSelection() { + this.selectedUids = new Set(); + } + + confirmDelete() { + if ( + !this.root.app.settings.getAllSettings().disableCutDeleteWarnings && + this.selectedUids.size > 100 + ) { + const { ok } = this.root.hud.parts.dialogs.showWarning( + T.dialogs.massDeleteConfirm.title, + T.dialogs.massDeleteConfirm.desc.replace( + "", + "" + formatBigNumberFull(this.selectedUids.size) + ), + ["cancel:good:escape", "ok:bad:enter"] + ); + ok.add(() => this.doDelete()); + } else { + this.doDelete(); + } + } + + doDelete() { + const entityUids = Array.from(this.selectedUids); + for (let i = 0; i < entityUids.length; ++i) { + const uid = entityUids[i]; + const entity = this.root.entityMgr.findByUid(uid); + if (!this.root.logic.tryDeleteBuilding(entity)) { + logger.error("Error in mass delete, could not remove building"); + this.selectedUids.delete(uid); + } + } + } + + startCopy() { + if (this.selectedUids.size > 0) { + if (!this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) { + this.root.hud.parts.dialogs.showInfo( + T.dialogs.blueprintsNotUnlocked.title, + T.dialogs.blueprintsNotUnlocked.desc + ); + return; + } + this.root.hud.signals.buildingsSelectedForCopy.dispatch(Array.from(this.selectedUids)); + this.selectedUids = new Set(); + this.root.soundProxy.playUiClick(); + } else { + this.root.soundProxy.playUiError(); + } + } + + confirmCut() { + if (!this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) { + this.root.hud.parts.dialogs.showInfo( + T.dialogs.blueprintsNotUnlocked.title, + T.dialogs.blueprintsNotUnlocked.desc + ); + } else if ( + !this.root.app.settings.getAllSettings().disableCutDeleteWarnings && + this.selectedUids.size > 100 + ) { + const { ok } = this.root.hud.parts.dialogs.showWarning( + T.dialogs.massCutConfirm.title, + T.dialogs.massCutConfirm.desc.replace( + "", + "" + formatBigNumberFull(this.selectedUids.size) + ), + ["cancel:good:escape", "ok:bad:enter"] + ); + ok.add(() => this.doCut()); + } else { + this.doCut(); + } + } + + doCut() { + if (this.selectedUids.size > 0) { + const entityUids = Array.from(this.selectedUids); + + const cutAction = () => { + // copy code relies on entities still existing, so must copy before deleting. + this.root.hud.signals.buildingsSelectedForCopy.dispatch(entityUids); + + for (let i = 0; i < entityUids.length; ++i) { + const uid = entityUids[i]; + const entity = this.root.entityMgr.findByUid(uid); + if (!this.root.logic.tryDeleteBuilding(entity)) { + logger.error("Error in mass cut, could not remove building"); + this.selectedUids.delete(uid); + } + } + }; + + const blueprint = Blueprint.fromUids(this.root, entityUids); + if (blueprint.canAfford(this.root)) { + cutAction(); + } else { + const { cancel, ok } = this.root.hud.parts.dialogs.showWarning( + T.dialogs.massCutInsufficientConfirm.title, + T.dialogs.massCutInsufficientConfirm.desc, + ["cancel:good:escape", "ok:bad:enter"] + ); + ok.add(cutAction); + } + + this.root.soundProxy.playUiClick(); + } else { + this.root.soundProxy.playUiError(); + } + } + + /** + * mouse down pre handler + * @param {Vector} pos + * @param {enumMouseButton} mouseButton + */ + onMouseDown(pos, mouseButton) { + if (!this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectStart).pressed) { + return; + } + + if (mouseButton !== enumMouseButton.left) { + return; + } + + if (!this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectSelectMultiple).pressed) { + // Start new selection + this.selectedUids = new Set(); + } + + this.currentSelectionStartWorld = this.root.camera.screenToWorld(pos.copy()); + this.currentSelectionEnd = pos.copy(); + return STOP_PROPAGATION; + } + + /** + * mouse move pre handler + * @param {Vector} pos + */ + onMouseMove(pos) { + if (this.currentSelectionStartWorld) { + this.currentSelectionEnd = pos.copy(); + } + } + + onMouseUp() { + if (this.currentSelectionStartWorld) { + const worldStart = this.currentSelectionStartWorld; + const worldEnd = this.root.camera.screenToWorld(this.currentSelectionEnd); + + const tileStart = worldStart.toTileSpace(); + const tileEnd = worldEnd.toTileSpace(); + + const realTileStart = tileStart.min(tileEnd); + const realTileEnd = tileStart.max(tileEnd); + + for (let x = realTileStart.x; x <= realTileEnd.x; ++x) { + for (let y = realTileStart.y; y <= realTileEnd.y; ++y) { + const contents = this.root.map.getLayerContentXY(x, y, this.root.currentLayer); + if (contents && this.root.logic.canDeleteBuilding(contents)) { + this.selectedUids.add(contents.uid); + } + } + } + + this.currentSelectionStartWorld = null; + this.currentSelectionEnd = null; + } + } + + /** + * + * @param {DrawParameters} parameters + */ + draw(parameters) { + const boundsBorder = 2; + + if (this.currentSelectionStartWorld) { + const worldStart = this.currentSelectionStartWorld; + const worldEnd = this.root.camera.screenToWorld(this.currentSelectionEnd); + + const realWorldStart = worldStart.min(worldEnd); + const realWorldEnd = worldStart.max(worldEnd); + + const tileStart = worldStart.toTileSpace(); + const tileEnd = worldEnd.toTileSpace(); + + const realTileStart = tileStart.min(tileEnd); + const realTileEnd = tileStart.max(tileEnd); + + parameters.context.lineWidth = 1; + parameters.context.fillStyle = THEME.map.selectionBackground; + parameters.context.strokeStyle = THEME.map.selectionOutline; + parameters.context.beginPath(); + parameters.context.rect( + realWorldStart.x, + realWorldStart.y, + realWorldEnd.x - realWorldStart.x, + realWorldEnd.y - realWorldStart.y + ); + parameters.context.fill(); + parameters.context.stroke(); + + parameters.context.fillStyle = THEME.map.selectionOverlay; + + const renderedUids = new Set(); + + for (let x = realTileStart.x; x <= realTileEnd.x; ++x) { + for (let y = realTileStart.y; y <= realTileEnd.y; ++y) { + const contents = this.root.map.getLayerContentXY(x, y, this.root.currentLayer); + if (contents && this.root.logic.canDeleteBuilding(contents)) { + // Prevent rendering the overlay twice + const uid = contents.uid; + if (renderedUids.has(uid)) { + continue; + } + renderedUids.add(uid); + + const staticComp = contents.components.StaticMapEntity; + const bounds = staticComp.getTileSpaceBounds(); + parameters.context.beginRoundedRect( + bounds.x * globalConfig.tileSize + boundsBorder, + bounds.y * globalConfig.tileSize + boundsBorder, + bounds.w * globalConfig.tileSize - 2 * boundsBorder, + bounds.h * globalConfig.tileSize - 2 * boundsBorder, + 2 + ); + parameters.context.fill(); + } + } + } + } + + parameters.context.fillStyle = THEME.map.selectionOverlay; + this.selectedUids.forEach(uid => { + const entity = this.root.entityMgr.findByUid(uid); + const staticComp = entity.components.StaticMapEntity; + const bounds = staticComp.getTileSpaceBounds(); + parameters.context.beginRoundedRect( + bounds.x * globalConfig.tileSize + boundsBorder, + bounds.y * globalConfig.tileSize + boundsBorder, + bounds.w * globalConfig.tileSize - 2 * boundsBorder, + bounds.h * globalConfig.tileSize - 2 * boundsBorder, + 2 + ); + parameters.context.fill(); + }); + } +} diff --git a/src/js/game/hud/parts/miner_highlight.js b/src/js/game/hud/parts/miner_highlight.js new file mode 100644 index 00000000..c2b23583 --- /dev/null +++ b/src/js/game/hud/parts/miner_highlight.js @@ -0,0 +1,170 @@ +import { globalConfig } from "../../../core/config"; +import { formatItemsPerSecond, round2Digits } from "../../../core/utils"; +import { Vector } from "../../../core/vector"; +import { T } from "../../../translations"; +import { Entity } from "../../entity"; +import { THEME } from "../../theme"; +import { BaseHUDPart } from "../base_hud_part"; + +export class HUDMinerHighlight extends BaseHUDPart { + initialize() {} + + /** + * + * @param {import("../../../core/draw_utils").DrawParameters} parameters + */ + draw(parameters) { + const mousePos = this.root.app.mousePosition; + if (!mousePos) { + // Mouse pos not ready + return; + } + + if (this.root.currentLayer !== "regular") { + // Not within the regular layer + return; + } + + if (this.root.camera.getIsMapOverlayActive()) { + // Not within the map overlay + return; + } + + const worldPos = this.root.camera.screenToWorld(mousePos); + const hoveredTile = worldPos.toTileSpace(); + + const contents = this.root.map.getTileContent(hoveredTile, "regular"); + if (!contents) { + // Empty tile + return; + } + + const minerComp = contents.components.Miner; + if (!minerComp || !minerComp.chainable) { + // Not a chainable miner + return; + } + + parameters.context.fillStyle = THEME.map.connectedMiners.overlay; + + const connectedEntities = this.findConnectedMiners(contents); + + for (let i = 0; i < connectedEntities.length; ++i) { + const entity = connectedEntities[i]; + const staticComp = entity.components.StaticMapEntity; + + parameters.context.beginRoundedRect( + staticComp.origin.x * globalConfig.tileSize + 5, + staticComp.origin.y * globalConfig.tileSize + 5, + globalConfig.tileSize - 10, + globalConfig.tileSize - 10, + 3 + ); + parameters.context.fill(); + } + + const throughput = round2Digits(connectedEntities.length * this.root.hubGoals.getMinerBaseSpeed()); + + const maxThroughput = this.root.hubGoals.getBeltBaseSpeed(); + + const screenPos = this.root.camera.screenToWorld(mousePos); + + const scale = (1 / this.root.camera.zoomLevel) * this.root.app.getEffectiveUiScale(); + + const isCapped = throughput > maxThroughput; + + // Background + parameters.context.fillStyle = THEME.map.connectedMiners.background; + parameters.context.beginRoundedRect( + screenPos.x + 5 * scale, + screenPos.y - 3 * scale, + (isCapped ? 100 : 65) * scale, + (isCapped ? 45 : 30) * scale, + 2 + ); + parameters.context.fill(); + + // Throughput + parameters.context.fillStyle = THEME.map.connectedMiners.textColor; + parameters.context.font = "bold " + scale * 10 + "px GameFont"; + parameters.context.fillText( + formatItemsPerSecond(throughput), + screenPos.x + 10 * scale, + screenPos.y + 10 * scale + ); + + // Amount of miners + parameters.context.globalAlpha = 0.6; + parameters.context.font = "bold " + scale * 8 + "px GameFont"; + parameters.context.fillText( + connectedEntities.length === 1 + ? T.ingame.connectedMiners.one_miner + : T.ingame.connectedMiners.n_miners.replace("", String(connectedEntities.length)), + screenPos.x + 10 * scale, + screenPos.y + 22 * scale + ); + + parameters.context.globalAlpha = 1; + + if (isCapped) { + parameters.context.fillStyle = THEME.map.connectedMiners.textColorCapped; + parameters.context.fillText( + T.ingame.connectedMiners.limited_items.replace( + "", + formatItemsPerSecond(maxThroughput) + ), + screenPos.x + 10 * scale, + screenPos.y + 34 * scale + ); + } + } + + /** + * Finds all connected miners to the given entity + * @param {Entity} entity + * @param {Set} seenUids Which entities have already been processed + * @returns {Array} The connected miners + */ + findConnectedMiners(entity, seenUids = new Set()) { + let results = []; + const origin = entity.components.StaticMapEntity.origin; + + if (!seenUids.has(entity.uid)) { + seenUids.add(entity.uid); + results.push(entity); + } + + // Check for the miner which we connect to + const connectedMiner = this.root.systemMgr.systems.miner.findChainedMiner(entity); + if (connectedMiner && !seenUids.has(connectedMiner.uid)) { + results.push(connectedMiner); + seenUids.add(connectedMiner.uid); + results.push(...this.findConnectedMiners(connectedMiner, seenUids)); + } + + // Search within a 1x1 grid - this assumes miners are always 1x1 + for (let dx = -1; dx <= 1; ++dx) { + for (let dy = -1; dy <= 1; ++dy) { + const contents = this.root.map.getTileContent( + new Vector(origin.x + dx, origin.y + dy), + "regular" + ); + if (contents) { + const minerComp = contents.components.Miner; + if (minerComp && minerComp.chainable) { + // Found a miner connected to this entity + if (!seenUids.has(contents.uid)) { + if (this.root.systemMgr.systems.miner.findChainedMiner(contents) === entity) { + results.push(contents); + seenUids.add(contents.uid); + results.push(...this.findConnectedMiners(contents, seenUids)); + } + } + } + } + } + } + + return results; + } +} diff --git a/src/js/game/hud/parts/pinned_shapes.js b/src/js/game/hud/parts/pinned_shapes.js index bda49f1e..2f7dd11e 100644 --- a/src/js/game/hud/parts/pinned_shapes.js +++ b/src/js/game/hud/parts/pinned_shapes.js @@ -1,5 +1,5 @@ import { ClickDetector } from "../../../core/click_detector"; -import { formatBigNumber, makeDiv, arrayDelete, arrayDeleteValue } from "../../../core/utils"; +import { formatBigNumber, makeDiv, arrayDeleteValue } from "../../../core/utils"; import { ShapeDefinition } from "../../shape_definition"; import { BaseHUDPart } from "../base_hud_part"; import { blueprintShape, UPGRADES } from "../../upgrades"; diff --git a/src/js/game/hud/parts/processing_overlay.js b/src/js/game/hud/parts/processing_overlay.js deleted file mode 100644 index 95383dfd..00000000 --- a/src/js/game/hud/parts/processing_overlay.js +++ /dev/null @@ -1,112 +0,0 @@ -import { DynamicDomAttach } from "../dynamic_dom_attach"; -import { BaseHUDPart } from "../base_hud_part"; -import { makeDiv } from "../../../core/utils"; -import { Signal } from "../../../core/signal"; -import { InputReceiver } from "../../../core/input_receiver"; -import { createLogger } from "../../../core/logging"; - -const logger = createLogger("hud/processing_overlay"); - -export class HUDProcessingOverlay extends BaseHUDPart { - constructor(root) { - super(root); - this.tasks = []; - this.computeTimeout = null; - - this.root.signals.performAsync.add(this.queueTask, this); - - this.allTasksFinished = new Signal(); - this.inputReceiver = new InputReceiver("processing-overlay"); - - this.root.signals.aboutToDestruct.add(() => - this.root.app.inputMgr.destroyReceiver(this.inputReceiver) - ); - } - - createElements(parent) { - this.element = makeDiv( - parent, - "rg_HUD_ProcessingOverlay", - ["hudElement"], - ` - - Computing - - ` - ); - } - - initialize() { - this.domWatcher = new DynamicDomAttach(this.root, this.element, { - timeToKeepSeconds: 0, - }); - } - - queueTask(task, name) { - if (!this.root.gameInitialized) { - // Tasks before the game started can be done directlry - task(); - return; - } - task.__name = name; - this.tasks.push(task); - } - - hasTasks() { - return this.tasks.length > 0; - } - - isRunning() { - return this.computeTimeout !== null; - } - - processSync() { - const now = performance.now(); - while (this.tasks.length > 0) { - const workload = this.tasks[0]; - workload.call(); - this.tasks.shift(); - } - const duration = performance.now() - now; - if (duration > 100) { - logger.log("Tasks done slow (SYNC!) within", (performance.now() - now).toFixed(2), "ms"); - } - } - - process() { - this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReceiver); - - this.domWatcher.update(true); - if (this.tasks.length === 0) { - logger.warn("No tasks but still called process"); - return; - } - - if (this.computeTimeout) { - assert(false, "Double compute queued"); - clearTimeout(this.computeTimeout); - } - - this.computeTimeout = setTimeout(() => { - const now = performance.now(); - while (this.tasks.length > 0) { - const workload = this.tasks[0]; - workload.call(); - this.tasks.shift(); - } - const duration = performance.now() - now; - if (duration > 100) { - logger.log("Tasks done slow within", (performance.now() - now).toFixed(2), "ms"); - } - - this.domWatcher.update(false); - - this.root.app.inputMgr.makeSureDetached(this.inputReceiver); - - clearTimeout(this.computeTimeout); - this.computeTimeout = null; - - this.allTasksFinished.dispatch(); - }); - } -} diff --git a/src/js/game/hud/parts/sandbox_controller.js b/src/js/game/hud/parts/sandbox_controller.js index 6bf277bb..dd521655 100644 --- a/src/js/game/hud/parts/sandbox_controller.js +++ b/src/js/game/hud/parts/sandbox_controller.js @@ -78,7 +78,7 @@ export class HUDSandboxController extends BaseHUDPart { if (!this.root.hubGoals.storedShapes[blueprintShape]) { this.root.hubGoals.storedShapes[blueprintShape] = 0; } - this.root.hubGoals.storedShapes[blueprintShape] += 1e4; + this.root.hubGoals.storedShapes[blueprintShape] += 1e9; } maxOutAll() { @@ -105,7 +105,7 @@ export class HUDSandboxController extends BaseHUDPart { this.root.hubGoals.upgradeImprovements[id] = improvement; this.root.signals.upgradePurchased.dispatch(id); this.root.hud.signals.notification.dispatch( - "Upgrade '" + id + "' is now at level " + this.root.hubGoals.upgradeLevels[id], + "Upgrade '" + id + "' is now at tier " + (this.root.hubGoals.upgradeLevels[id] + 1), enumNotificationType.upgrade ); } diff --git a/src/js/game/hud/parts/screenshot_exporter.js b/src/js/game/hud/parts/screenshot_exporter.js index 19c644e9..a3310204 100644 --- a/src/js/game/hud/parts/screenshot_exporter.js +++ b/src/js/game/hud/parts/screenshot_exporter.js @@ -63,7 +63,7 @@ export class HUDScreenshotExporter extends BaseHUDPart { } logger.log("ChunkSizePixels:", chunkSizePixels); - const chunkScale = chunkSizePixels / (globalConfig.mapChunkSize * globalConfig.tileSize); + const chunkScale = chunkSizePixels / globalConfig.mapChunkWorldSize; logger.log("Scale:", chunkScale); logger.log("Allocating buffer, if the factory grew too big it will crash here"); @@ -79,10 +79,10 @@ export class HUDScreenshotExporter extends BaseHUDPart { logger.log("Got buffer, rendering now ..."); const visibleRect = new Rectangle( - minChunk.x * globalConfig.mapChunkSize * globalConfig.tileSize, - minChunk.y * globalConfig.mapChunkSize * globalConfig.tileSize, - dimensions.x * globalConfig.mapChunkSize * globalConfig.tileSize, - dimensions.y * globalConfig.mapChunkSize * globalConfig.tileSize + minChunk.x * globalConfig.mapChunkWorldSize, + minChunk.y * globalConfig.mapChunkWorldSize, + dimensions.x * globalConfig.mapChunkWorldSize, + dimensions.y * globalConfig.mapChunkWorldSize ); const parameters = new DrawParameters({ context, diff --git a/src/js/game/hud/parts/settings_menu.js b/src/js/game/hud/parts/settings_menu.js index c70d6afc..391fde01 100644 --- a/src/js/game/hud/parts/settings_menu.js +++ b/src/js/game/hud/parts/settings_menu.js @@ -1,13 +1,11 @@ import { BaseHUDPart } from "../base_hud_part"; -import { makeDiv, formatSeconds, formatBigNumberFull } from "../../../core/utils"; +import { makeDiv, formatBigNumberFull } from "../../../core/utils"; import { DynamicDomAttach } from "../dynamic_dom_attach"; import { InputReceiver } from "../../../core/input_receiver"; import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper"; import { T } from "../../../translations"; import { StaticMapEntityComponent } from "../../components/static_map_entity"; -import { ItemProcessorComponent } from "../../components/item_processor"; import { BeltComponent } from "../../components/belt"; -import { IS_DEMO } from "../../../core/config"; export class HUDSettingsMenu extends BaseHUDPart { createElements(parent) { @@ -23,7 +21,7 @@ export class HUDSettingsMenu extends BaseHUDPart { ${T.ingame.settingsMenu.beltsPlaced} ${T.ingame.settingsMenu.buildingsPlaced} ${T.ingame.settingsMenu.playtime} - + ` ); @@ -57,16 +55,7 @@ export class HUDSettingsMenu extends BaseHUDPart { } returnToMenu() { - // if (IS_DEMO) { - // const { cancel, deleteGame } = this.root.hud.parts.dialogs.showWarning( - // T.dialogs.leaveNotPossibleInDemo.title, - // T.dialogs.leaveNotPossibleInDemo.desc, - // ["cancel:good", "deleteGame:bad"] - // ); - // deleteGame.add(() => this.root.gameState.goBackToMenu()); - // } else { this.root.gameState.goBackToMenu(); - // } } goToSettings() { @@ -102,20 +91,25 @@ export class HUDSettingsMenu extends BaseHUDPart { show() { this.visible = true; document.body.classList.add("ingameDialogOpen"); - // this.background.classList.add("visible"); this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); const totalMinutesPlayed = Math.ceil(this.root.time.now() / 60); - this.statsElement.querySelector(".playtime").innerText = T.global.time.xMinutes.replace( - "", - "" + totalMinutesPlayed - ); - this.statsElement.querySelector(".buildingsPlaced").innerText = formatBigNumberFull( + /** @type {HTMLElement} */ + const playtimeElement = this.statsElement.querySelector(".playtime"); + /** @type {HTMLElement} */ + const buildingsPlacedElement = this.statsElement.querySelector(".buildingsPlaced"); + /** @type {HTMLElement} */ + const beltsPlacedElement = this.statsElement.querySelector(".beltsPlaced"); + + playtimeElement.innerText = T.global.time.xMinutes.replace("", `${totalMinutesPlayed}`); + + buildingsPlacedElement.innerText = formatBigNumberFull( this.root.entityMgr.getAllWithComponent(StaticMapEntityComponent).length - this.root.entityMgr.getAllWithComponent(BeltComponent).length ); - this.statsElement.querySelector(".beltsPlaced").innerText = formatBigNumberFull( + + beltsPlacedElement.innerText = formatBigNumberFull( this.root.entityMgr.getAllWithComponent(BeltComponent).length ); } diff --git a/src/js/game/hud/parts/shape_viewer.js b/src/js/game/hud/parts/shape_viewer.js index 55feb976..ea4273aa 100644 --- a/src/js/game/hud/parts/shape_viewer.js +++ b/src/js/game/hud/parts/shape_viewer.js @@ -1,133 +1,133 @@ -import { InputReceiver } from "../../../core/input_receiver"; -import { makeDiv, removeAllChildren } from "../../../core/utils"; -import { T } from "../../../translations"; -import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper"; -import { ShapeDefinition } from "../../shape_definition"; -import { BaseHUDPart } from "../base_hud_part"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; - -const copy = require("clipboard-copy"); - -export class HUDShapeViewer extends BaseHUDPart { - createElements(parent) { - this.background = makeDiv(parent, "ingame_HUD_ShapeViewer", ["ingameDialog"]); - - // DIALOG Inner / Wrapper - this.dialogInner = makeDiv(this.background, null, ["dialogInner"]); - this.title = makeDiv(this.dialogInner, null, ["title"], T.ingame.shapeViewer.title); - this.closeButton = makeDiv(this.title, null, ["closeButton"]); - this.trackClicks(this.closeButton, this.close); - this.contentDiv = makeDiv(this.dialogInner, null, ["content"]); - - this.renderArea = makeDiv(this.contentDiv, null, ["renderArea"]); - this.infoArea = makeDiv(this.contentDiv, null, ["infoArea"]); - - // Create button to copy the shape area - this.copyButton = document.createElement("button"); - this.copyButton.classList.add("styledButton", "copyKey"); - this.copyButton.innerText = T.ingame.shapeViewer.copyKey; - this.infoArea.appendChild(this.copyButton); - } - - initialize() { - this.root.hud.signals.viewShapeDetailsRequested.add(this.renderForShape, this); - - this.domAttach = new DynamicDomAttach(this.root, this.background, { - attachClass: "visible", - }); - - this.currentShapeKey = null; - - this.inputReciever = new InputReceiver("shape_viewer"); - this.keyActionMapper = new KeyActionMapper(this.root, this.inputReciever); - - this.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.close, this); - - this.trackClicks(this.copyButton, this.onCopyKeyRequested); - - this.close(); - } - - /** - * Called when the copying of a key was requested - */ - onCopyKeyRequested() { - if (this.currentShapeKey) { - copy(this.currentShapeKey); - this.close(); - } - } - - /** - * Closes the dialog - */ - close() { - this.visible = false; - document.body.classList.remove("ingameDialogOpen"); - this.root.app.inputMgr.makeSureDetached(this.inputReciever); - this.update(); - } - - /** - * Shows the viewer for a given definition - * @param {ShapeDefinition} definition - */ - renderForShape(definition) { - this.visible = true; - document.body.classList.add("ingameDialogOpen"); - this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); - - removeAllChildren(this.renderArea); - - this.currentShapeKey = definition.getHash(); - - const layers = definition.layers; - this.contentDiv.setAttribute("data-layers", layers.length); - - for (let i = 0; i < layers.length; ++i) { - const layerElem = makeDiv(this.renderArea, null, ["layer", "layer-" + i]); - - let fakeLayers = []; - for (let k = 0; k < i; ++k) { - fakeLayers.push([null, null, null, null]); - } - fakeLayers.push(layers[i]); - - const thisLayerOnly = new ShapeDefinition({ layers: fakeLayers }); - const thisLayerCanvas = thisLayerOnly.generateAsCanvas(160); - layerElem.appendChild(thisLayerCanvas); - - for (let quad = 0; quad < 4; ++quad) { - const quadElem = makeDiv(layerElem, null, ["quad", "quad-" + quad]); - - const contents = layers[i][quad]; - if (contents) { - const colorLabelElem = makeDiv( - quadElem, - null, - ["colorLabel"], - T.ingame.colors[contents.color] - ); - } else { - const emptyLabelElem = makeDiv( - quadElem, - null, - ["emptyLabel"], - T.ingame.shapeViewer.empty - ); - } - } - } - } - - /** - * Cleans up everything - */ - cleanup() { - document.body.classList.remove("ingameDialogOpen"); - } - - update() { - this.domAttach.update(this.visible); - } -} +import { InputReceiver } from "../../../core/input_receiver"; +import { makeDiv, removeAllChildren } from "../../../core/utils"; +import { T } from "../../../translations"; +import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper"; +import { ShapeDefinition } from "../../shape_definition"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; + +const copy = require("clipboard-copy"); + +export class HUDShapeViewer extends BaseHUDPart { + createElements(parent) { + this.background = makeDiv(parent, "ingame_HUD_ShapeViewer", ["ingameDialog"]); + + // DIALOG Inner / Wrapper + this.dialogInner = makeDiv(this.background, null, ["dialogInner"]); + this.title = makeDiv(this.dialogInner, null, ["title"], T.ingame.shapeViewer.title); + this.closeButton = makeDiv(this.title, null, ["closeButton"]); + this.trackClicks(this.closeButton, this.close); + this.contentDiv = makeDiv(this.dialogInner, null, ["content"]); + + this.renderArea = makeDiv(this.contentDiv, null, ["renderArea"]); + this.infoArea = makeDiv(this.contentDiv, null, ["infoArea"]); + + // Create button to copy the shape area + this.copyButton = document.createElement("button"); + this.copyButton.classList.add("styledButton", "copyKey"); + this.copyButton.innerText = T.ingame.shapeViewer.copyKey; + this.infoArea.appendChild(this.copyButton); + } + + initialize() { + this.root.hud.signals.viewShapeDetailsRequested.add(this.renderForShape, this); + + this.domAttach = new DynamicDomAttach(this.root, this.background, { + attachClass: "visible", + }); + + this.currentShapeKey = null; + + this.inputReciever = new InputReceiver("shape_viewer"); + this.keyActionMapper = new KeyActionMapper(this.root, this.inputReciever); + + this.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.close, this); + + this.trackClicks(this.copyButton, this.onCopyKeyRequested); + + this.close(); + } + + /** + * Called when the copying of a key was requested + */ + onCopyKeyRequested() { + if (this.currentShapeKey) { + copy(this.currentShapeKey); + this.close(); + } + } + + /** + * Closes the dialog + */ + close() { + this.visible = false; + document.body.classList.remove("ingameDialogOpen"); + this.root.app.inputMgr.makeSureDetached(this.inputReciever); + this.update(); + } + + /** + * Shows the viewer for a given definition + * @param {ShapeDefinition} definition + */ + renderForShape(definition) { + this.visible = true; + document.body.classList.add("ingameDialogOpen"); + this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); + + removeAllChildren(this.renderArea); + + this.currentShapeKey = definition.getHash(); + + const layers = definition.layers; + this.contentDiv.setAttribute("data-layers", layers.length); + + for (let i = layers.length - 1; i >= 0; --i) { + const layerElem = makeDiv(this.renderArea, null, ["layer", "layer-" + i]); + + let fakeLayers = []; + for (let k = 0; k < i; ++k) { + fakeLayers.push([null, null, null, null]); + } + fakeLayers.push(layers[i]); + + const thisLayerOnly = new ShapeDefinition({ layers: fakeLayers }); + const thisLayerCanvas = thisLayerOnly.generateAsCanvas(160); + layerElem.appendChild(thisLayerCanvas); + + for (let quad = 0; quad < 4; ++quad) { + const quadElem = makeDiv(layerElem, null, ["quad", "quad-" + quad]); + + const contents = layers[i][quad]; + if (contents) { + const colorLabelElem = makeDiv( + quadElem, + null, + ["colorLabel"], + T.ingame.colors[contents.color] + ); + } else { + const emptyLabelElem = makeDiv( + quadElem, + null, + ["emptyLabel"], + T.ingame.shapeViewer.empty + ); + } + } + } + } + + /** + * Cleans up everything + */ + cleanup() { + document.body.classList.remove("ingameDialogOpen"); + } + + update() { + this.domAttach.update(this.visible); + } +} diff --git a/src/js/game/hud/parts/statistics.js b/src/js/game/hud/parts/statistics.js index e1a747a2..c5136312 100644 --- a/src/js/game/hud/parts/statistics.js +++ b/src/js/game/hud/parts/statistics.js @@ -1,5 +1,5 @@ import { InputReceiver } from "../../../core/input_receiver"; -import { makeButton, makeDiv, removeAllChildren, capitalizeFirstLetter } from "../../../core/utils"; +import { makeButton, makeDiv, removeAllChildren } from "../../../core/utils"; import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper"; import { enumAnalyticsDataSource } from "../../production_analytics"; import { BaseHUDPart } from "../base_hud_part"; @@ -7,6 +7,14 @@ import { DynamicDomAttach } from "../dynamic_dom_attach"; import { enumDisplayMode, HUDShapeStatisticsHandle } from "./statistics_handle"; import { T } from "../../../translations"; +/** + * Capitalizes the first letter + * @param {string} str + */ +function capitalizeFirstLetter(str) { + return str.substr(0, 1).toUpperCase() + str.substr(1).toLowerCase(); +} + export class HUDStatistics extends BaseHUDPart { createElements(parent) { this.background = makeDiv(parent, "ingame_HUD_Statistics", ["ingameDialog"]); @@ -39,9 +47,11 @@ export class HUDStatistics extends BaseHUDPart { this.trackClicks(button, () => this.setDataSource(dataSource)); } + const buttonDisplaySorted = makeButton(this.filtersDisplayMode, ["displaySorted"]); const buttonDisplayDetailed = makeButton(this.filtersDisplayMode, ["displayDetailed"]); const buttonDisplayIcons = makeButton(this.filtersDisplayMode, ["displayIcons"]); + this.trackClicks(buttonDisplaySorted, () => this.toggleSorted()); this.trackClicks(buttonDisplayIcons, () => this.setDisplayMode(enumDisplayMode.icons)); this.trackClicks(buttonDisplayDetailed, () => this.setDisplayMode(enumDisplayMode.detailed)); @@ -72,6 +82,21 @@ export class HUDStatistics extends BaseHUDPart { } } + /** + * @param {boolean} sorted + */ + setSorted(sorted) { + this.sorted = sorted; + this.dialogInner.setAttribute("data-sorted", String(sorted)); + if (this.visible) { + this.rerenderFull(); + } + } + + toggleSorted() { + this.setSorted(!this.sorted); + } + initialize() { this.domAttach = new DynamicDomAttach(this.root, this.background, { attachClass: "visible", @@ -87,6 +112,7 @@ export class HUDStatistics extends BaseHUDPart { /** @type {Object.} */ this.activeHandles = {}; + this.setSorted(true); this.setDataSource(enumAnalyticsDataSource.produced); this.setDisplayMode(enumDisplayMode.detailed); @@ -175,7 +201,22 @@ export class HUDStatistics extends BaseHUDPart { } } - entries.sort((a, b) => b[1] - a[1]); + const pinnedShapes = this.root.hud.parts.pinnedShapes; + + entries.sort((a, b) => { + const aPinned = pinnedShapes.isShapePinned(a[0]); + const bPinned = pinnedShapes.isShapePinned(b[0]); + + if (aPinned !== bPinned) { + return aPinned ? -1 : 1; + } + + // Sort by shape key for some consistency + if (!this.sorted || b[1] == a[1]) { + return b[0].localeCompare(a[0]); + } + return b[1] - a[1]; + }); let rendered = new Set(); diff --git a/src/js/game/hud/parts/statistics_handle.js b/src/js/game/hud/parts/statistics_handle.js index d5c60d3b..6f49f8d3 100644 --- a/src/js/game/hud/parts/statistics_handle.js +++ b/src/js/game/hud/parts/statistics_handle.js @@ -74,6 +74,11 @@ export class HUDShapeStatisticsHandle { return; } + this.element.classList.toggle( + "pinned", + this.root.hud.parts.pinnedShapes.isShapePinned(this.definition.getHash()) + ); + switch (dataSource) { case enumAnalyticsDataSource.stored: { this.counter.innerText = formatBigNumber( @@ -87,15 +92,10 @@ export class HUDShapeStatisticsHandle { (this.root.productionAnalytics.getCurrentShapeRate(dataSource, this.definition) / globalConfig.analyticsSliceDurationSeconds) * 60; - this.counter.innerText = T.ingame.statistics.shapesPerMinute.replace( + this.counter.innerText = T.ingame.statistics.shapesPerSecond.replace( "", - formatBigNumber(rate) + formatBigNumber(rate / 60) ); - - if (G_IS_DEV && globalConfig.debug.detailedStatistics) { - this.counter.innerText = "" + round2Digits(rate / 60) + " /s"; - } - break; } } diff --git a/src/js/game/hud/parts/waypoints.js b/src/js/game/hud/parts/waypoints.js index 8cab85c5..abf05b1f 100644 --- a/src/js/game/hud/parts/waypoints.js +++ b/src/js/game/hud/parts/waypoints.js @@ -15,6 +15,8 @@ import { BaseHUDPart } from "../base_hud_part"; import { DynamicDomAttach } from "../dynamic_dom_attach"; import { enumNotificationType } from "./notifications"; import { ShapeDefinition } from "../../shape_definition"; +import { BaseItem } from "../../base_item"; +import { ShapeItem } from "../../items/shape_item"; /** @typedef {{ * label: string | null, @@ -25,8 +27,6 @@ import { ShapeDefinition } from "../../shape_definition"; /** * Used when a shape icon is rendered instead */ -const SHAPE_LABEL_PLACEHOLDER = " "; - const MAX_LABEL_LENGTH = 71; export class HUDWaypoints extends BaseHUDPart { @@ -133,10 +133,44 @@ export class HUDWaypoints extends BaseHUDPart { */ this.cachedKeyToCanvas = {}; + /** + * Store cached text widths + * @type {Object} + */ + this.cachedTextWidths = {}; + // Initial render this.rerenderWaypointList(); } + /** + * Returns how long a text will be rendered + * @param {string} text + * @returns {number} + */ + getTextWidth(text) { + if (this.cachedTextWidths[text]) { + return this.cachedTextWidths[text]; + } + + this.dummyBuffer.font = "bold " + this.getTextScale() + "px GameFont"; + return (this.cachedTextWidths[text] = this.dummyBuffer.measureText(text).width); + } + + /** + * Returns how big the text should be rendered + */ + getTextScale() { + return this.getWaypointUiScale() * 12; + } + + /** + * Returns the scale for rendering waypoints + */ + getWaypointUiScale() { + return this.root.app.getEffectiveUiScale(); + } + /** * Re-renders the waypoint list to account for changes */ @@ -214,7 +248,7 @@ export class HUDWaypoints extends BaseHUDPart { } assert(ShapeDefinition.isValidShortKey(key), "Invalid short key: " + key); - const definition = ShapeDefinition.fromShortKey(key); + const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey(key); const preRendered = definition.generateAsCanvas(48); return (this.cachedKeyToCanvas[key] = preRendered); } @@ -367,6 +401,51 @@ export class HUDWaypoints extends BaseHUDPart { return waypoint.label !== null; } + /** + * Returns the screen space bounds of the given waypoint or null + * if it couldn't be determined. Also returns wheter its a shape or not + * @param {Waypoint} waypoint + * @return {{ + * screenBounds: Rectangle + * item: BaseItem|null, + * text: string + * }} + */ + getWaypointScreenParams(waypoint) { + if (!this.root.camera.getIsMapOverlayActive()) { + return null; + } + + // Find parameters + const scale = this.getWaypointUiScale(); + const screenPos = this.root.camera.worldToScreen(new Vector(waypoint.center.x, waypoint.center.y)); + + // Distinguish between text and item waypoints -> Figure out parameters + const originalLabel = this.getWaypointLabel(waypoint); + let text, item, textWidth; + + if (ShapeDefinition.isValidShortKey(originalLabel)) { + // If the label is actually a key, render the shape icon + item = this.root.shapeDefinitionMgr.getShapeItemFromShortKey(originalLabel); + textWidth = 40; + } else { + // Otherwise render a regular waypoint + text = originalLabel; + textWidth = this.getTextWidth(text); + } + + return { + screenBounds: new Rectangle( + screenPos.x - 7 * scale, + screenPos.y - 12 * scale, + 15 * scale + textWidth, + 15 * scale + ), + item, + text, + }; + } + /** * Finds the currently intersected waypoint on the map overview under * the cursor. @@ -379,34 +458,10 @@ export class HUDWaypoints extends BaseHUDPart { return; } - if (!this.root.camera.getIsMapOverlayActive()) { - return; - } - - const scale = this.root.app.getEffectiveUiScale(); - - this.dummyBuffer.font = "bold " + 12 * scale + "px GameFont"; - for (let i = 0; i < this.waypoints.length; ++i) { const waypoint = this.waypoints[i]; - const screenPos = this.root.camera.worldToScreen( - new Vector(waypoint.center.x, waypoint.center.y) - ); - - let label = this.getWaypointLabel(waypoint); - - // Special case for icons - if (ShapeDefinition.isValidShortKey(label)) { - label = SHAPE_LABEL_PLACEHOLDER; - } - - const intersectionRect = new Rectangle( - screenPos.x - 7 * scale, - screenPos.y - 12 * scale, - 15 * scale + this.dummyBuffer.measureText(label).width, - 15 * scale - ); - if (intersectionRect.containsPoint(mousePos.x, mousePos.y)) { + const params = this.getWaypointScreenParams(waypoint); + if (params && params.screenBounds.containsPoint(mousePos.x, mousePos.y)) { return waypoint; } } @@ -449,18 +504,21 @@ export class HUDWaypoints extends BaseHUDPart { * Rerenders the compass */ rerenderWaypointsCompass() { - const context = this.compassBuffer.context; const dims = 48; - context.clearRect(0, 0, dims, dims); const indicatorSize = 30; - const cameraPos = this.root.camera.center; + const context = this.compassBuffer.context; + context.clearRect(0, 0, dims, dims); + const distanceToHub = cameraPos.length(); const compassVisible = distanceToHub > (10 * globalConfig.tileSize) / this.root.camera.zoomLevel; const targetCompassAlpha = compassVisible ? 1 : 0; + + // Fade the compas in / out this.currentCompassOpacity = lerp(this.currentCompassOpacity, targetCompassAlpha, 0.08); + // Render the compass if (this.currentCompassOpacity > 0.01) { context.globalAlpha = this.currentCompassOpacity; const angle = cameraPos.angle() + Math.radians(45) + Math.PI / 2; @@ -472,9 +530,9 @@ export class HUDWaypoints extends BaseHUDPart { context.globalAlpha = 1; } + // Render the regualr icon const iconOpacity = 1 - this.currentCompassOpacity; if (iconOpacity > 0.01) { - // Draw icon context.globalAlpha = iconOpacity; this.waypointSprite.drawCentered(context, dims / 2, dims / 2, dims * 0.7); context.globalAlpha = 1; @@ -485,7 +543,8 @@ export class HUDWaypoints extends BaseHUDPart { * Draws the waypoints on the map * @param {DrawParameters} parameters */ - draw(parameters) { + drawOverlays(parameters) { + const mousePos = this.root.app.mousePosition; const desiredOpacity = this.root.camera.getIsMapOverlayActive() ? 1 : 0; this.currentMarkerOpacity = lerp(this.currentMarkerOpacity, desiredOpacity, 0.08); @@ -496,61 +555,73 @@ export class HUDWaypoints extends BaseHUDPart { return; } - // Find waypoint below cursor - const selected = this.findCurrentIntersectedWaypoint(); - // Determine rendering scale - const scale = (1 / this.root.camera.zoomLevel) * this.root.app.getEffectiveUiScale(); + const scale = this.getWaypointUiScale(); - // Render all of 'em + // Set the font size + const textSize = this.getTextScale(); + parameters.context.font = "bold " + textSize + "px GameFont"; + parameters.context.textBaseline = "middle"; + + // Loop over all waypoints for (let i = 0; i < this.waypoints.length; ++i) { const waypoint = this.waypoints[i]; - const pos = waypoint.center; - parameters.context.globalAlpha = this.currentMarkerOpacity * (selected === waypoint ? 1 : 0.7); - - const yOffset = -5 * scale; - const originalLabel = this.getWaypointLabel(waypoint); - let renderLabel = originalLabel; - let isShapeIcon = false; - - if (ShapeDefinition.isValidShortKey(originalLabel)) { - renderLabel = SHAPE_LABEL_PLACEHOLDER; - isShapeIcon = true; + const waypointData = this.getWaypointScreenParams(waypoint); + if (!waypointData) { + // Not relevant + continue; } + if (!parameters.visibleRect.containsRect(waypointData.screenBounds)) { + // Out of screen + continue; + } + + const bounds = waypointData.screenBounds; + const contentPaddingX = 7 * scale; + const isSelected = mousePos && bounds.containsPoint(mousePos.x, mousePos.y); + // Render the background rectangle - parameters.context.font = "bold " + 12 * scale + "px GameFont"; + parameters.context.globalAlpha = this.currentMarkerOpacity * (isSelected ? 1 : 0.7); parameters.context.fillStyle = "rgba(255, 255, 255, 0.7)"; - parameters.context.fillRect( - pos.x - 7 * scale, - pos.y - 12 * scale, - 15 * scale + this.dummyBuffer.measureText(renderLabel).width / this.root.camera.zoomLevel, - 15 * scale - ); + parameters.context.fillRect(bounds.x, bounds.y, bounds.w, bounds.h); // Render the text - if (isShapeIcon) { + if (waypointData.item) { const canvas = this.getWaypointCanvas(waypoint); + const itemSize = 14 * scale; parameters.context.drawImage( canvas, - pos.x + 6 * scale, - pos.y - 11.5 * scale, - 14 * scale, - 14 * scale + bounds.x + contentPaddingX + 6 * scale, + bounds.y + bounds.h / 2 - itemSize / 2, + itemSize, + itemSize ); - } else { + } else if (waypointData.text) { // Render the text parameters.context.fillStyle = "#000"; parameters.context.textBaseline = "middle"; - parameters.context.fillText(renderLabel, pos.x + 6 * scale, pos.y + 0.5 * scale + yOffset); + parameters.context.fillText( + waypointData.text, + bounds.x + contentPaddingX + 6 * scale, + bounds.y + bounds.h / 2 + ); parameters.context.textBaseline = "alphabetic"; + } else { + assertAlways(false, "Waypoint has no item and text"); } // Render the small icon on the left - this.waypointSprite.drawCentered(parameters.context, pos.x, pos.y + yOffset, 10 * scale); + this.waypointSprite.drawCentered( + parameters.context, + bounds.x + contentPaddingX, + bounds.y + bounds.h / 2, + bounds.h * 0.7 + ); } + parameters.context.textBaseline = "alphabetic"; parameters.context.globalAlpha = 1; } } diff --git a/src/js/game/hud/parts/wire_info.js b/src/js/game/hud/parts/wire_info.js new file mode 100644 index 00000000..9394dcc2 --- /dev/null +++ b/src/js/game/hud/parts/wire_info.js @@ -0,0 +1,119 @@ +import { globalConfig } from "../../../core/config"; +import { MapChunkView } from "../../map_chunk_view"; +import { WireNetwork } from "../../systems/wire"; +import { THEME } from "../../theme"; +import { BaseHUDPart } from "../base_hud_part"; +import { Loader } from "../../../core/loader"; + +export class HUDWireInfo extends BaseHUDPart { + initialize() { + this.spriteEmpty = Loader.getSprite("sprites/wires/network_empty.png"); + this.spriteConflict = Loader.getSprite("sprites/wires/network_conflict.png"); + } + + /** + * + * @param {import("../../../core/draw_utils").DrawParameters} parameters + */ + drawOverlays(parameters) { + if (this.root.currentLayer !== "wires") { + // Not in the wires layer + return; + } + + const mousePos = this.root.app.mousePosition; + if (!mousePos) { + // No mouse + return; + } + + const worldPos = this.root.camera.screenToWorld(mousePos); + const tile = worldPos.toTileSpace(); + const entity = this.root.map.getLayerContentXY(tile.x, tile.y, "wires"); + + if (!entity) { + // No entity + return; + } + + if ( + !this.root.camera.getIsMapOverlayActive() && + !this.root.logic.getIsEntityIntersectedWithMatrix(entity, worldPos) + ) { + // Detailed intersection check + return; + } + + const networks = this.root.logic.getEntityWireNetworks(entity, tile); + if (networks === null) { + // This entity will never be able to be connected + return; + } + + if (networks.length === 0) { + // No network at all + return; + } + + for (let i = 0; i < networks.length; ++i) { + const network = networks[i]; + this.drawHighlightedNetwork(parameters, network); + } + + if (networks.length === 1) { + const network = networks[0]; + + if (network.valueConflict) { + this.spriteConflict.draw(parameters.context, mousePos.x + 15, mousePos.y - 10, 60, 60); + } else if (!network.currentValue) { + this.spriteEmpty.draw(parameters.context, mousePos.x + 15, mousePos.y - 10, 60, 60); + } else { + network.currentValue.drawItemCenteredClipped( + mousePos.x + 40, + mousePos.y + 10, + parameters, + 60 + ); + } + } + } + + /** + * + * + * @param {import("../../../core/draw_utils").DrawParameters} parameters + * @param {WireNetwork} network + */ + drawHighlightedNetwork(parameters, network) { + parameters.context.globalAlpha = 0.5; + + for (let i = 0; i < network.wires.length; ++i) { + const wire = network.wires[i]; + const staticComp = wire.components.StaticMapEntity; + const screenTile = this.root.camera.worldToScreen(staticComp.origin.toWorldSpace()); + MapChunkView.drawSingleWiresOverviewTile({ + context: parameters.context, + x: screenTile.x, + y: screenTile.y, + entity: wire, + tileSizePixels: globalConfig.tileSize * this.root.camera.zoomLevel, + overrideColor: THEME.map.wires.highlightColor, + }); + } + + for (let i = 0; i < network.tunnels.length; ++i) { + const tunnel = network.tunnels[i]; + const staticComp = tunnel.components.StaticMapEntity; + const screenTile = this.root.camera.worldToScreen(staticComp.origin.toWorldSpace()); + MapChunkView.drawSingleWiresOverviewTile({ + context: parameters.context, + x: screenTile.x, + y: screenTile.y, + entity: tunnel, + tileSizePixels: globalConfig.tileSize * this.root.camera.zoomLevel, + overrideColor: THEME.map.wires.highlightColor, + }); + } + parameters.context.globalAlpha = 1; + } +} diff --git a/src/js/game/hud/parts/wires_overlay.js b/src/js/game/hud/parts/wires_overlay.js index 8bda5d0d..8d1d213e 100644 --- a/src/js/game/hud/parts/wires_overlay.js +++ b/src/js/game/hud/parts/wires_overlay.js @@ -1,97 +1,92 @@ -import { makeOffscreenBuffer } from "../../../core/buffer_utils"; -import { globalConfig } from "../../../core/config"; -import { DrawParameters } from "../../../core/draw_parameters"; -import { KEYMAPPINGS } from "../../key_action_mapper"; -import { enumLayer } from "../../root"; -import { THEME } from "../../theme"; -import { BaseHUDPart } from "../base_hud_part"; -import { Loader } from "../../../core/loader"; -import { lerp } from "../../../core/utils"; - -const wiresBackgroundDpi = 4; - -export class HUDWiresOverlay extends BaseHUDPart { - createElements(parent) {} - - initialize() { - // Probably not the best location, but the one which makes most sense - this.root.keyMapper.getBinding(KEYMAPPINGS.ingame.switchLayers).add(this.switchLayers, this); - - this.generateTilePattern(); - - this.currentAlpha = 0.0; - } - - /** - * Switches between layers - */ - switchLayers() { - if (this.root.currentLayer === enumLayer.regular) { - this.root.currentLayer = enumLayer.wires; - } else { - this.root.currentLayer = enumLayer.regular; - } - this.root.signals.editModeChanged.dispatch(this.root.currentLayer); - } - - /** - * Generates the background pattern for the wires overlay - */ - generateTilePattern() { - const overlayTile = Loader.getSprite("sprites/misc/wires_overlay_tile.png"); - const dims = globalConfig.tileSize * wiresBackgroundDpi; - const [canvas, context] = makeOffscreenBuffer(dims, dims, { - smooth: false, - reusable: false, - label: "wires-tile-pattern", - }); - overlayTile.draw(context, 0, 0, dims, dims); - this.tilePatternCanvas = canvas; - } - - update() { - const desiredAlpha = this.root.currentLayer === enumLayer.wires ? 1.0 : 0.0; - this.currentAlpha = lerp(this.currentAlpha, desiredAlpha, 0.12); - } - - /** - * - * @param {DrawParameters} parameters - */ - draw(parameters) { - if (this.currentAlpha < 0.02) { - return; - } - - if (this.root.camera.getIsMapOverlayActive()) { - return; - } - - if (!this.cachedPatternBackground) { - this.cachedPatternBackground = parameters.context.createPattern(this.tilePatternCanvas, "repeat"); - } - - const bounds = parameters.visibleRect; - - const scaleFactor = 1 / wiresBackgroundDpi; - - parameters.context.globalAlpha = 0.9 * this.currentAlpha; - parameters.context.globalCompositeOperation = "darken"; - parameters.context.scale(scaleFactor, scaleFactor); - parameters.context.fillStyle = this.cachedPatternBackground; - parameters.context.fillRect( - bounds.x / scaleFactor, - bounds.y / scaleFactor, - bounds.w / scaleFactor, - bounds.h / scaleFactor - ); - parameters.context.scale(1 / scaleFactor, 1 / scaleFactor); - parameters.context.globalCompositeOperation = "source-over"; - parameters.context.globalAlpha = 1; - - // parameters.context.fillStyle = "#3a85bf"; - // parameters.context.globalAlpha = 0.0 * this.currentAlpha; - // parameters.context.fillRect(bounds.x, bounds.y, bounds.w, bounds.h); - // parameters.context.globalAlpha = 1; - } -} +import { makeOffscreenBuffer } from "../../../core/buffer_utils"; +import { globalConfig } from "../../../core/config"; +import { DrawParameters } from "../../../core/draw_parameters"; +import { KEYMAPPINGS } from "../../key_action_mapper"; +import { THEME } from "../../theme"; +import { BaseHUDPart } from "../base_hud_part"; +import { Loader } from "../../../core/loader"; +import { lerp } from "../../../core/utils"; + +const wiresBackgroundDpi = 4; + +export class HUDWiresOverlay extends BaseHUDPart { + createElements(parent) {} + + initialize() { + // Probably not the best location, but the one which makes most sense + this.root.keyMapper.getBinding(KEYMAPPINGS.ingame.switchLayers).add(this.switchLayers, this); + + this.generateTilePattern(); + + this.currentAlpha = 0.0; + } + + /** + * Switches between layers + */ + switchLayers() { + if (this.root.currentLayer === "regular") { + this.root.currentLayer = "wires"; + } else { + this.root.currentLayer = "regular"; + } + this.root.signals.editModeChanged.dispatch(this.root.currentLayer); + } + + /** + * Generates the background pattern for the wires overlay + */ + generateTilePattern() { + const overlayTile = Loader.getSprite("sprites/wires/overlay_tile.png"); + const dims = globalConfig.tileSize * wiresBackgroundDpi; + const [canvas, context] = makeOffscreenBuffer(dims, dims, { + smooth: false, + reusable: false, + label: "wires-tile-pattern", + }); + context.clearRect(0, 0, dims, dims); + overlayTile.draw(context, 0, 0, dims, dims); + this.tilePatternCanvas = canvas; + } + + update() { + const desiredAlpha = this.root.currentLayer === "wires" ? 1.0 : 0.0; + this.currentAlpha = lerp(this.currentAlpha, desiredAlpha, 0.12); + } + + /** + * + * @param {DrawParameters} parameters + */ + draw(parameters) { + if (this.currentAlpha < 0.02) { + return; + } + + if (!this.cachedPatternBackground) { + this.cachedPatternBackground = parameters.context.createPattern(this.tilePatternCanvas, "repeat"); + } + + const bounds = parameters.visibleRect; + + parameters.context.globalAlpha = this.currentAlpha; + + const scaleFactor = 1 / wiresBackgroundDpi; + parameters.context.globalCompositeOperation = "overlay"; + parameters.context.fillStyle = "rgba(50, 200, 150, 1)"; + parameters.context.fillRect(bounds.x, bounds.y, bounds.w, bounds.h); + parameters.context.globalCompositeOperation = "source-over"; + + parameters.context.scale(scaleFactor, scaleFactor); + parameters.context.fillStyle = this.cachedPatternBackground; + parameters.context.fillRect( + bounds.x / scaleFactor, + bounds.y / scaleFactor, + bounds.w / scaleFactor, + bounds.h / scaleFactor + ); + parameters.context.scale(1 / scaleFactor, 1 / scaleFactor); + + parameters.context.globalAlpha = 1; + } +} diff --git a/src/js/game/hud/parts/wires_toolbar.js b/src/js/game/hud/parts/wires_toolbar.js index 6ebc0a98..af5a31dd 100644 --- a/src/js/game/hud/parts/wires_toolbar.js +++ b/src/js/game/hud/parts/wires_toolbar.js @@ -1,17 +1,27 @@ -import { MetaWireBaseBuilding } from "../../buildings/wire_base"; -import { enumLayer } from "../../root"; -import { HUDBaseToolbar } from "./base_toolbar"; -import { MetaWireCrossingsBuilding } from "../../buildings/wire_crossings"; - -const supportedBuildings = [MetaWireBaseBuilding, MetaWireCrossingsBuilding]; - -export class HUDWiresToolbar extends HUDBaseToolbar { - constructor(root) { - super(root, { - supportedBuildings, - visibilityCondition: () => - !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === enumLayer.wires, - htmlElementId: "ingame_HUD_wires_toolbar", - }); - } -} +import { HUDBaseToolbar } from "./base_toolbar"; +import { MetaWireBuilding } from "../../buildings/wire"; +import { MetaConstantSignalBuilding } from "../../buildings/constant_signal"; +import { MetaLogicGateBuilding } from "../../buildings/logic_gate"; +import { MetaLeverBuilding } from "../../buildings/lever"; +import { MetaWireTunnelBuilding } from "../../buildings/wire_tunnel"; +import { MetaVirtualProcessorBuilding } from "../../buildings/virtual_processor"; + +const supportedBuildings = [ + MetaWireBuilding, + MetaWireTunnelBuilding, + MetaConstantSignalBuilding, + MetaLogicGateBuilding, + MetaLeverBuilding, + MetaVirtualProcessorBuilding, +]; + +export class HUDWiresToolbar extends HUDBaseToolbar { + constructor(root) { + super(root, { + supportedBuildings, + visibilityCondition: () => + !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "wires", + htmlElementId: "ingame_HUD_wires_toolbar", + }); + } +} diff --git a/src/js/game/hud/trailer_maker.js b/src/js/game/hud/trailer_maker.js index 2834b40d..8655def4 100644 --- a/src/js/game/hud/trailer_maker.js +++ b/src/js/game/hud/trailer_maker.js @@ -1,4 +1,4 @@ -import { GameRoot, enumLayer } from "../root"; +import { GameRoot } from "../root"; import { globalConfig } from "../../core/config"; import { Vector, mixVector } from "../../core/vector"; import { lerp } from "../../core/utils"; @@ -92,7 +92,7 @@ export class TrailerMaker { const speed = globalConfig.tileSize * globalConfig.beltSpeedItemsPerSecond * - globalConfig.beltItemSpacingByLayer[enumLayer.regular]; + globalConfig.itemSpacingOnBelts; // let time = // this.currentPlaybackOrigin.distance(Vector.fromSerializedObject(nextMarker.pos)) / speed; const time = nextMarker.time; diff --git a/src/js/game/item_registry.js b/src/js/game/item_registry.js index d483119f..e6207ea3 100644 --- a/src/js/game/item_registry.js +++ b/src/js/game/item_registry.js @@ -1,12 +1,10 @@ import { gItemRegistry } from "../core/global_registries"; import { ShapeItem } from "./items/shape_item"; import { ColorItem } from "./items/color_item"; -import { PositiveEnergyItem } from "./items/positive_energy_item"; -import { NegativeEnergyItem } from "./items/negative_energy_item"; +import { BooleanItem } from "./items/boolean_item"; export function initItemRegistry() { gItemRegistry.register(ShapeItem); gItemRegistry.register(ColorItem); - gItemRegistry.register(PositiveEnergyItem); - gItemRegistry.register(NegativeEnergyItem); + gItemRegistry.register(BooleanItem); } diff --git a/src/js/game/item_resolver.js b/src/js/game/item_resolver.js new file mode 100644 index 00000000..da15fa0c --- /dev/null +++ b/src/js/game/item_resolver.js @@ -0,0 +1,33 @@ +import { types } from "../savegame/serialization"; +import { gItemRegistry } from "../core/global_registries"; +import { BooleanItem, BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON } from "./items/boolean_item"; +import { ShapeItem } from "./items/shape_item"; +import { ColorItem, COLOR_ITEM_SINGLETONS } from "./items/color_item"; + +/** + * Resolves items so we share instances + * @param {import("../savegame/savegame_serializer").GameRoot} root + * @param {{$: string, data: any }} data + */ +export function itemResolverSingleton(root, data) { + const itemType = data.$; + const itemData = data.data; + + switch (itemType) { + case BooleanItem.getId(): { + return itemData ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON; + } + case ShapeItem.getId(): { + return root.shapeDefinitionMgr.getShapeItemFromShortKey(itemData); + } + case ColorItem.getId(): { + return COLOR_ITEM_SINGLETONS[itemData]; + } + + default: { + assertAlways(false, "Unknown item type: " + itemType); + } + } +} + +export const typeItemSingleton = types.obj(gItemRegistry, itemResolverSingleton); diff --git a/src/js/game/items/boolean_item.js b/src/js/game/items/boolean_item.js new file mode 100644 index 00000000..77e8bbb3 --- /dev/null +++ b/src/js/game/items/boolean_item.js @@ -0,0 +1,88 @@ +import { DrawParameters } from "../../core/draw_parameters"; +import { Loader } from "../../core/loader"; +import { types } from "../../savegame/serialization"; +import { BaseItem } from "../base_item"; +import { globalConfig } from "../../core/config"; + +export class BooleanItem extends BaseItem { + static getId() { + return "boolean_item"; + } + + static getSchema() { + return types.uint; + } + + serialize() { + return this.value; + } + + deserialize(data) { + this.value = data; + } + + /** @returns {"boolean"} **/ + getItemType() { + return "boolean"; + } + + /** + * @param {number} value + */ + constructor(value) { + super(); + this.value = value ? 1 : 0; + } + + /** + * @param {BaseItem} other + */ + equalsImpl(other) { + return this.value === /** @type {BooleanItem} */ (other).value; + } + + /** + * @param {number} x + * @param {number} y + * @param {number} diameter + * @param {DrawParameters} parameters + */ + drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) { + let sprite; + if (this.value) { + sprite = Loader.getSprite("sprites/wires/boolean_true.png"); + } else { + sprite = Loader.getSprite("sprites/wires/boolean_false.png"); + } + sprite.drawCachedCentered(parameters, x, y, diameter); + } +} + +export const BOOL_FALSE_SINGLETON = new BooleanItem(0); +export const BOOL_TRUE_SINGLETON = new BooleanItem(1); + +/** + * Returns whether the item is Boolean and TRUE + * @param {BaseItem} item + * @returns {boolean} + */ +export function isTrueItem(item) { + return item && item.getItemType() === "boolean" && !!(/** @type {BooleanItem} */ (item).value); +} + +/** + * Returns whether the item is truthy + * @param {BaseItem} item + * @returns {boolean} + */ +export function isTruthyItem(item) { + if (!item) { + return false; + } + + if (item.getItemType() === "boolean") { + return !!(/** @type {BooleanItem} */ (item).value); + } + + return true; +} diff --git a/src/js/game/items/color_item.js b/src/js/game/items/color_item.js index d1b9a217..19d26286 100644 --- a/src/js/game/items/color_item.js +++ b/src/js/game/items/color_item.js @@ -2,9 +2,10 @@ import { globalConfig } from "../../core/config"; import { smoothenDpi } from "../../core/dpi_manager"; import { DrawParameters } from "../../core/draw_parameters"; import { types } from "../../savegame/serialization"; -import { BaseItem, enumItemType } from "../base_item"; +import { BaseItem } from "../base_item"; import { enumColors, enumColorsToHexCode } from "../colors"; import { THEME } from "../theme"; +import { drawSpriteClipped } from "../../core/draw_utils"; export class ColorItem extends BaseItem { static getId() { @@ -23,8 +24,16 @@ export class ColorItem extends BaseItem { this.color = data; } + /** @returns {"color"} **/ getItemType() { - return enumItemType.color; + return "color"; + } + + /** + * @param {BaseItem} other + */ + equalsImpl(other) { + return this.color === /** @type {ColorItem} */ (other).color; } /** @@ -43,26 +52,36 @@ export class ColorItem extends BaseItem { /** * @param {number} x * @param {number} y - * @param {number} size + * @param {number} diameter * @param {DrawParameters} parameters */ - draw(x, y, parameters, size = 12) { + drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) { if (!this.bufferGenerator) { this.bufferGenerator = this.internalGenerateColorBuffer.bind(this); } + const realDiameter = diameter * 0.6; const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel); - - const key = size + "/" + dpi; - const canvas = parameters.root.buffers.getForKey( - key, - this.color, - size, - size, + const key = realDiameter + "/" + dpi + "/" + this.color; + const canvas = parameters.root.buffers.getForKey({ + key: "coloritem", + subKey: key, + w: realDiameter, + h: realDiameter, dpi, - this.bufferGenerator - ); - parameters.context.drawImage(canvas, x - size / 2, y - size / 2, size, size); + redrawMethod: this.bufferGenerator, + }); + + drawSpriteClipped({ + parameters, + sprite: canvas, + x: x - realDiameter / 2, + y: y - realDiameter / 2, + w: realDiameter, + h: realDiameter, + originalW: realDiameter * dpi, + originalH: realDiameter * dpi, + }); } /** * @@ -91,3 +110,13 @@ export class ColorItem extends BaseItem { context.fill(); } } + +/** + * Singleton instances + * @type {Object} + */ +export const COLOR_ITEM_SINGLETONS = {}; + +for (const color in enumColors) { + COLOR_ITEM_SINGLETONS[color] = new ColorItem(color); +} diff --git a/src/js/game/items/negative_energy_item.js b/src/js/game/items/negative_energy_item.js deleted file mode 100644 index 99e2cd06..00000000 --- a/src/js/game/items/negative_energy_item.js +++ /dev/null @@ -1,37 +0,0 @@ -import { DrawParameters } from "../../core/draw_parameters"; -import { Loader } from "../../core/loader"; -import { types } from "../../savegame/serialization"; -import { BaseItem, enumItemType } from "../base_item"; - -export class NegativeEnergyItem extends BaseItem { - static getId() { - return "negative_energy"; - } - - static getSchema() { - return types.uint; - } - - serialize() { - return 0; - } - - deserialize(data) {} - - getItemType() { - return enumItemType.negativeEnergy; - } - - /** - * @param {number} x - * @param {number} y - * @param {number} size - * @param {DrawParameters} parameters - */ - draw(x, y, parameters, size = 12) { - const sprite = Loader.getSprite("sprites/wires/negative_energy.png"); - sprite.drawCachedCentered(parameters, x, y, size * 1.5); - } -} - -export const NEGATIVE_ENERGY_ITEM_SINGLETON = new NegativeEnergyItem(); diff --git a/src/js/game/items/positive_energy_item.js b/src/js/game/items/positive_energy_item.js deleted file mode 100644 index 260ae149..00000000 --- a/src/js/game/items/positive_energy_item.js +++ /dev/null @@ -1,37 +0,0 @@ -import { DrawParameters } from "../../core/draw_parameters"; -import { Loader } from "../../core/loader"; -import { types } from "../../savegame/serialization"; -import { BaseItem, enumItemType } from "../base_item"; - -export class PositiveEnergyItem extends BaseItem { - static getId() { - return "positive_energy"; - } - - static getSchema() { - return types.uint; - } - - serialize() { - return 0; - } - - deserialize(data) {} - - getItemType() { - return enumItemType.positiveEnergy; - } - - /** - * @param {number} x - * @param {number} y - * @param {number} size - * @param {DrawParameters} parameters - */ - draw(x, y, parameters, size = 12) { - const sprite = Loader.getSprite("sprites/wires/positive_energy.png"); - sprite.drawCachedCentered(parameters, x, y, size * 1.5); - } -} - -export const POSITIVE_ENERGY_ITEM_SINGLETON = new PositiveEnergyItem(); diff --git a/src/js/game/items/shape_item.js b/src/js/game/items/shape_item.js index 2aca63f6..d99a7251 100644 --- a/src/js/game/items/shape_item.js +++ b/src/js/game/items/shape_item.js @@ -1,8 +1,9 @@ import { DrawParameters } from "../../core/draw_parameters"; import { types } from "../../savegame/serialization"; -import { BaseItem, enumItemType } from "../base_item"; +import { BaseItem } from "../base_item"; import { ShapeDefinition } from "../shape_definition"; import { THEME } from "../theme"; +import { globalConfig } from "../../core/config"; export class ShapeItem extends BaseItem { static getId() { @@ -21,8 +22,16 @@ export class ShapeItem extends BaseItem { this.definition = ShapeDefinition.fromShortKey(data); } + /** @returns {"shape"} **/ getItemType() { - return enumItemType.shape; + return "shape"; + } + + /** + * @param {BaseItem} other + */ + equalsImpl(other) { + return this.definition.getHash() === /** @type {ShapeItem} */ (other).definition.getHash(); } /** @@ -30,7 +39,6 @@ export class ShapeItem extends BaseItem { */ constructor(definition) { super(); - // logger.log("New shape item for shape definition", definition.generateId(), "created"); /** * This property must not be modified on runtime, you have to clone the class in order to change the definition @@ -46,9 +54,9 @@ export class ShapeItem extends BaseItem { * @param {number} x * @param {number} y * @param {DrawParameters} parameters - * @param {number=} size + * @param {number=} diameter */ - draw(x, y, parameters, size) { - this.definition.draw(x, y, parameters, size); + drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) { + this.definition.drawCentered(x, y, parameters, diameter); } } diff --git a/src/js/game/key_action_mapper.js b/src/js/game/key_action_mapper.js index 2dfc5bb1..d5a758a5 100644 --- a/src/js/game/key_action_mapper.js +++ b/src/js/game/key_action_mapper.js @@ -1,453 +1,458 @@ -/* typehints:start */ -import { GameRoot } from "./root"; -import { InputReceiver } from "../core/input_receiver"; -import { Application } from "../application"; -/* typehints:end */ - -import { Signal, STOP_PROPAGATION } from "../core/signal"; -import { IS_MOBILE } from "../core/config"; -import { T } from "../translations"; -function key(str) { - return str.toUpperCase().charCodeAt(0); -} - -export const KEYMAPPINGS = { - general: { - confirm: { keyCode: 13 }, // enter - back: { keyCode: 27, builtin: true }, // escape - }, - - ingame: { - menuOpenShop: { keyCode: key("F") }, - menuOpenStats: { keyCode: key("G") }, - menuClose: { keyCode: key("Q") }, - - toggleHud: { keyCode: 113 }, // F2 - exportScreenshot: { keyCode: 114 }, // F3PS - toggleFPSInfo: { keyCode: 115 }, // F4 - - switchLayers: { keyCode: key("Y") }, - }, - - navigation: { - mapMoveUp: { keyCode: key("W") }, - mapMoveRight: { keyCode: key("D") }, - mapMoveDown: { keyCode: key("S") }, - mapMoveLeft: { keyCode: key("A") }, - mapMoveFaster: { keyCode: 16 }, //shift - - centerMap: { keyCode: 32 }, // SPACE - mapZoomIn: { keyCode: 187, repeated: true }, // "+" - mapZoomOut: { keyCode: 189, repeated: true }, // "-" - - createMarker: { keyCode: key("M") }, - }, - - buildings: { - belt: { keyCode: key("1") }, - splitter: { keyCode: key("2") }, - underground_belt: { keyCode: key("3") }, - miner: { keyCode: key("4") }, - cutter: { keyCode: key("5") }, - rotater: { keyCode: key("6") }, - stacker: { keyCode: key("7") }, - mixer: { keyCode: key("8") }, - painter: { keyCode: key("9") }, - trash: { keyCode: key("0") }, - energy_generator: { keyCode: key("O") }, - advanced_processor: { keyCode: key("P") }, - - // Wires layer - wire: { keyCode: key("1") }, - wire_crossings: { keyCode: key("2") }, - }, - - placement: { - pipette: { keyCode: key("Q") }, - rotateWhilePlacing: { keyCode: key("R") }, - rotateInverseModifier: { keyCode: 16 }, // SHIFT - cycleBuildingVariants: { keyCode: key("T") }, - cycleBuildings: { keyCode: 9 }, // TAB - switchDirectionLockSide: { keyCode: key("R") }, - }, - - massSelect: { - massSelectStart: { keyCode: 17 }, // CTRL - massSelectSelectMultiple: { keyCode: 16 }, // SHIFT - massSelectCopy: { keyCode: key("C") }, - massSelectCut: { keyCode: key("X") }, - confirmMassDelete: { keyCode: 46 }, // DEL - pasteLastBlueprint: { keyCode: key("V") }, - }, - - placementModifiers: { - lockBeltDirection: { keyCode: 16 }, // SHIFT - placementDisableAutoOrientation: { keyCode: 17 }, // CTRL - placeMultiple: { keyCode: 16 }, // SHIFT - placeInverse: { keyCode: 18 }, // ALT - }, -}; - -// Assign ids -for (const categoryId in KEYMAPPINGS) { - for (const mappingId in KEYMAPPINGS[categoryId]) { - KEYMAPPINGS[categoryId][mappingId].id = mappingId; - } -} - -export const KEYCODE_LMB = 1; -export const KEYCODE_MMB = 2; -export const KEYCODE_RMB = 3; - -/** - * Returns a keycode -> string - * @param {number} code - * @returns {string} - */ -export function getStringForKeyCode(code) { - switch (code) { - case KEYCODE_LMB: - return "LMB"; - case KEYCODE_MMB: - return "MMB"; - case KEYCODE_RMB: - return "RMB"; - case 4: - return "MB4"; - case 5: - return "MB5"; - case 8: - return "⌫"; - case 9: - return T.global.keys.tab; - case 13: - return "⏎"; - case 16: - return "⇪"; - case 17: - return T.global.keys.control; - case 18: - return T.global.keys.alt; - case 19: - return "PAUSE"; - case 20: - return "CAPS"; - case 27: - return T.global.keys.escape; - case 32: - return T.global.keys.space; - case 33: - return "PGUP"; - case 34: - return "PGDOWN"; - case 35: - return "END"; - case 36: - return "HOME"; - case 37: - return "⬅"; - case 38: - return "⬆"; - case 39: - return "➡"; - case 40: - return "⬇"; - case 44: - return "PRNT"; - case 45: - return "INS"; - case 46: - return "DEL"; - case 93: - return "SEL"; - case 96: - return "NUM 0"; - case 97: - return "NUM 1"; - case 98: - return "NUM 2"; - case 99: - return "NUM 3"; - case 100: - return "NUM 4"; - case 101: - return "NUM 5"; - case 102: - return "NUM 6"; - case 103: - return "NUM 7"; - case 104: - return "NUM 8"; - case 105: - return "NUM 9"; - case 106: - return "*"; - case 107: - return "+"; - case 109: - return "-"; - case 110: - return "."; - case 111: - return "/"; - case 112: - return "F1"; - case 113: - return "F2"; - case 114: - return "F3"; - case 115: - return "F4"; - case 116: - return "F4"; - case 117: - return "F5"; - case 118: - return "F6"; - case 119: - return "F7"; - case 120: - return "F8"; - case 121: - return "F9"; - case 122: - return "F10"; - case 123: - return "F11"; - case 124: - return "F12"; - - case 144: - return "NUMLOCK"; - case 145: - return "SCRLOCK"; - case 182: - return "COMP"; - case 183: - return "CALC"; - case 186: - return ";"; - case 187: - return "+"; - case 188: - return ","; - case 189: - return "-"; - case 191: - return "/"; - case 219: - return "["; - case 220: - return "\\"; - case 221: - return "]"; - case 222: - return "'"; - } - - return String.fromCharCode(code); -} - -export class Keybinding { - /** - * - * @param {KeyActionMapper} keyMapper - * @param {Application} app - * @param {object} param0 - * @param {number} param0.keyCode - * @param {boolean=} param0.builtin - * @param {boolean=} param0.repeated - */ - constructor(keyMapper, app, { keyCode, builtin = false, repeated = false }) { - assert(keyCode && Number.isInteger(keyCode), "Invalid key code: " + keyCode); - this.keyMapper = keyMapper; - this.app = app; - this.keyCode = keyCode; - this.builtin = builtin; - this.repeated = repeated; - - this.signal = new Signal(); - this.toggled = new Signal(); - } - - /** - * Returns whether this binding is currently pressed - * @returns {boolean} - */ - get pressed() { - // Check if the key is down - if (this.app.inputMgr.keysDown.has(this.keyCode)) { - // Check if it is the top reciever - const reciever = this.keyMapper.inputReceiver; - return this.app.inputMgr.getTopReciever() === reciever; - } - return false; - } - - /** - * Adds an event listener - * @param {function() : void} receiver - * @param {object=} scope - */ - add(receiver, scope = null) { - this.signal.add(receiver, scope); - } - - /** - * @param {Element} elem - * @returns {HTMLElement} the created element, or null if the keybindings are not shown - * */ - appendLabelToElement(elem) { - if (IS_MOBILE) { - return null; - } - const spacer = document.createElement("code"); - spacer.classList.add("keybinding"); - spacer.innerHTML = getStringForKeyCode(this.keyCode); - elem.appendChild(spacer); - return spacer; - } - - /** - * Returns the key code as a nice string - */ - getKeyCodeString() { - return getStringForKeyCode(this.keyCode); - } - - /** - * Remvoes all signal receivers - */ - clearSignalReceivers() { - this.signal.removeAll(); - } -} - -export class KeyActionMapper { - /** - * - * @param {GameRoot} root - * @param {InputReceiver} inputReciever - */ - constructor(root, inputReciever) { - this.root = root; - this.inputReceiver = inputReciever; - - inputReciever.keydown.add(this.handleKeydown, this); - inputReciever.keyup.add(this.handleKeyup, this); - - /** @type {Object.} */ - this.keybindings = {}; - - const overrides = root.app.settings.getKeybindingOverrides(); - - for (const category in KEYMAPPINGS) { - for (const key in KEYMAPPINGS[category]) { - let payload = Object.assign({}, KEYMAPPINGS[category][key]); - if (overrides[key]) { - payload.keyCode = overrides[key]; - } - - this.keybindings[key] = new Keybinding(this, this.root.app, payload); - } - } - - inputReciever.pageBlur.add(this.onPageBlur, this); - inputReciever.destroyed.add(this.cleanup, this); - } - - /** - * Returns all keybindings starting with the given id - * @param {string} pattern - * @returns {Array} - */ - getKeybindingsStartingWith(pattern) { - let result = []; - for (const key in this.keybindings) { - if (key.startsWith(pattern)) { - result.push(this.keybindings[key]); - } - } - return result; - } - - /** - * Forwards the given events to the other mapper (used in tooltips) - * @param {KeyActionMapper} receiver - * @param {Array} bindings - */ - forward(receiver, bindings) { - for (let i = 0; i < bindings.length; ++i) { - const key = bindings[i]; - this.keybindings[key].signal.add((...args) => receiver.keybindings[key].signal.dispatch(...args)); - } - } - - cleanup() { - for (const key in this.keybindings) { - this.keybindings[key].signal.removeAll(); - } - } - - onPageBlur() { - // Reset all down states - // Find mapping - for (const key in this.keybindings) { - /** @type {Keybinding} */ - const binding = this.keybindings[key]; - } - } - - /** - * Internal keydown handler - * @param {object} param0 - * @param {number} param0.keyCode - * @param {boolean} param0.shift - * @param {boolean} param0.alt - * @param {boolean=} param0.initial - */ - handleKeydown({ keyCode, shift, alt, initial }) { - let stop = false; - - // Find mapping - for (const key in this.keybindings) { - /** @type {Keybinding} */ - const binding = this.keybindings[key]; - if (binding.keyCode === keyCode && (initial || binding.repeated)) { - /** @type {Signal} */ - const signal = this.keybindings[key].signal; - if (signal.dispatch() === STOP_PROPAGATION) { - return; - } - } - } - - if (stop) { - return STOP_PROPAGATION; - } - } - - /** - * Internal keyup handler - * @param {object} param0 - * @param {number} param0.keyCode - * @param {boolean} param0.shift - * @param {boolean} param0.alt - */ - handleKeyup({ keyCode, shift, alt }) { - // Empty - } - - /** - * Returns a given keybinding - * @param {{ keyCode: number }} binding - * @returns {Keybinding} - */ - getBinding(binding) { - // @ts-ignore - const id = binding.id; - assert(id, "Not a valid keybinding: " + JSON.stringify(binding)); - assert(this.keybindings[id], "Keybinding " + id + " not known!"); - return this.keybindings[id]; - } -} +/* typehints:start */ +import { GameRoot } from "./root"; +import { InputReceiver } from "../core/input_receiver"; +import { Application } from "../application"; +/* typehints:end */ + +import { Signal, STOP_PROPAGATION } from "../core/signal"; +import { IS_MOBILE } from "../core/config"; +import { T } from "../translations"; +function key(str) { + return str.toUpperCase().charCodeAt(0); +} + +export const KEYMAPPINGS = { + general: { + confirm: { keyCode: 13 }, // enter + back: { keyCode: 27, builtin: true }, // escape + }, + + ingame: { + menuOpenShop: { keyCode: key("F") }, + menuOpenStats: { keyCode: key("G") }, + menuClose: { keyCode: key("Q") }, + + toggleHud: { keyCode: 113 }, // F2 + exportScreenshot: { keyCode: 114 }, // F3PS + toggleFPSInfo: { keyCode: 115 }, // F4 + + switchLayers: { keyCode: key("Y") }, + }, + + navigation: { + mapMoveUp: { keyCode: key("W") }, + mapMoveRight: { keyCode: key("D") }, + mapMoveDown: { keyCode: key("S") }, + mapMoveLeft: { keyCode: key("A") }, + mapMoveFaster: { keyCode: 16 }, //shift + + centerMap: { keyCode: 32 }, // SPACE + mapZoomIn: { keyCode: 187, repeated: true }, // "+" + mapZoomOut: { keyCode: 189, repeated: true }, // "-" + + createMarker: { keyCode: key("M") }, + }, + + buildings: { + belt: { keyCode: key("1") }, + splitter: { keyCode: key("2") }, + underground_belt: { keyCode: key("3") }, + miner: { keyCode: key("4") }, + cutter: { keyCode: key("5") }, + rotater: { keyCode: key("6") }, + stacker: { keyCode: key("7") }, + mixer: { keyCode: key("8") }, + painter: { keyCode: key("9") }, + trash: { keyCode: key("0") }, + + lever: { keyCode: key("L") }, + filter: { keyCode: key("B") }, + display: { keyCode: key("N") }, + reader: { keyCode: key("J") }, + + wire: { keyCode: key("1") }, + wire_tunnel: { keyCode: key("2") }, + constant_signal: { keyCode: key("3") }, + logic_gate: { keyCode: key("4") }, + virtual_processor: { keyCode: key("5") }, + }, + + placement: { + pipette: { keyCode: key("Q") }, + rotateWhilePlacing: { keyCode: key("R") }, + rotateInverseModifier: { keyCode: 16 }, // SHIFT + cycleBuildingVariants: { keyCode: key("T") }, + cycleBuildings: { keyCode: 9 }, // TAB + switchDirectionLockSide: { keyCode: key("R") }, + }, + + massSelect: { + massSelectStart: { keyCode: 17 }, // CTRL + massSelectSelectMultiple: { keyCode: 16 }, // SHIFT + massSelectCopy: { keyCode: key("C") }, + massSelectCut: { keyCode: key("X") }, + confirmMassDelete: { keyCode: 46 }, // DEL + pasteLastBlueprint: { keyCode: key("V") }, + }, + + placementModifiers: { + lockBeltDirection: { keyCode: 16 }, // SHIFT + placementDisableAutoOrientation: { keyCode: 17 }, // CTRL + placeMultiple: { keyCode: 16 }, // SHIFT + placeInverse: { keyCode: 18 }, // ALT + }, +}; + +// Assign ids +for (const categoryId in KEYMAPPINGS) { + for (const mappingId in KEYMAPPINGS[categoryId]) { + KEYMAPPINGS[categoryId][mappingId].id = mappingId; + } +} + +export const KEYCODE_LMB = 1; +export const KEYCODE_MMB = 2; +export const KEYCODE_RMB = 3; + +/** + * Returns a keycode -> string + * @param {number} code + * @returns {string} + */ +export function getStringForKeyCode(code) { + switch (code) { + case KEYCODE_LMB: + return "LMB"; + case KEYCODE_MMB: + return "MMB"; + case KEYCODE_RMB: + return "RMB"; + case 4: + return "MB4"; + case 5: + return "MB5"; + case 8: + return "⌫"; + case 9: + return T.global.keys.tab; + case 13: + return "⏎"; + case 16: + return "⇪"; + case 17: + return T.global.keys.control; + case 18: + return T.global.keys.alt; + case 19: + return "PAUSE"; + case 20: + return "CAPS"; + case 27: + return T.global.keys.escape; + case 32: + return T.global.keys.space; + case 33: + return "PGUP"; + case 34: + return "PGDOWN"; + case 35: + return "END"; + case 36: + return "HOME"; + case 37: + return "⬅"; + case 38: + return "⬆"; + case 39: + return "➡"; + case 40: + return "⬇"; + case 44: + return "PRNT"; + case 45: + return "INS"; + case 46: + return "DEL"; + case 93: + return "SEL"; + case 96: + return "NUM 0"; + case 97: + return "NUM 1"; + case 98: + return "NUM 2"; + case 99: + return "NUM 3"; + case 100: + return "NUM 4"; + case 101: + return "NUM 5"; + case 102: + return "NUM 6"; + case 103: + return "NUM 7"; + case 104: + return "NUM 8"; + case 105: + return "NUM 9"; + case 106: + return "*"; + case 107: + return "+"; + case 109: + return "-"; + case 110: + return "."; + case 111: + return "/"; + case 112: + return "F1"; + case 113: + return "F2"; + case 114: + return "F3"; + case 115: + return "F4"; + case 116: + return "F4"; + case 117: + return "F5"; + case 118: + return "F6"; + case 119: + return "F7"; + case 120: + return "F8"; + case 121: + return "F9"; + case 122: + return "F10"; + case 123: + return "F11"; + case 124: + return "F12"; + + case 144: + return "NUMLOCK"; + case 145: + return "SCRLOCK"; + case 182: + return "COMP"; + case 183: + return "CALC"; + case 186: + return ";"; + case 187: + return "+"; + case 188: + return ","; + case 189: + return "-"; + case 191: + return "/"; + case 219: + return "["; + case 220: + return "\\"; + case 221: + return "]"; + case 222: + return "'"; + } + + return String.fromCharCode(code); +} + +export class Keybinding { + /** + * + * @param {KeyActionMapper} keyMapper + * @param {Application} app + * @param {object} param0 + * @param {number} param0.keyCode + * @param {boolean=} param0.builtin + * @param {boolean=} param0.repeated + */ + constructor(keyMapper, app, { keyCode, builtin = false, repeated = false }) { + assert(keyCode && Number.isInteger(keyCode), "Invalid key code: " + keyCode); + this.keyMapper = keyMapper; + this.app = app; + this.keyCode = keyCode; + this.builtin = builtin; + this.repeated = repeated; + + this.signal = new Signal(); + this.toggled = new Signal(); + } + + /** + * Returns whether this binding is currently pressed + * @returns {boolean} + */ + get pressed() { + // Check if the key is down + if (this.app.inputMgr.keysDown.has(this.keyCode)) { + // Check if it is the top reciever + const reciever = this.keyMapper.inputReceiver; + return this.app.inputMgr.getTopReciever() === reciever; + } + return false; + } + + /** + * Adds an event listener + * @param {function() : void} receiver + * @param {object=} scope + */ + add(receiver, scope = null) { + this.signal.add(receiver, scope); + } + + /** + * @param {Element} elem + * @returns {HTMLElement} the created element, or null if the keybindings are not shown + * */ + appendLabelToElement(elem) { + if (IS_MOBILE) { + return null; + } + const spacer = document.createElement("code"); + spacer.classList.add("keybinding"); + spacer.innerHTML = getStringForKeyCode(this.keyCode); + elem.appendChild(spacer); + return spacer; + } + + /** + * Returns the key code as a nice string + */ + getKeyCodeString() { + return getStringForKeyCode(this.keyCode); + } + + /** + * Remvoes all signal receivers + */ + clearSignalReceivers() { + this.signal.removeAll(); + } +} + +export class KeyActionMapper { + /** + * + * @param {GameRoot} root + * @param {InputReceiver} inputReciever + */ + constructor(root, inputReciever) { + this.root = root; + this.inputReceiver = inputReciever; + + inputReciever.keydown.add(this.handleKeydown, this); + inputReciever.keyup.add(this.handleKeyup, this); + + /** @type {Object.} */ + this.keybindings = {}; + + const overrides = root.app.settings.getKeybindingOverrides(); + + for (const category in KEYMAPPINGS) { + for (const key in KEYMAPPINGS[category]) { + let payload = Object.assign({}, KEYMAPPINGS[category][key]); + if (overrides[key]) { + payload.keyCode = overrides[key]; + } + + this.keybindings[key] = new Keybinding(this, this.root.app, payload); + } + } + + inputReciever.pageBlur.add(this.onPageBlur, this); + inputReciever.destroyed.add(this.cleanup, this); + } + + /** + * Returns all keybindings starting with the given id + * @param {string} pattern + * @returns {Array} + */ + getKeybindingsStartingWith(pattern) { + let result = []; + for (const key in this.keybindings) { + if (key.startsWith(pattern)) { + result.push(this.keybindings[key]); + } + } + return result; + } + + /** + * Forwards the given events to the other mapper (used in tooltips) + * @param {KeyActionMapper} receiver + * @param {Array} bindings + */ + forward(receiver, bindings) { + for (let i = 0; i < bindings.length; ++i) { + const key = bindings[i]; + this.keybindings[key].signal.add((...args) => receiver.keybindings[key].signal.dispatch(...args)); + } + } + + cleanup() { + for (const key in this.keybindings) { + this.keybindings[key].signal.removeAll(); + } + } + + onPageBlur() { + // Reset all down states + // Find mapping + for (const key in this.keybindings) { + /** @type {Keybinding} */ + const binding = this.keybindings[key]; + } + } + + /** + * Internal keydown handler + * @param {object} param0 + * @param {number} param0.keyCode + * @param {boolean} param0.shift + * @param {boolean} param0.alt + * @param {boolean=} param0.initial + */ + handleKeydown({ keyCode, shift, alt, initial }) { + let stop = false; + + // Find mapping + for (const key in this.keybindings) { + /** @type {Keybinding} */ + const binding = this.keybindings[key]; + if (binding.keyCode === keyCode && (initial || binding.repeated)) { + /** @type {Signal} */ + const signal = this.keybindings[key].signal; + if (signal.dispatch() === STOP_PROPAGATION) { + return; + } + } + } + + if (stop) { + return STOP_PROPAGATION; + } + } + + /** + * Internal keyup handler + * @param {object} param0 + * @param {number} param0.keyCode + * @param {boolean} param0.shift + * @param {boolean} param0.alt + */ + handleKeyup({ keyCode, shift, alt }) { + // Empty + } + + /** + * Returns a given keybinding + * @param {{ keyCode: number }} binding + * @returns {Keybinding} + */ + getBinding(binding) { + // @ts-ignore + const id = binding.id; + assert(id, "Not a valid keybinding: " + JSON.stringify(binding)); + assert(this.keybindings[id], "Keybinding " + id + " not known!"); + return this.keybindings[id]; + } +} diff --git a/src/js/game/logic.js b/src/js/game/logic.js index 403fa15b..ce4d18a5 100644 --- a/src/js/game/logic.js +++ b/src/js/game/logic.js @@ -1,13 +1,23 @@ import { createLogger } from "../core/logging"; +import { STOP_PROPAGATION } from "../core/signal"; import { round2Digits } from "../core/utils"; -import { enumDirection, enumDirectionToVector, Vector } from "../core/vector"; +import { enumDirection, enumDirectionToVector, enumInvertedDirections, Vector } from "../core/vector"; +import { getBuildingDataFromCode } from "./building_codes"; import { Entity } from "./entity"; import { MetaBuilding } from "./meta_building"; -import { enumLayer, GameRoot } from "./root"; -import { STOP_PROPAGATION } from "../core/signal"; +import { GameRoot } from "./root"; +import { WireNetwork } from "./systems/wire"; +import { globalConfig } from "../core/config"; +import { CHUNK_OVERLAY_RES } from "./map_chunk_view"; const logger = createLogger("ingame/logic"); +/** @enum {number} */ +export const enumWireEdgeFlag = { + empty: 0, + connected: 2, +}; + /** * Typing helper * @typedef {Array<{ @@ -63,9 +73,12 @@ export class GameLogic { for (let y = rect.y; y < rect.y + rect.h; ++y) { // Check if there is any direct collision const otherEntity = this.root.map.getLayerContentXY(x, y, entity.layer); - if (otherEntity && !otherEntity.components.ReplaceableMapEntity) { - // This one is a direct blocker - return false; + if (otherEntity) { + const metaClass = otherEntity.components.StaticMapEntity.getMetaBuilding(); + if (!metaClass.getIsReplaceable()) { + // This one is a direct blocker + return false; + } } } } @@ -121,7 +134,7 @@ export class GameLogic { const contents = this.root.map.getLayerContentXY(x, y, entity.layer); if (contents) { assertAlways( - contents.components.ReplaceableMapEntity, + contents.components.StaticMapEntity.getMetaBuilding().getIsReplaceable(), "Tried to replace non-repleaceable entity" ); if (!this.tryDeleteBuilding(contents)) { @@ -158,7 +171,8 @@ export class GameLogic { * @param {Entity} building */ canDeleteBuilding(building) { - return building.components.StaticMapEntity && !building.components.Unremovable; + const staticComp = building.components.StaticMapEntity; + return staticComp.getMetaBuilding().getIsRemovable(); } /** @@ -175,13 +189,206 @@ export class GameLogic { return true; } + /** + * + * Computes the flag for a given tile + * @param {object} param0 + * @param {Vector} param0.tile The tile to check at + * @param {enumDirection} param0.edge The edge to check for + * @param {number} param0.rotation The local tiles base rotation + */ + computeWireEdgeStatus({ tile, edge, rotation }) { + const offset = enumDirectionToVector[edge]; + const refTile = tile.add(offset); + // const angle = enumDirectionToAngle[edge]; + + // // First, check if this edge can be connected from locally + // const canConnectLocally = rotation === angle || (rotation + 180) % 360 === angle; + + const neighbourStatus = this.getWireEdgeFlag(refTile, edge); + + if (neighbourStatus === enumWireEdgeFlag.empty) { + // It's empty, no point in connecting + return false; + } + + if (neighbourStatus === enumWireEdgeFlag.connected) { + return true; + } + } + + /** + * Returns all wire networks this entity participates in on the given tile + * @param {Entity} entity + * @param {Vector} tile + * @returns {Array|null} Null if the entity is never able to be connected at the given tile + */ + getEntityWireNetworks(entity, tile) { + let canConnectAtAll = false; + + /** @type {Set} */ + const networks = new Set(); + + const staticComp = entity.components.StaticMapEntity; + const wireComp = entity.components.Wire; + if (wireComp) { + canConnectAtAll = true; + if (wireComp.linkedNetwork) { + networks.add(wireComp.linkedNetwork); + } + } + + const tunnelComp = entity.components.WireTunnel; + if (tunnelComp) { + canConnectAtAll = true; + for (let i = 0; i < tunnelComp.linkedNetworks.length; ++i) { + networks.add(tunnelComp.linkedNetworks[i]); + } + } + + const pinsComp = entity.components.WiredPins; + if (pinsComp) { + const slots = pinsComp.slots; + for (let i = 0; i < slots.length; ++i) { + const slot = slots[i]; + const slotLocalPos = staticComp.localTileToWorld(slot.pos); + if (slotLocalPos.equals(tile)) { + canConnectAtAll = true; + if (slot.linkedNetwork) { + networks.add(slot.linkedNetwork); + } + } + } + } + + if (!canConnectAtAll) { + return null; + } + + return Array.from(networks); + } + + /** + * Returns if the entities tile *and* his overlay matrix is intersected + * @param {Entity} entity + * @param {Vector} worldPos + */ + getIsEntityIntersectedWithMatrix(entity, worldPos) { + const staticComp = entity.components.StaticMapEntity; + const tile = worldPos.toTileSpace(); + + if (!staticComp.getTileSpaceBounds().containsPoint(tile.x, tile.y)) { + // No intersection at all + return; + } + + const data = getBuildingDataFromCode(staticComp.code); + const overlayMatrix = data.metaInstance.getSpecialOverlayRenderMatrix( + staticComp.rotation, + data.rotationVariant, + data.variant, + entity + ); + // Always the same + if (!overlayMatrix) { + return true; + } + + const localPosition = worldPos + .divideScalar(globalConfig.tileSize) + .modScalar(1) + .multiplyScalar(CHUNK_OVERLAY_RES) + .floor(); + + return !!overlayMatrix[localPosition.x + localPosition.y * 3]; + } + + /** + * Gets the flag at the given tile + * @param {Vector} tile + * @param {enumDirection} edge + * @returns {enumWireEdgeFlag} + */ + getWireEdgeFlag(tile, edge) { + // Search for relevant pins + const pinEntities = this.root.map.getLayersContentsMultipleXY(tile.x, tile.y); + + // Go over all entities which could have a pin + for (let i = 0; i < pinEntities.length; ++i) { + const pinEntity = pinEntities[i]; + const pinComp = pinEntity.components.WiredPins; + const staticComp = pinEntity.components.StaticMapEntity; + + // Skip those who don't have pins + if (!pinComp) { + continue; + } + + // Go over all pins + const pins = pinComp.slots; + for (let k = 0; k < pinComp.slots.length; ++k) { + const pinSlot = pins[k]; + const pinLocation = staticComp.localTileToWorld(pinSlot.pos); + const pinDirection = staticComp.localDirectionToWorld(pinSlot.direction); + + // Check if the pin has the right location + if (!pinLocation.equals(tile)) { + continue; + } + + // Check if the pin has the right direction + if (pinDirection !== enumInvertedDirections[edge]) { + continue; + } + + // Found a pin! + return enumWireEdgeFlag.connected; + } + } + + // Now check if there's a connectable wire + const targetEntity = this.root.map.getTileContent(tile, "wires"); + if (!targetEntity) { + return enumWireEdgeFlag.empty; + } + + const targetStaticComp = targetEntity.components.StaticMapEntity; + + // Check if its a crossing + const wireTunnelComp = targetEntity.components.WireTunnel; + if (wireTunnelComp) { + // Check if the crossing is connected + if (wireTunnelComp.multipleDirections) { + return enumWireEdgeFlag.connected; + } else { + // Its a coating, check if it matches the direction + const referenceDirection = targetStaticComp.localDirectionToWorld(enumDirection.top); + return referenceDirection === edge || enumInvertedDirections[referenceDirection] === edge + ? enumWireEdgeFlag.connected + : enumWireEdgeFlag.empty; + } + } + + // Check if its a wire + const wiresComp = targetEntity.components.Wire; + if (!wiresComp) { + return enumWireEdgeFlag.empty; + } + + // const refAngle = enumDirectionToAngle[edge]; + // const refRotation = targetEntity.components.StaticMapEntity.originalRotation; + // const canConnectRemotely = refRotation === refAngle || (refRotation + 180) % 360 === refAngle; + + // Actually connected + return enumWireEdgeFlag.connected; + } + /** * Returns the acceptors and ejectors which affect the current tile * @param {Vector} tile - * @param {enumLayer} layer * @returns {AcceptorsAndEjectorsAffectingTile} */ - getEjectorsAndAcceptorsAtTile(tile, layer) { + getEjectorsAndAcceptorsAtTile(tile) { /** @type {EjectorsAffectingTile} */ let ejectors = []; /** @type {AcceptorsAffectingTile} */ @@ -194,54 +401,61 @@ export class GameLogic { continue; } - const entities = this.root.map.getLayersContentsMultipleXY(tile.x + dx, tile.y + dy); - for (let i = 0; i < entities.length; ++i) { - const entity = entities[i]; + const entity = this.root.map.getLayerContentXY(tile.x + dx, tile.y + dy, "regular"); + if (entity) { + let ejectorSlots = []; + let acceptorSlots = []; const staticComp = entity.components.StaticMapEntity; const itemEjector = entity.components.ItemEjector; + const itemAcceptor = entity.components.ItemAcceptor; + const beltComp = entity.components.Belt; + if (itemEjector) { - for (let ejectorSlot = 0; ejectorSlot < itemEjector.slots.length; ++ejectorSlot) { - const slot = itemEjector.slots[ejectorSlot]; - if (slot.layer !== layer) { - continue; - } - const wsTile = staticComp.localTileToWorld(slot.pos); - const wsDirection = staticComp.localDirectionToWorld(slot.direction); - const targetTile = wsTile.add(enumDirectionToVector[wsDirection]); - if (targetTile.equals(tile)) { - ejectors.push({ - entity, - slot, - fromTile: wsTile, - toDirection: wsDirection, - }); - } + ejectorSlots = itemEjector.slots.slice(); + } + + if (itemAcceptor) { + acceptorSlots = itemAcceptor.slots.slice(); + } + + if (beltComp) { + const fakeEjectorSlot = beltComp.getFakeEjectorSlot(); + const fakeAcceptorSlot = beltComp.getFakeAcceptorSlot(); + ejectorSlots.push(fakeEjectorSlot); + acceptorSlots.push(fakeAcceptorSlot); + } + + for (let ejectorSlot = 0; ejectorSlot < ejectorSlots.length; ++ejectorSlot) { + const slot = ejectorSlots[ejectorSlot]; + const wsTile = staticComp.localTileToWorld(slot.pos); + const wsDirection = staticComp.localDirectionToWorld(slot.direction); + const targetTile = wsTile.add(enumDirectionToVector[wsDirection]); + if (targetTile.equals(tile)) { + ejectors.push({ + entity, + slot, + fromTile: wsTile, + toDirection: wsDirection, + }); } } - const itemAcceptor = entity.components.ItemAcceptor; - if (itemAcceptor) { - for (let acceptorSlot = 0; acceptorSlot < itemAcceptor.slots.length; ++acceptorSlot) { - const slot = itemAcceptor.slots[acceptorSlot]; - if (slot.layer !== layer) { - continue; - } + for (let acceptorSlot = 0; acceptorSlot < acceptorSlots.length; ++acceptorSlot) { + const slot = acceptorSlots[acceptorSlot]; + const wsTile = staticComp.localTileToWorld(slot.pos); + for (let k = 0; k < slot.directions.length; ++k) { + const direction = slot.directions[k]; + const wsDirection = staticComp.localDirectionToWorld(direction); - const wsTile = staticComp.localTileToWorld(slot.pos); - for (let k = 0; k < slot.directions.length; ++k) { - const direction = slot.directions[k]; - const wsDirection = staticComp.localDirectionToWorld(direction); - - const sourceTile = wsTile.add(enumDirectionToVector[wsDirection]); - if (sourceTile.equals(tile)) { - acceptors.push({ - entity, - slot, - toTile: wsTile, - fromDirection: wsDirection, - }); - } + const sourceTile = wsTile.add(enumDirectionToVector[wsDirection]); + if (sourceTile.equals(tile)) { + acceptors.push({ + entity, + slot, + toTile: wsTile, + fromDirection: wsDirection, + }); } } } diff --git a/src/js/game/map.js b/src/js/game/map.js index 3f8a16f8..5ff51ce8 100644 --- a/src/js/game/map.js +++ b/src/js/game/map.js @@ -1,14 +1,10 @@ -import { GameRoot, enumLayer } from "./root"; import { globalConfig } from "../core/config"; import { Vector } from "../core/vector"; -import { Entity } from "./entity"; -import { createLogger } from "../core/logging"; -import { BaseItem } from "./base_item"; -import { MapChunkView } from "./map_chunk_view"; -import { randomInt } from "../core/utils"; import { BasicSerializableObject, types } from "../savegame/serialization"; - -const logger = createLogger("map"); +import { BaseItem } from "./base_item"; +import { Entity } from "./entity"; +import { MapChunkView } from "./map_chunk_view"; +import { GameRoot } from "./root"; export class BaseMap extends BasicSerializableObject { static getId() { @@ -98,7 +94,7 @@ export class BaseMap extends BasicSerializableObject { /** * Returns the tile content of a given tile * @param {Vector} tile - * @param {enumLayer} layer + * @param {Layer} layer * @returns {Entity} Entity or null */ getTileContent(tile, layer) { @@ -123,7 +119,7 @@ export class BaseMap extends BasicSerializableObject { * Returns the tile content of a given tile * @param {number} x * @param {number} y - * @param {enumLayer} layer + * @param {Layer} layer * @returns {Entity} Entity or null */ getLayerContentXY(x, y, layer) { @@ -148,7 +144,7 @@ export class BaseMap extends BasicSerializableObject { /** * Checks if the tile is used * @param {Vector} tile - * @param {enumLayer} layer + * @param {Layer} layer * @returns {boolean} */ isTileUsed(tile, layer) { @@ -163,7 +159,7 @@ export class BaseMap extends BasicSerializableObject { * Checks if the tile is used * @param {number} x * @param {number} y - * @param {enumLayer} layer + * @param {Layer} layer * @returns {boolean} */ isTileUsedXY(x, y, layer) { diff --git a/src/js/game/map_chunk.js b/src/js/game/map_chunk.js index dd9ba81d..54af1125 100644 --- a/src/js/game/map_chunk.js +++ b/src/js/game/map_chunk.js @@ -1,15 +1,15 @@ -import { GameRoot, enumLayer } from "./root"; import { globalConfig } from "../core/config"; import { createLogger } from "../core/logging"; +import { RandomNumberGenerator } from "../core/rng"; import { clamp, fastArrayDeleteValueIfContained, make2DUndefinedArray } from "../core/utils"; import { Vector } from "../core/vector"; import { BaseItem } from "./base_item"; import { enumColors } from "./colors"; import { Entity } from "./entity"; -import { ColorItem } from "./items/color_item"; -import { ShapeItem } from "./items/shape_item"; +import { COLOR_ITEM_SINGLETONS } from "./items/color_item"; +import { GameRoot } from "./root"; import { enumSubShape } from "./shape_definition"; -import { RandomNumberGenerator } from "../core/rng"; +import { Rectangle } from "../core/rectangle"; const logger = createLogger("map_chunk"); @@ -27,30 +27,56 @@ export class MapChunk { this.tileX = x * globalConfig.mapChunkSize; this.tileY = y * globalConfig.mapChunkSize; - /** @type {Array>} */ - this.contents = make2DUndefinedArray( - globalConfig.mapChunkSize, - globalConfig.mapChunkSize, - "map-chunk@" + this.x + "|" + this.y - ); + /** + * Stores the contents of the lower (= map resources) layer + * @type {Array>} + */ + this.lowerLayer = make2DUndefinedArray(globalConfig.mapChunkSize, globalConfig.mapChunkSize); - /** @type {Array>} */ - this.wireContents = make2DUndefinedArray( - globalConfig.mapChunkSize, - globalConfig.mapChunkSize, - "map-chunk-wires@" + this.x + "|" + this.y - ); + /** + * Stores the contents of the regular layer + * @type {Array>} + */ + this.contents = make2DUndefinedArray(globalConfig.mapChunkSize, globalConfig.mapChunkSize); - /** @type {Array>} */ - this.lowerLayer = make2DUndefinedArray( - globalConfig.mapChunkSize, - globalConfig.mapChunkSize, - "map-chunk-lower@" + this.x + "|" + this.y - ); + /** + * Stores the contents of the wires layer + * @type {Array>} + */ + this.wireContents = make2DUndefinedArray(globalConfig.mapChunkSize, globalConfig.mapChunkSize); /** @type {Array} */ this.containedEntities = []; + /** + * World space rectangle, can be used for culling + */ + this.worldSpaceRectangle = new Rectangle( + this.tileX * globalConfig.tileSize, + this.tileY * globalConfig.tileSize, + globalConfig.mapChunkWorldSize, + globalConfig.mapChunkWorldSize + ); + + /** + * Tile space rectangle, can be used for culling + */ + this.tileSpaceRectangle = new Rectangle( + this.tileX, + this.tileY, + globalConfig.mapChunkSize, + globalConfig.mapChunkSize + ); + + /** + * Which entities this chunk contains, sorted by layer + * @type {Record>} + */ + this.containedEntitiesByLayer = { + regular: [], + wires: [], + }; + /** * Store which patches we have so we can render them in the overview * @type {Array<{pos: Vector, item: BaseItem, size: number }>} @@ -143,7 +169,7 @@ export class MapChunk { if (distanceToOriginInChunks > 2) { availableColors.push(enumColors.blue); } - this.internalGeneratePatch(rng, colorPatchSize, new ColorItem(rng.choice(availableColors))); + this.internalGeneratePatch(rng, colorPatchSize, COLOR_ITEM_SINGLETONS[rng.choice(availableColors)]); } /** @@ -204,7 +230,11 @@ export class MapChunk { } const definition = this.root.shapeDefinitionMgr.getDefinitionFromSimpleShapes(subShapes); - this.internalGeneratePatch(rng, shapePatchSize, new ShapeItem(definition)); + this.internalGeneratePatch( + rng, + shapePatchSize, + this.root.shapeDefinitionMgr.getShapeItemFromDefinition(definition) + ); } /** @@ -268,28 +298,28 @@ export class MapChunk { */ generatePredefined(rng) { if (this.x === 0 && this.y === 0) { - this.internalGeneratePatch(rng, 2, new ColorItem(enumColors.red), 7, 7); + this.internalGeneratePatch(rng, 2, COLOR_ITEM_SINGLETONS[enumColors.red], 7, 7); return true; } if (this.x === -1 && this.y === 0) { - const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey("CuCuCuCu"); - this.internalGeneratePatch(rng, 2, new ShapeItem(definition), globalConfig.mapChunkSize - 9, 7); + const item = this.root.shapeDefinitionMgr.getShapeItemFromShortKey("CuCuCuCu"); + this.internalGeneratePatch(rng, 2, item, globalConfig.mapChunkSize - 9, 7); return true; } if (this.x === 0 && this.y === -1) { - const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey("RuRuRuRu"); - this.internalGeneratePatch(rng, 2, new ShapeItem(definition), 5, globalConfig.mapChunkSize - 7); + const item = this.root.shapeDefinitionMgr.getShapeItemFromShortKey("RuRuRuRu"); + this.internalGeneratePatch(rng, 2, item, 5, globalConfig.mapChunkSize - 7); return true; } if (this.x === -1 && this.y === -1) { - this.internalGeneratePatch(rng, 2, new ColorItem(enumColors.green)); + this.internalGeneratePatch(rng, 2, COLOR_ITEM_SINGLETONS[enumColors.green]); return true; } if (this.x === 5 && this.y === -2) { - const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey("SuSuSuSu"); - this.internalGeneratePatch(rng, 2, new ShapeItem(definition), 5, globalConfig.mapChunkSize - 7); + const item = this.root.shapeDefinitionMgr.getShapeItemFromShortKey("SuSuSuSu"); + this.internalGeneratePatch(rng, 2, item, 5, globalConfig.mapChunkSize - 7); return true; } @@ -332,7 +362,7 @@ export class MapChunk { * Returns the contents of this chunk from the given world space coordinates * @param {number} worldX * @param {number} worldY - * @param {enumLayer} layer + * @param {Layer} layer * @returns {Entity=} */ getLayerContentFromWorldCoords(worldX, worldY, layer) { @@ -342,7 +372,7 @@ export class MapChunk { assert(localY >= 0, "Local Y is < 0"); assert(localX < globalConfig.mapChunkSize, "Local X is >= chunk size"); assert(localY < globalConfig.mapChunkSize, "Local Y is >= chunk size"); - if (layer === enumLayer.regular) { + if (layer === "regular") { return this.contents[localX][localY] || null; } else { return this.wireContents[localX][localY] || null; @@ -395,7 +425,7 @@ export class MapChunk { * @param {number} tileX * @param {number} tileY * @param {Entity=} contents - * @param {enumLayer} layer + * @param {Layer} layer */ setLayerContentFromWorldCords(tileX, tileY, contents, layer) { const localX = tileX - this.tileX; @@ -406,7 +436,7 @@ export class MapChunk { assert(localY < globalConfig.mapChunkSize, "Local Y is >= chunk size"); let oldContents; - if (layer === enumLayer.regular) { + if (layer === "regular") { oldContents = this.contents[localX][localY]; } else { oldContents = this.wireContents[localX][localY]; @@ -415,11 +445,12 @@ export class MapChunk { assert(contents === null || !oldContents, "Tile already used: " + tileX + " / " + tileY); if (oldContents) { - // Remove from list + // Remove from list (the old contents must be reigstered) fastArrayDeleteValueIfContained(this.containedEntities, oldContents); + fastArrayDeleteValueIfContained(this.containedEntitiesByLayer[layer], oldContents); } - if (layer === enumLayer.regular) { + if (layer === "regular") { this.contents[localX][localY] = contents; } else { this.wireContents[localX][localY] = contents; @@ -429,6 +460,10 @@ export class MapChunk { if (this.containedEntities.indexOf(contents) < 0) { this.containedEntities.push(contents); } + + if (this.containedEntitiesByLayer[layer].indexOf(contents) < 0) { + this.containedEntitiesByLayer[layer].push(contents); + } } } } diff --git a/src/js/game/map_chunk_view.js b/src/js/game/map_chunk_view.js index c3f09b39..7d74e224 100644 --- a/src/js/game/map_chunk_view.js +++ b/src/js/game/map_chunk_view.js @@ -1,77 +1,288 @@ -import { MapChunk } from "./map_chunk"; -import { GameRoot } from "./root"; -import { globalConfig } from "../core/config"; -import { DrawParameters } from "../core/draw_parameters"; -import { round1Digit } from "../core/utils"; -import { Rectangle } from "../core/rectangle"; -import { createLogger } from "../core/logging"; -import { smoothenDpi } from "../core/dpi_manager"; -import { THEME } from "./theme"; - -const logger = createLogger("chunk"); -const chunkSizePixels = globalConfig.mapChunkSize * globalConfig.tileSize; - -export class MapChunkView extends MapChunk { - /** - * - * @param {GameRoot} root - * @param {number} x - * @param {number} y - */ - constructor(root, x, y) { - super(root, x, y); - - /** - * Whenever something changes, we increase this number - so we know we need to redraw - */ - this.renderIteration = 0; - - this.markDirty(); - } - - /** - * Marks this chunk as dirty, rerendering all caches - */ - markDirty() { - ++this.renderIteration; - this.renderKey = this.x + "/" + this.y + "@" + this.renderIteration; - } - - /** - * Draws the background layer - * @param {DrawParameters} parameters - */ - drawBackgroundLayer(parameters) { - const systems = this.root.systemMgr.systems; - systems.mapResources.drawChunk(parameters, this); - systems.belt.drawChunk(parameters, this); - } - - /** - * Draws the foreground layer - * @param {DrawParameters} parameters - */ - drawForegroundLayer(parameters) { - const systems = this.root.systemMgr.systems; - systems.miner.drawChunk(parameters, this); - systems.staticMapEntities.drawChunk(parameters, this); - } - - /** - * Draws the wires layer - * @param {DrawParameters} parameters - */ - drawWiresLayer(parameters) { - const systems = this.root.systemMgr.systems; - systems.belt.drawWiresChunk(parameters, this); - } - - /** - * Draws the wires layer - * @param {DrawParameters} parameters - */ - drawWiresForegroundLayer(parameters) { - const systems = this.root.systemMgr.systems; - systems.staticMapEntities.drawWiresChunk(parameters, this); - } -} +import { globalConfig } from "../core/config"; +import { DrawParameters } from "../core/draw_parameters"; +import { getBuildingDataFromCode } from "./building_codes"; +import { Entity } from "./entity"; +import { MapChunk } from "./map_chunk"; +import { GameRoot } from "./root"; +import { THEME } from "./theme"; +import { drawSpriteClipped } from "../core/draw_utils"; + +export const CHUNK_OVERLAY_RES = 3; + +export class MapChunkView extends MapChunk { + /** + * + * @param {GameRoot} root + * @param {number} x + * @param {number} y + */ + constructor(root, x, y) { + super(root, x, y); + + /** + * Whenever something changes, we increase this number - so we know we need to redraw + */ + this.renderIteration = 0; + + this.markDirty(); + } + + /** + * Marks this chunk as dirty, rerendering all caches + */ + markDirty() { + ++this.renderIteration; + this.renderKey = this.x + "/" + this.y + "@" + this.renderIteration; + } + + /** + * Draws the background layer + * @param {DrawParameters} parameters + */ + drawBackgroundLayer(parameters) { + const systems = this.root.systemMgr.systems; + systems.mapResources.drawChunk(parameters, this); + systems.beltUnderlays.drawChunk(parameters, this); + systems.belt.drawChunk(parameters, this); + } + + /** + * Draws the dynamic foreground layer + * @param {DrawParameters} parameters + */ + drawForegroundDynamicLayer(parameters) { + const systems = this.root.systemMgr.systems; + + systems.itemEjector.drawChunk(parameters, this); + systems.itemAcceptor.drawChunk(parameters, this); + systems.miner.drawChunk(parameters, this); + } + + /** + * Draws the static foreground layer + * @param {DrawParameters} parameters + */ + drawForegroundStaticLayer(parameters) { + const systems = this.root.systemMgr.systems; + + systems.staticMapEntities.drawChunk(parameters, this); + systems.lever.drawChunk(parameters, this); + systems.display.drawChunk(parameters, this); + systems.storage.drawChunk(parameters, this); + systems.itemProcessorOverlays.drawChunk(parameters, this); + } + + /** + * Overlay + * @param {DrawParameters} parameters + */ + drawOverlay(parameters) { + const overlaySize = globalConfig.mapChunkSize * CHUNK_OVERLAY_RES; + const sprite = this.root.buffers.getForKey({ + key: "chunk@" + this.root.currentLayer, + subKey: this.renderKey, + w: overlaySize, + h: overlaySize, + dpi: 1, + redrawMethod: this.generateOverlayBuffer.bind(this), + }); + + const dims = globalConfig.mapChunkWorldSize; + + // Draw chunk "pixel" art + parameters.context.imageSmoothingEnabled = false; + drawSpriteClipped({ + parameters, + sprite, + x: this.x * dims, + y: this.y * dims, + w: dims, + h: dims, + originalW: overlaySize, + originalH: overlaySize, + }); + + parameters.context.imageSmoothingEnabled = true; + + // Draw patch items + if (this.root.currentLayer === "regular") { + for (let i = 0; i < this.patches.length; ++i) { + const patch = this.patches[i]; + + const destX = this.x * dims + patch.pos.x * globalConfig.tileSize; + const destY = this.y * dims + patch.pos.y * globalConfig.tileSize; + const diameter = Math.min(80, 30 / parameters.zoomLevel); + + patch.item.drawItemCenteredClipped(destX, destY, parameters, diameter); + } + } + } + + /** + * + * @param {HTMLCanvasElement} canvas + * @param {CanvasRenderingContext2D} context + * @param {number} w + * @param {number} h + * @param {number} dpi + */ + generateOverlayBuffer(canvas, context, w, h, dpi) { + context.fillStyle = + this.containedEntities.length > 0 + ? THEME.map.chunkOverview.filled + : THEME.map.chunkOverview.empty; + context.fillRect(0, 0, w, h); + + if (this.root.app.settings.getAllSettings().displayChunkBorders) { + context.fillStyle = THEME.map.chunkBorders; + context.fillRect(0, 0, w, 1); + context.fillRect(0, 1, 1, h); + } + + for (let x = 0; x < globalConfig.mapChunkSize; ++x) { + const lowerArray = this.lowerLayer[x]; + const upperArray = this.contents[x]; + for (let y = 0; y < globalConfig.mapChunkSize; ++y) { + const upperContent = upperArray[y]; + if (upperContent) { + const staticComp = upperContent.components.StaticMapEntity; + const data = getBuildingDataFromCode(staticComp.code); + const metaBuilding = data.metaInstance; + + const overlayMatrix = metaBuilding.getSpecialOverlayRenderMatrix( + staticComp.rotation, + data.rotationVariant, + data.variant, + upperContent + ); + + if (overlayMatrix) { + // Draw lower content first since it "shines" through + const lowerContent = lowerArray[y]; + if (lowerContent) { + context.fillStyle = lowerContent.getBackgroundColorAsResource(); + context.fillRect( + x * CHUNK_OVERLAY_RES, + y * CHUNK_OVERLAY_RES, + CHUNK_OVERLAY_RES, + CHUNK_OVERLAY_RES + ); + } + + context.fillStyle = metaBuilding.getSilhouetteColor(); + for (let dx = 0; dx < 3; ++dx) { + for (let dy = 0; dy < 3; ++dy) { + const isFilled = overlayMatrix[dx + dy * 3]; + if (isFilled) { + context.fillRect( + x * CHUNK_OVERLAY_RES + dx, + y * CHUNK_OVERLAY_RES + dy, + 1, + 1 + ); + } + } + } + + continue; + } else { + context.fillStyle = metaBuilding.getSilhouetteColor(); + context.fillRect( + x * CHUNK_OVERLAY_RES, + y * CHUNK_OVERLAY_RES, + CHUNK_OVERLAY_RES, + CHUNK_OVERLAY_RES + ); + + continue; + } + } + + const lowerContent = lowerArray[y]; + if (lowerContent) { + context.fillStyle = lowerContent.getBackgroundColorAsResource(); + context.fillRect( + x * CHUNK_OVERLAY_RES, + y * CHUNK_OVERLAY_RES, + CHUNK_OVERLAY_RES, + CHUNK_OVERLAY_RES + ); + } + } + } + + if (this.root.currentLayer === "wires") { + // Draw wires overlay + + context.fillStyle = THEME.map.wires.overlayColor; + context.fillRect(0, 0, w, h); + + for (let x = 0; x < globalConfig.mapChunkSize; ++x) { + const wiresArray = this.wireContents[x]; + for (let y = 0; y < globalConfig.mapChunkSize; ++y) { + const content = wiresArray[y]; + if (!content) { + continue; + } + MapChunkView.drawSingleWiresOverviewTile({ + context, + x: x * CHUNK_OVERLAY_RES, + y: y * CHUNK_OVERLAY_RES, + entity: content, + tileSizePixels: CHUNK_OVERLAY_RES, + }); + } + } + } + } + + /** + * @param {object} param0 + * @param {CanvasRenderingContext2D} param0.context + * @param {number} param0.x + * @param {number} param0.y + * @param {Entity} param0.entity + * @param {number} param0.tileSizePixels + * @param {string=} param0.overrideColor Optionally override the color to be rendered + */ + static drawSingleWiresOverviewTile({ context, x, y, entity, tileSizePixels, overrideColor = null }) { + const staticComp = entity.components.StaticMapEntity; + const data = getBuildingDataFromCode(staticComp.code); + const metaBuilding = data.metaInstance; + const overlayMatrix = metaBuilding.getSpecialOverlayRenderMatrix( + staticComp.rotation, + data.rotationVariant, + data.variant, + entity + ); + context.fillStyle = overrideColor || metaBuilding.getSilhouetteColor(); + if (overlayMatrix) { + for (let dx = 0; dx < 3; ++dx) { + for (let dy = 0; dy < 3; ++dy) { + const isFilled = overlayMatrix[dx + dy * 3]; + if (isFilled) { + context.fillRect( + x + (dx * tileSizePixels) / CHUNK_OVERLAY_RES, + y + (dy * tileSizePixels) / CHUNK_OVERLAY_RES, + tileSizePixels / CHUNK_OVERLAY_RES, + tileSizePixels / CHUNK_OVERLAY_RES + ); + } + } + } + } else { + context.fillRect(x, y, tileSizePixels, tileSizePixels); + } + } + + /** + * Draws the wires layer + * @param {DrawParameters} parameters + */ + drawWiresForegroundLayer(parameters) { + const systems = this.root.systemMgr.systems; + systems.wire.drawChunk(parameters, this); + systems.staticMapEntities.drawWiresChunk(parameters, this); + systems.wiredPins.drawChunk(parameters, this); + } +} diff --git a/src/js/game/map_view.js b/src/js/game/map_view.js index bd10755c..0e0f3d5b 100644 --- a/src/js/game/map_view.js +++ b/src/js/game/map_view.js @@ -1,254 +1,216 @@ -import { globalConfig } from "../core/config"; -import { DrawParameters } from "../core/draw_parameters"; -import { BaseMap } from "./map"; -import { freeCanvas, makeOffscreenBuffer } from "../core/buffer_utils"; -import { Entity } from "./entity"; -import { THEME } from "./theme"; -import { MapChunkView } from "./map_chunk_view"; - -/** - * This is the view of the map, it extends the map which is the raw model and allows - * to draw it - */ -export class MapView extends BaseMap { - constructor(root) { - super(root); - - /** - * DPI of the background cache images, required in some places - */ - this.backgroundCacheDPI = 2; - - /** - * The cached background sprite, containing the flat background - * @type {HTMLCanvasElement} */ - this.cachedBackgroundCanvas = null; - - /** @type {CanvasRenderingContext2D} */ - this.cachedBackgroundContext = null; - /** - * Cached pattern of the stripes background - * @type {CanvasPattern} */ - this.cachedBackgroundPattern = null; - - this.internalInitializeCachedBackgroundCanvases(); - this.root.signals.aboutToDestruct.add(this.cleanup, this); - - this.root.signals.entityAdded.add(this.onEntityChanged, this); - this.root.signals.entityDestroyed.add(this.onEntityChanged, this); - this.root.signals.entityChanged.add(this.onEntityChanged, this); - } - - cleanup() { - freeCanvas(this.cachedBackgroundCanvas); - this.cachedBackgroundCanvas = null; - this.cachedBackgroundPattern = null; - } - - /** - * Called when an entity was added, removed or changed - * @param {Entity} entity - */ - onEntityChanged(entity) { - const staticComp = entity.components.StaticMapEntity; - if (staticComp) { - const rect = staticComp.getTileSpaceBounds(); - for (let x = rect.x; x <= rect.right(); ++x) { - for (let y = rect.y; y <= rect.bottom(); ++y) { - this.root.map.getOrCreateChunkAtTile(x, y).markDirty(); - } - } - } - } - - /** - * Draws all static entities like buildings etc. - * @param {DrawParameters} drawParameters - */ - drawStaticEntityDebugOverlays(drawParameters) { - const cullRange = drawParameters.visibleRect.toTileCullRectangle(); - const top = cullRange.top(); - const right = cullRange.right(); - const bottom = cullRange.bottom(); - const left = cullRange.left(); - - const border = 1; - - const minY = top - border; - const maxY = bottom + border; - const minX = left - border; - const maxX = right + border - 1; - - // Render y from top down for proper blending - for (let y = minY; y <= maxY; ++y) { - for (let x = minX; x <= maxX; ++x) { - // const content = this.tiles[x][y]; - const chunk = this.getChunkAtTileOrNull(x, y); - if (!chunk) { - continue; - } - const content = chunk.getTileContentFromWorldCoords(x, y); - if (content) { - let isBorder = x <= left - 1 || x >= right + 1 || y <= top - 1 || y >= bottom + 1; - if (!isBorder) { - content.drawDebugOverlays(drawParameters); - } - } - } - } - } - - /** - * Initializes all canvases used for background rendering - */ - internalInitializeCachedBackgroundCanvases() { - // Background canvas - const dims = globalConfig.tileSize; - const dpi = this.backgroundCacheDPI; - const [canvas, context] = makeOffscreenBuffer(dims * dpi, dims * dpi, { - smooth: false, - label: "map-cached-bg", - }); - context.scale(dpi, dpi); - - context.fillStyle = THEME.map.background; - context.fillRect(0, 0, dims, dims); - - const borderWidth = THEME.map.gridLineWidth; - context.fillStyle = THEME.map.grid; - context.fillRect(0, 0, dims, borderWidth); - context.fillRect(0, borderWidth, borderWidth, dims); - - context.fillRect(dims - borderWidth, borderWidth, borderWidth, dims - 2 * borderWidth); - context.fillRect(borderWidth, dims - borderWidth, dims, borderWidth); - - this.cachedBackgroundCanvas = canvas; - this.cachedBackgroundContext = context; - } - - /** - * Draws the maps foreground - * @param {DrawParameters} parameters - */ - drawForeground(parameters) { - this.drawVisibleChunks(parameters, MapChunkView.prototype.drawForegroundLayer); - } - - /** - * Calls a given method on all given chunks - * @param {DrawParameters} parameters - * @param {function} method - */ - drawVisibleChunks(parameters, method) { - const cullRange = parameters.visibleRect.toTileCullRectangle(); - const top = cullRange.top(); - const right = cullRange.right(); - const bottom = cullRange.bottom(); - const left = cullRange.left(); - - const border = 1; - const minY = top - border; - const maxY = bottom + border; - const minX = left - border; - const maxX = right + border - 1; - - const chunkStartX = Math.floor(minX / globalConfig.mapChunkSize); - const chunkStartY = Math.floor(minY / globalConfig.mapChunkSize); - - const chunkEndX = Math.ceil(maxX / globalConfig.mapChunkSize); - const chunkEndY = Math.ceil(maxY / globalConfig.mapChunkSize); - - // Render y from top down for proper blending - for (let chunkX = chunkStartX; chunkX <= chunkEndX; ++chunkX) { - for (let chunkY = chunkStartY; chunkY <= chunkEndY; ++chunkY) { - const chunk = this.root.map.getChunk(chunkX, chunkY, true); - method.call(chunk, parameters); - } - } - } - - /** - * Draws the wires background - * @param {DrawParameters} parameters - */ - drawWiresLayer(parameters) { - this.drawVisibleChunks(parameters, MapChunkView.prototype.drawWiresLayer); - } - - /** - * Draws the wires foreground - * @param {DrawParameters} parameters - */ - drawWiresForegroundLayer(parameters) { - this.drawVisibleChunks(parameters, MapChunkView.prototype.drawWiresForegroundLayer); - } - - /** - * Draws the map background - * @param {DrawParameters} parameters - */ - drawBackground(parameters) { - // If not using prerendered, draw background - if (parameters.zoomLevel > globalConfig.mapChunkPrerenderMinZoom) { - if (!this.cachedBackgroundPattern) { - this.cachedBackgroundPattern = parameters.context.createPattern( - this.cachedBackgroundCanvas, - "repeat" - ); - } - - const dpi = this.backgroundCacheDPI; - parameters.context.scale(1 / dpi, 1 / dpi); - - parameters.context.fillStyle = this.cachedBackgroundPattern; - parameters.context.fillRect( - parameters.visibleRect.x * dpi, - parameters.visibleRect.y * dpi, - parameters.visibleRect.w * dpi, - parameters.visibleRect.h * dpi - ); - parameters.context.scale(dpi, dpi); - } - - this.drawVisibleChunks(parameters, MapChunkView.prototype.drawBackgroundLayer); - - if (G_IS_DEV && globalConfig.debug.showChunkBorders) { - const cullRange = parameters.visibleRect.toTileCullRectangle(); - const top = cullRange.top(); - const right = cullRange.right(); - const bottom = cullRange.bottom(); - const left = cullRange.left(); - - const border = 1; - const minY = top - border; - const maxY = bottom + border; - const minX = left - border; - const maxX = right + border - 1; - - const chunkStartX = Math.floor(minX / globalConfig.mapChunkSize); - const chunkStartY = Math.floor(minY / globalConfig.mapChunkSize); - - const chunkEndX = Math.ceil(maxX / globalConfig.mapChunkSize); - const chunkEndY = Math.ceil(maxY / globalConfig.mapChunkSize); - - // Render y from top down for proper blending - for (let chunkX = chunkStartX; chunkX <= chunkEndX; ++chunkX) { - for (let chunkY = chunkStartY; chunkY <= chunkEndY; ++chunkY) { - parameters.context.fillStyle = "#ffaaaa"; - parameters.context.fillRect( - chunkX * globalConfig.mapChunkSize * globalConfig.tileSize, - chunkY * globalConfig.mapChunkSize * globalConfig.tileSize, - globalConfig.mapChunkSize * globalConfig.tileSize, - 3 - ); - parameters.context.fillRect( - chunkX * globalConfig.mapChunkSize * globalConfig.tileSize, - chunkY * globalConfig.mapChunkSize * globalConfig.tileSize, - 3, - globalConfig.mapChunkSize * globalConfig.tileSize - ); - } - } - } - } -} +import { globalConfig } from "../core/config"; +import { DrawParameters } from "../core/draw_parameters"; +import { BaseMap } from "./map"; +import { freeCanvas, makeOffscreenBuffer } from "../core/buffer_utils"; +import { Entity } from "./entity"; +import { THEME } from "./theme"; +import { MapChunkView } from "./map_chunk_view"; + +/** + * This is the view of the map, it extends the map which is the raw model and allows + * to draw it + */ +export class MapView extends BaseMap { + constructor(root) { + super(root); + + /** + * DPI of the background cache images, required in some places + */ + this.backgroundCacheDPI = 2; + + /** + * The cached background sprite, containing the flat background + * @type {HTMLCanvasElement} */ + this.cachedBackgroundCanvas = null; + + /** @type {CanvasRenderingContext2D} */ + this.cachedBackgroundContext = null; + /** + * Cached pattern of the stripes background + * @type {CanvasPattern} */ + this.cachedBackgroundPattern = null; + + this.internalInitializeCachedBackgroundCanvases(); + this.root.signals.aboutToDestruct.add(this.cleanup, this); + + this.root.signals.entityAdded.add(this.onEntityChanged, this); + this.root.signals.entityDestroyed.add(this.onEntityChanged, this); + this.root.signals.entityChanged.add(this.onEntityChanged, this); + } + + cleanup() { + freeCanvas(this.cachedBackgroundCanvas); + this.cachedBackgroundCanvas = null; + this.cachedBackgroundPattern = null; + } + + /** + * Called when an entity was added, removed or changed + * @param {Entity} entity + */ + onEntityChanged(entity) { + const staticComp = entity.components.StaticMapEntity; + if (staticComp) { + const rect = staticComp.getTileSpaceBounds(); + for (let x = rect.x; x <= rect.right(); ++x) { + for (let y = rect.y; y <= rect.bottom(); ++y) { + this.root.map.getOrCreateChunkAtTile(x, y).markDirty(); + } + } + } + } + + /** + * Draws all static entities like buildings etc. + * @param {DrawParameters} drawParameters + */ + drawStaticEntityDebugOverlays(drawParameters) { + const cullRange = drawParameters.visibleRect.toTileCullRectangle(); + const top = cullRange.top(); + const right = cullRange.right(); + const bottom = cullRange.bottom(); + const left = cullRange.left(); + + const border = 1; + + const minY = top - border; + const maxY = bottom + border; + const minX = left - border; + const maxX = right + border - 1; + + // Render y from top down for proper blending + for (let y = minY; y <= maxY; ++y) { + for (let x = minX; x <= maxX; ++x) { + // const content = this.tiles[x][y]; + const chunk = this.getChunkAtTileOrNull(x, y); + if (!chunk) { + continue; + } + const content = chunk.getTileContentFromWorldCoords(x, y); + if (content) { + let isBorder = x <= left - 1 || x >= right + 1 || y <= top - 1 || y >= bottom + 1; + if (!isBorder) { + content.drawDebugOverlays(drawParameters); + } + } + } + } + } + + /** + * Initializes all canvases used for background rendering + */ + internalInitializeCachedBackgroundCanvases() { + // Background canvas + const dims = globalConfig.tileSize; + const dpi = this.backgroundCacheDPI; + const [canvas, context] = makeOffscreenBuffer(dims * dpi, dims * dpi, { + smooth: false, + label: "map-cached-bg", + }); + context.scale(dpi, dpi); + + context.fillStyle = THEME.map.background; + context.fillRect(0, 0, dims, dims); + + const borderWidth = THEME.map.gridLineWidth; + context.fillStyle = THEME.map.grid; + context.fillRect(0, 0, dims, borderWidth); + context.fillRect(0, borderWidth, borderWidth, dims); + + context.fillRect(dims - borderWidth, borderWidth, borderWidth, dims - 2 * borderWidth); + context.fillRect(borderWidth, dims - borderWidth, dims, borderWidth); + + this.cachedBackgroundCanvas = canvas; + this.cachedBackgroundContext = context; + } + + /** + * Draws the maps foreground + * @param {DrawParameters} parameters + */ + drawForeground(parameters) { + this.drawVisibleChunks(parameters, MapChunkView.prototype.drawForegroundDynamicLayer); + this.drawVisibleChunks(parameters, MapChunkView.prototype.drawForegroundStaticLayer); + } + + /** + * Calls a given method on all given chunks + * @param {DrawParameters} parameters + * @param {function} method + */ + drawVisibleChunks(parameters, method) { + const cullRange = parameters.visibleRect.allScaled(1 / globalConfig.tileSize); + const top = cullRange.top(); + const right = cullRange.right(); + const bottom = cullRange.bottom(); + const left = cullRange.left(); + + const border = 0; + const minY = top - border; + const maxY = bottom + border; + const minX = left - border; + const maxX = right + border; + + const chunkStartX = Math.floor(minX / globalConfig.mapChunkSize); + const chunkStartY = Math.floor(minY / globalConfig.mapChunkSize); + + const chunkEndX = Math.floor(maxX / globalConfig.mapChunkSize); + const chunkEndY = Math.floor(maxY / globalConfig.mapChunkSize); + + // Render y from top down for proper blending + for (let chunkX = chunkStartX; chunkX <= chunkEndX; ++chunkX) { + for (let chunkY = chunkStartY; chunkY <= chunkEndY; ++chunkY) { + const chunk = this.root.map.getChunk(chunkX, chunkY, true); + method.call(chunk, parameters); + } + } + } + + /** + * Draws the wires foreground + * @param {DrawParameters} parameters + */ + drawWiresForegroundLayer(parameters) { + this.drawVisibleChunks(parameters, MapChunkView.prototype.drawWiresForegroundLayer); + } + + /** + * Draws the map overlay + * @param {DrawParameters} parameters + */ + drawOverlay(parameters) { + this.drawVisibleChunks(parameters, MapChunkView.prototype.drawOverlay); + } + + /** + * Draws the map background + * @param {DrawParameters} parameters + */ + drawBackground(parameters) { + if (!this.cachedBackgroundPattern) { + this.cachedBackgroundPattern = parameters.context.createPattern( + this.cachedBackgroundCanvas, + "repeat" + ); + } + + // Render tile grid + if (!this.root.app.settings.getAllSettings().disableTileGrid) { + const dpi = this.backgroundCacheDPI; + parameters.context.scale(1 / dpi, 1 / dpi); + + parameters.context.fillStyle = this.cachedBackgroundPattern; + parameters.context.fillRect( + parameters.visibleRect.x * dpi, + parameters.visibleRect.y * dpi, + parameters.visibleRect.w * dpi, + parameters.visibleRect.h * dpi + ); + parameters.context.scale(dpi, dpi); + } + + this.drawVisibleChunks(parameters, MapChunkView.prototype.drawBackgroundLayer); + } +} diff --git a/src/js/game/meta_building.js b/src/js/game/meta_building.js index 514474c9..b09e901e 100644 --- a/src/js/game/meta_building.js +++ b/src/js/game/meta_building.js @@ -4,7 +4,8 @@ import { Vector } from "../core/vector"; import { SOUNDS } from "../platform/sound"; import { StaticMapEntityComponent } from "./components/static_map_entity"; import { Entity } from "./entity"; -import { enumLayer, GameRoot } from "./root"; +import { GameRoot } from "./root"; +import { getCodeFromBuildingData } from "./building_codes"; export const defaultBuildingVariant = "default"; @@ -26,10 +27,10 @@ export class MetaBuilding { /** * Returns the edit layer of the building - * @returns {enumLayer} + * @returns {Layer} */ getLayer() { - return enumLayer.regular; + return "regular"; } /** @@ -53,6 +54,18 @@ export class MetaBuilding { return false; } + /** + * Can return a special interlaved 9 elements overlay matrix for rendering + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + * @returns {Array|null} + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return null; + } + /** * Should return additional statistics about this building * @param {GameRoot} root @@ -63,6 +76,13 @@ export class MetaBuilding { return []; } + /** + * Returns whether this building can get replaced + */ + getIsReplaceable() { + return false; + } + /** * Whether to flip the orientation after a building has been placed - useful * for tunnels. @@ -71,6 +91,13 @@ export class MetaBuilding { return false; } + /** + * Whether to show a preview of the wires layer when placing the building + */ + getShowWiresLayerPreview() { + return false; + } + /** * Whether to rotate automatically in the dragging direction while placing * @param {string} variant @@ -79,6 +106,14 @@ export class MetaBuilding { return false; } + /** + * Returns whether this building is removable + * @returns {boolean} + */ + getIsRemovable() { + return true; + } + /** * Returns the placement sound * @returns {string} @@ -125,7 +160,7 @@ export class MetaBuilding { * @param {string} variant * @returns {boolean} */ - isRotateable(variant) { + getIsRotateable(variant) { return true; } @@ -144,6 +179,14 @@ export class MetaBuilding { return null; } + /** + * Should return false if the pins are already included in the sprite of the building + * @returns {boolean} + */ + getRenderPins() { + return true; + } + /** * Creates the entity without placing it * @param {object} param0 @@ -157,20 +200,13 @@ export class MetaBuilding { createEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) { const entity = new Entity(root); entity.layer = this.getLayer(); - const blueprintSprite = this.getBlueprintSprite(rotationVariant, variant); entity.addComponent( new StaticMapEntityComponent({ - spriteKey: - "sprites/buildings/" + - this.id + - (variant === defaultBuildingVariant ? "" : "-" + variant) + - ".png", origin: new Vector(origin.x, origin.y), rotation, originalRotation, tileSize: this.getDimensions(variant).copy(), - silhouetteColor: this.getSilhouetteColor(), - blueprintSpriteKey: blueprintSprite ? blueprintSprite.spriteName : "", + code: getCodeFromBuildingData(this, variant, rotationVariant), }) ); this.setupEntityComponents(entity, root); @@ -178,6 +214,21 @@ export class MetaBuilding { return entity; } + /** + * Returns the sprite for a given variant + * @param {number} rotationVariant + * @param {string} variant + * @returns {AtlasSprite} + */ + getSprite(rotationVariant, variant) { + return Loader.getSprite( + "sprites/buildings/" + + this.id + + (variant === defaultBuildingVariant ? "" : "-" + variant) + + ".png" + ); + } + /** * Should compute the optimal rotation variant on the given tile * @param {object} param0 @@ -185,11 +236,11 @@ export class MetaBuilding { * @param {Vector} param0.tile * @param {number} param0.rotation * @param {string} param0.variant - * @param {string} param0.layer + * @param {Layer} param0.layer * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array }} */ computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { - if (!this.isRotateable(variant)) { + if (!this.getIsRotateable(variant)) { return { rotation: 0, rotationVariant: 0, diff --git a/src/js/game/meta_building_registry.js b/src/js/game/meta_building_registry.js index 4e1fdd81..647e55f5 100644 --- a/src/js/game/meta_building_registry.js +++ b/src/js/game/meta_building_registry.js @@ -1,35 +1,178 @@ -import { gMetaBuildingRegistry } from "../core/global_registries"; -import { MetaBeltBaseBuilding } from "./buildings/belt_base"; -import { MetaCutterBuilding } from "./buildings/cutter"; -import { MetaMinerBuilding } from "./buildings/miner"; -import { MetaMixerBuilding } from "./buildings/mixer"; -import { MetaPainterBuilding } from "./buildings/painter"; -import { MetaRotaterBuilding } from "./buildings/rotater"; -import { MetaSplitterBuilding } from "./buildings/splitter"; -import { MetaStackerBuilding } from "./buildings/stacker"; -import { MetaTrashBuilding } from "./buildings/trash"; -import { MetaUndergroundBeltBuilding } from "./buildings/underground_belt"; -import { MetaHubBuilding } from "./buildings/hub"; -import { MetaEnergyGenerator } from "./buildings/energy_generator"; -import { MetaWireBaseBuilding } from "./buildings/wire_base"; -import { MetaAdvancedProcessorBuilding } from "./buildings/advanced_processor"; -import { MetaBeltBuilding } from "./buildings/belt"; -import { MetaWireCrossingsBuilding } from "./buildings/wire_crossings"; - -export function initMetaBuildingRegistry() { - gMetaBuildingRegistry.register(MetaSplitterBuilding); - gMetaBuildingRegistry.register(MetaMinerBuilding); - gMetaBuildingRegistry.register(MetaCutterBuilding); - gMetaBuildingRegistry.register(MetaRotaterBuilding); - gMetaBuildingRegistry.register(MetaStackerBuilding); - gMetaBuildingRegistry.register(MetaMixerBuilding); - gMetaBuildingRegistry.register(MetaPainterBuilding); - gMetaBuildingRegistry.register(MetaTrashBuilding); - gMetaBuildingRegistry.register(MetaBeltBuilding); - gMetaBuildingRegistry.register(MetaUndergroundBeltBuilding); - gMetaBuildingRegistry.register(MetaHubBuilding); - gMetaBuildingRegistry.register(MetaEnergyGenerator); - gMetaBuildingRegistry.register(MetaWireBaseBuilding); - gMetaBuildingRegistry.register(MetaAdvancedProcessorBuilding); - gMetaBuildingRegistry.register(MetaWireCrossingsBuilding); -} +import { gMetaBuildingRegistry } from "../core/global_registries"; +import { createLogger } from "../core/logging"; +import { MetaBeltBuilding } from "./buildings/belt"; +import { MetaBeltBaseBuilding } from "./buildings/belt_base"; +import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter"; +import { MetaHubBuilding } from "./buildings/hub"; +import { enumMinerVariants, MetaMinerBuilding } from "./buildings/miner"; +import { MetaMixerBuilding } from "./buildings/mixer"; +import { enumPainterVariants, MetaPainterBuilding } from "./buildings/painter"; +import { enumRotaterVariants, MetaRotaterBuilding } from "./buildings/rotater"; +import { enumSplitterVariants, MetaSplitterBuilding } from "./buildings/splitter"; +import { MetaStackerBuilding } from "./buildings/stacker"; +import { enumTrashVariants, MetaTrashBuilding } from "./buildings/trash"; +import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt"; +import { MetaWireBuilding } from "./buildings/wire"; +import { gBuildingVariants, registerBuildingVariant } from "./building_codes"; +import { defaultBuildingVariant } from "./meta_building"; +import { MetaConstantSignalBuilding } from "./buildings/constant_signal"; +import { MetaLogicGateBuilding, enumLogicGateVariants } from "./buildings/logic_gate"; +import { MetaLeverBuilding } from "./buildings/lever"; +import { MetaFilterBuilding } from "./buildings/filter"; +import { MetaWireTunnelBuilding, enumWireTunnelVariants } from "./buildings/wire_tunnel"; +import { MetaDisplayBuilding } from "./buildings/display"; +import { MetaVirtualProcessorBuilding, enumVirtualProcessorVariants } from "./buildings/virtual_processor"; +import { MetaReaderBuilding } from "./buildings/reader"; + +const logger = createLogger("building_registry"); + +export function initMetaBuildingRegistry() { + gMetaBuildingRegistry.register(MetaSplitterBuilding); + gMetaBuildingRegistry.register(MetaMinerBuilding); + gMetaBuildingRegistry.register(MetaCutterBuilding); + gMetaBuildingRegistry.register(MetaRotaterBuilding); + gMetaBuildingRegistry.register(MetaStackerBuilding); + gMetaBuildingRegistry.register(MetaMixerBuilding); + gMetaBuildingRegistry.register(MetaPainterBuilding); + gMetaBuildingRegistry.register(MetaTrashBuilding); + gMetaBuildingRegistry.register(MetaBeltBuilding); + gMetaBuildingRegistry.register(MetaUndergroundBeltBuilding); + gMetaBuildingRegistry.register(MetaHubBuilding); + gMetaBuildingRegistry.register(MetaWireBuilding); + gMetaBuildingRegistry.register(MetaConstantSignalBuilding); + gMetaBuildingRegistry.register(MetaLogicGateBuilding); + gMetaBuildingRegistry.register(MetaLeverBuilding); + gMetaBuildingRegistry.register(MetaFilterBuilding); + gMetaBuildingRegistry.register(MetaWireTunnelBuilding); + gMetaBuildingRegistry.register(MetaDisplayBuilding); + gMetaBuildingRegistry.register(MetaVirtualProcessorBuilding); + gMetaBuildingRegistry.register(MetaReaderBuilding); + + // Belt + registerBuildingVariant(1, MetaBeltBaseBuilding, defaultBuildingVariant, 0); + registerBuildingVariant(2, MetaBeltBaseBuilding, defaultBuildingVariant, 1); + registerBuildingVariant(3, MetaBeltBaseBuilding, defaultBuildingVariant, 2); + + // Splitter + registerBuildingVariant(4, MetaSplitterBuilding); + registerBuildingVariant(5, MetaSplitterBuilding, enumSplitterVariants.compact); + registerBuildingVariant(6, MetaSplitterBuilding, enumSplitterVariants.compactInverse); + registerBuildingVariant(47, MetaSplitterBuilding, enumSplitterVariants.compactMerge); + registerBuildingVariant(48, MetaSplitterBuilding, enumSplitterVariants.compactMergeInverse); + + // Miner + registerBuildingVariant(7, MetaMinerBuilding); + registerBuildingVariant(8, MetaMinerBuilding, enumMinerVariants.chainable); + + // Cutter + registerBuildingVariant(9, MetaCutterBuilding); + registerBuildingVariant(10, MetaCutterBuilding, enumCutterVariants.quad); + + // Rotater + registerBuildingVariant(11, MetaRotaterBuilding); + registerBuildingVariant(12, MetaRotaterBuilding, enumRotaterVariants.ccw); + registerBuildingVariant(13, MetaRotaterBuilding, enumRotaterVariants.fl); + + // Stacker + registerBuildingVariant(14, MetaStackerBuilding); + + // Mixer + registerBuildingVariant(15, MetaMixerBuilding); + + // Painter + registerBuildingVariant(16, MetaPainterBuilding); + registerBuildingVariant(17, MetaPainterBuilding, enumPainterVariants.mirrored); + registerBuildingVariant(18, MetaPainterBuilding, enumPainterVariants.double); + registerBuildingVariant(19, MetaPainterBuilding, enumPainterVariants.quad); + + // Trash + registerBuildingVariant(20, MetaTrashBuilding); + registerBuildingVariant(21, MetaTrashBuilding, enumTrashVariants.storage); + + // Underground belt + registerBuildingVariant(22, MetaUndergroundBeltBuilding, defaultBuildingVariant, 0); + registerBuildingVariant(23, MetaUndergroundBeltBuilding, defaultBuildingVariant, 1); + registerBuildingVariant(24, MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2, 0); + registerBuildingVariant(25, MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2, 1); + + // Hub + registerBuildingVariant(26, MetaHubBuilding); + + // Wire + registerBuildingVariant(27, MetaWireBuilding, defaultBuildingVariant, 0); + registerBuildingVariant(28, MetaWireBuilding, defaultBuildingVariant, 1); + registerBuildingVariant(29, MetaWireBuilding, defaultBuildingVariant, 2); + registerBuildingVariant(30, MetaWireBuilding, defaultBuildingVariant, 3); + + // Constant signal + registerBuildingVariant(31, MetaConstantSignalBuilding); + + // Logic gate + registerBuildingVariant(32, MetaLogicGateBuilding); + registerBuildingVariant(34, MetaLogicGateBuilding, enumLogicGateVariants.not); + registerBuildingVariant(35, MetaLogicGateBuilding, enumLogicGateVariants.xor); + registerBuildingVariant(36, MetaLogicGateBuilding, enumLogicGateVariants.or); + registerBuildingVariant(38, MetaLogicGateBuilding, enumLogicGateVariants.transistor); + + // Lever + registerBuildingVariant(33, MetaLeverBuilding); + + // Filter + registerBuildingVariant(37, MetaFilterBuilding); + + // Wire tunnel + registerBuildingVariant(39, MetaWireTunnelBuilding); + registerBuildingVariant(41, MetaWireTunnelBuilding, enumWireTunnelVariants.coating); + + // Display + registerBuildingVariant(40, MetaDisplayBuilding); + + // Virtual Processor + registerBuildingVariant(42, MetaVirtualProcessorBuilding); + registerBuildingVariant(43, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.analyzer); + registerBuildingVariant(44, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.rotater); + registerBuildingVariant(45, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.unstacker); + registerBuildingVariant(46, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.shapecompare); + + // Reader + registerBuildingVariant(49, MetaReaderBuilding); + + // Propagate instances + for (const key in gBuildingVariants) { + gBuildingVariants[key].metaInstance = gMetaBuildingRegistry.findByClass( + gBuildingVariants[key].metaClass + ); + } + + for (const key in gBuildingVariants) { + const variant = gBuildingVariants[key]; + assert(variant.metaClass, "Variant has no meta: " + key); + + if (typeof variant.rotationVariant === "undefined") { + variant.rotationVariant = 0; + } + if (typeof variant.variant === "undefined") { + variant.variant = defaultBuildingVariant; + } + } + + logger.log("Registered", gMetaBuildingRegistry.getNumEntries(), "buildings"); + logger.log("Registered", Object.keys(gBuildingVariants).length, "building codes"); +} + +/** + * Once all sprites are loaded, propagates the cache + */ +export function initBuildingCodesAfterResourcesLoaded() { + logger.log("Propagating sprite cache"); + for (const key in gBuildingVariants) { + const variant = gBuildingVariants[key]; + + variant.sprite = variant.metaInstance.getSprite(variant.rotationVariant, variant.variant); + variant.blueprintSprite = variant.metaInstance.getBlueprintSprite( + variant.rotationVariant, + variant.variant + ); + variant.silhouetteColor = variant.metaInstance.getSilhouetteColor(); + } +} diff --git a/src/js/game/production_analytics.js b/src/js/game/production_analytics.js index 41ec31ae..eda79c83 100644 --- a/src/js/game/production_analytics.js +++ b/src/js/game/production_analytics.js @@ -1,7 +1,7 @@ import { GameRoot } from "./root"; import { ShapeDefinition } from "./shape_definition"; import { globalConfig } from "../core/config"; -import { BaseItem, enumItemType } from "./base_item"; +import { BaseItem } from "./base_item"; import { ShapeItem } from "./items/shape_item"; import { BasicSerializableObject } from "../savegame/serialization"; @@ -53,7 +53,7 @@ export class ProductionAnalytics extends BasicSerializableObject { * @param {BaseItem} item */ onItemProduced(item) { - if (item.getItemType() === enumItemType.shape) { + if (item.getItemType() === "shape") { const definition = /** @type {ShapeItem} */ (item).definition; const key = definition.getHash(); const entry = this.history[enumAnalyticsDataSource.produced]; diff --git a/src/js/game/root.js b/src/js/game/root.js index df0db09e..dd224dd8 100644 --- a/src/js/game/root.js +++ b/src/js/game/root.js @@ -1,5 +1,4 @@ /* eslint-disable no-unused-vars */ - import { Signal } from "../core/signal"; import { RandomNumberGenerator } from "../core/rng"; import { createLogger } from "../core/logging"; @@ -32,14 +31,8 @@ import { Vector } from "../core/vector"; const logger = createLogger("game/root"); -/** @enum {string} */ -export const enumLayer = { - regular: "regular", - wires: "wires", -}; - -/** @type {Array} */ -export const arrayLayers = [enumLayer.regular, enumLayer.wires]; +/** @type {Array} */ +export const layers = ["regular", "wires"]; /** * The game root is basically the whole game state at a given point, @@ -134,8 +127,8 @@ export class GameRoot { /** @type {DynamicTickrate} */ this.dynamicTickrate = null; - /** @type {enumLayer} */ - this.currentLayer = enumLayer.regular; + /** @type {Layer} */ + this.currentLayer = "regular"; this.signals = { // Entities @@ -156,21 +149,20 @@ export class GameRoot { gameSaved: /** @type {TypedSignal<[]>} */ (new Signal()), // Game got saved gameRestored: /** @type {TypedSignal<[]>} */ (new Signal()), // Game got restored + gameFrameStarted: /** @type {TypedSignal<[]>} */ (new Signal()), // New frame + storyGoalCompleted: /** @type {TypedSignal<[number, string]>} */ (new Signal()), upgradePurchased: /** @type {TypedSignal<[string]>} */ (new Signal()), // Called right after game is initialized postLoadHook: /** @type {TypedSignal<[]>} */ (new Signal()), - // Can be used to trigger an async task - performAsync: /** @type {TypedSignal<[function]>} */ (new Signal()), - shapeDelivered: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()), itemProduced: /** @type {TypedSignal<[BaseItem]>} */ (new Signal()), bulkOperationFinished: /** @type {TypedSignal<[]>} */ (new Signal()), - editModeChanged: /** @type {TypedSignal<[enumLayer]>} */ (new Signal()), + editModeChanged: /** @type {TypedSignal<[Layer]>} */ (new Signal()), // Called to check if an entity can be placed, second parameter is an additional offset. // Use to introduce additional placement checks diff --git a/src/js/game/shape_definition.js b/src/js/game/shape_definition.js index af2214e3..65b72a1a 100644 --- a/src/js/game/shape_definition.js +++ b/src/js/game/shape_definition.js @@ -2,22 +2,11 @@ import { makeOffscreenBuffer } from "../core/buffer_utils"; import { globalConfig } from "../core/config"; import { smoothenDpi } from "../core/dpi_manager"; import { DrawParameters } from "../core/draw_parameters"; -import { createLogger } from "../core/logging"; import { Vector } from "../core/vector"; import { BasicSerializableObject, types } from "../savegame/serialization"; -import { - enumColors, - enumColorsToHexCode, - enumColorToShortcode, - enumShortcodeToColor, - enumInvertedColors, -} from "./colors"; +import { enumColors, enumColorsToHexCode, enumColorToShortcode, enumShortcodeToColor } from "./colors"; import { THEME } from "./theme"; -const rusha = require("rusha"); - -const logger = createLogger("shape_definition"); - /** * @typedef {{ * subShape: enumSubShape, @@ -96,7 +85,7 @@ export class ShapeDefinition extends BasicSerializableObject { return errorCode; } const definition = ShapeDefinition.fromShortKey(data); - this.layers = definition.layers; + this.layers = /** @type {Array} */ (definition.layers); } serialize() { @@ -113,7 +102,8 @@ export class ShapeDefinition extends BasicSerializableObject { /** * The layers from bottom to top - * @type {Array} */ + * @type {Array} + */ this.layers = layers; /** @type {string} */ @@ -286,24 +276,25 @@ export class ShapeDefinition extends BasicSerializableObject { * @param {number} x * @param {number} y * @param {DrawParameters} parameters + * @param {number=} diameter */ - draw(x, y, parameters, size = 20) { + drawCentered(x, y, parameters, diameter = 20) { const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel); if (!this.bufferGenerator) { this.bufferGenerator = this.internalGenerateShapeBuffer.bind(this); } - const key = size + "/" + dpi; - const canvas = parameters.root.buffers.getForKey( - key, - this.cachedHash, - size, - size, + const key = diameter + "/" + dpi + "/" + this.cachedHash; + const canvas = parameters.root.buffers.getForKey({ + key: "shapedef", + subKey: key, + w: diameter, + h: diameter, dpi, - this.bufferGenerator - ); - parameters.context.drawImage(canvas, x - size / 2, y - size / 2, size, size); + redrawMethod: this.bufferGenerator, + }); + parameters.context.drawImage(canvas, x - diameter / 2, y - diameter / 2, diameter, diameter); } /** @@ -495,62 +486,88 @@ export class ShapeDefinition extends BasicSerializableObject { return new ShapeDefinition({ layers: newLayers }); } + /** + * Returns a definition which was rotated 180 degrees (flipped) + * @returns {ShapeDefinition} + */ + cloneRotateFL() { + const newLayers = this.internalCloneLayers(); + for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { + const quadrants = newLayers[layerIndex]; + quadrants.push(quadrants.shift(), quadrants.shift()); + } + return new ShapeDefinition({ layers: newLayers }); + } + /** * Stacks the given shape definition on top. * @param {ShapeDefinition} definition */ cloneAndStackWith(definition) { - const newLayers = this.internalCloneLayers(); - if (this.isEntirelyEmpty() || definition.isEntirelyEmpty()) { assert(false, "Can not stack entirely empty definition"); } - // Put layer for layer on top - for (let i = 0; i < definition.layers.length; ++i) { - const layerToAdd = definition.layers[i]; + const bottomShapeLayers = this.layers; + const bottomShapeHighestLayerByQuad = [-1, -1, -1, -1]; - // On which layer we can merge this upper layer - let mergeOnLayerIndex = null; - - // Go from top to bottom and check if there is anything intercepting it - for (let k = newLayers.length - 1; k >= 0; --k) { - const lowerLayer = newLayers[k]; - - let canMerge = true; - for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) { - const upperItem = layerToAdd[quadrantIndex]; - const lowerItem = lowerLayer[quadrantIndex]; - - if (upperItem && lowerItem) { - // so, we can't merge it because two items conflict - canMerge = false; - break; - } + for (let layer = bottomShapeLayers.length - 1; layer >= 0; --layer) { + const shapeLayer = bottomShapeLayers[layer]; + for (let quad = 0; quad < 4; ++quad) { + const shapeQuad = shapeLayer[quad]; + if (shapeQuad !== null && bottomShapeHighestLayerByQuad[quad] < layer) { + bottomShapeHighestLayerByQuad[quad] = layer; } - - // If we can merge it, store it - since we go from top to bottom - // we can simply override it - if (canMerge) { - mergeOnLayerIndex = k; - } - } - - if (mergeOnLayerIndex !== null) { - // Simply merge using an OR mask - for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) { - newLayers[mergeOnLayerIndex][quadrantIndex] = - newLayers[mergeOnLayerIndex][quadrantIndex] || layerToAdd[quadrantIndex]; - } - } else { - // Add new layer - newLayers.push(layerToAdd); } } - newLayers.splice(4); + const topShapeLayers = definition.layers; + const topShapeLowestLayerByQuad = [4, 4, 4, 4]; - return new ShapeDefinition({ layers: newLayers }); + for (let layer = 0; layer < topShapeLayers.length; ++layer) { + const shapeLayer = topShapeLayers[layer]; + for (let quad = 0; quad < 4; ++quad) { + const shapeQuad = shapeLayer[quad]; + if (shapeQuad !== null && topShapeLowestLayerByQuad[quad] > layer) { + topShapeLowestLayerByQuad[quad] = layer; + } + } + } + + /** + * We want to find the number `layerToMergeAt` such that when the top shape is placed at that + * layer, the smallest gap between shapes is only 1. Instead of doing a guess-and-check method to + * find the appropriate layer, we just calculate all the gaps assuming a merge at layer 0, even + * though they go negative, and calculating the number to add to it so the minimum gap is 1 (ends + * up being 1 - minimum). + */ + const gapsBetweenShapes = []; + for (let quad = 0; quad < 4; ++quad) { + gapsBetweenShapes.push(topShapeLowestLayerByQuad[quad] - bottomShapeHighestLayerByQuad[quad]); + } + const smallestGapBetweenShapes = Math.min(...gapsBetweenShapes); + // Can't merge at a layer lower than 0 + const layerToMergeAt = Math.max(1 - smallestGapBetweenShapes, 0); + + const mergedLayers = this.internalCloneLayers(); + for (let layer = mergedLayers.length; layer < layerToMergeAt + topShapeLayers.length; ++layer) { + mergedLayers.push([null, null, null, null]); + } + + for (let layer = 0; layer < topShapeLayers.length; ++layer) { + const layerMergingAt = layerToMergeAt + layer; + const bottomShapeLayer = mergedLayers[layerMergingAt]; + const topShapeLayer = topShapeLayers[layer]; + for (let quad = 0; quad < 4; quad++) { + assert(!(bottomShapeLayer[quad] && topShapeLayer[quad]), "Shape merge: Sub shape got lost"); + bottomShapeLayer[quad] = bottomShapeLayer[quad] || topShapeLayer[quad]; + } + } + + // Limit to 4 layers at max + mergedLayers.splice(4); + + return new ShapeDefinition({ layers: mergedLayers }); } /** @@ -572,23 +589,6 @@ export class ShapeDefinition extends BasicSerializableObject { return new ShapeDefinition({ layers: newLayers }); } - /** - * Clones the shape and inverts all colors - */ - cloneAndInvertColors() { - const newLayers = this.internalCloneLayers(); - for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { - const quadrants = newLayers[layerIndex]; - for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) { - const item = quadrants[quadrantIndex]; - if (item) { - item.color = enumInvertedColors[item.color]; - } - } - } - return new ShapeDefinition({ layers: newLayers }); - } - /** * Clones the shape and colors everything in the given colors * @param {[enumColors, enumColors, enumColors, enumColors]} colors @@ -601,7 +601,7 @@ export class ShapeDefinition extends BasicSerializableObject { for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) { const item = quadrants[quadrantIndex]; if (item) { - item.color = colors[quadrantIndex]; + item.color = colors[quadrantIndex] || item.color; } } } diff --git a/src/js/game/shape_definition_manager.js b/src/js/game/shape_definition_manager.js index bebb4592..ef0d592f 100644 --- a/src/js/game/shape_definition_manager.js +++ b/src/js/game/shape_definition_manager.js @@ -1,8 +1,9 @@ -import { BasicSerializableObject } from "../savegame/serialization"; -import { GameRoot } from "./root"; -import { ShapeDefinition, enumSubShape } from "./shape_definition"; import { createLogger } from "../core/logging"; +import { BasicSerializableObject } from "../savegame/serialization"; import { enumColors } from "./colors"; +import { ShapeItem } from "./items/shape_item"; +import { GameRoot } from "./root"; +import { enumSubShape, ShapeDefinition } from "./shape_definition"; const logger = createLogger("shape_definition_manager"); @@ -19,15 +20,24 @@ export class ShapeDefinitionManager extends BasicSerializableObject { super(); this.root = root; + /** + * Store a cache from key -> definition + * @type {Object} + */ this.shapeKeyToDefinition = {}; + /** + * Store a cache from key -> item + */ + this.shapeKeyToItem = {}; + // Caches operations in the form of 'operation:def1[:def2]' /** @type {Object.|ShapeDefinition>} */ this.operationCache = {}; } /** - * + * Returns a shape instance from a given short key * @param {string} hash * @returns {ShapeDefinition} */ @@ -39,6 +49,29 @@ export class ShapeDefinitionManager extends BasicSerializableObject { return (this.shapeKeyToDefinition[hash] = ShapeDefinition.fromShortKey(hash)); } + /** + * Returns a item instance from a given short key + * @param {string} hash + * @returns {ShapeItem} + */ + getShapeItemFromShortKey(hash) { + const cached = this.shapeKeyToItem[hash]; + if (cached) { + return cached; + } + const definition = this.getShapeFromShortKey(hash); + return (this.shapeKeyToItem[hash] = new ShapeItem(definition)); + } + + /** + * Returns a shape item for a given definition + * @param {ShapeDefinition} definition + * @returns {ShapeItem} + */ + getShapeItemFromDefinition(definition) { + return this.getShapeItemFromShortKey(definition.getHash()); + } + /** * Registers a new shape definition * @param {ShapeDefinition} definition @@ -127,6 +160,24 @@ export class ShapeDefinitionManager extends BasicSerializableObject { )); } + /** + * Generates a definition for rotating a shape counter clockwise + * @param {ShapeDefinition} definition + * @returns {ShapeDefinition} + */ + shapeActionRotateFL(definition) { + const key = "rotate-fl:" + definition.getHash(); + if (this.operationCache[key]) { + return /** @type {ShapeDefinition} */ (this.operationCache[key]); + } + + const rotated = definition.cloneRotateFL(); + + return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( + rotated + )); + } + /** * Generates a definition for stacking the upper definition onto the lower one * @param {ShapeDefinition} lowerDefinition @@ -161,22 +212,6 @@ export class ShapeDefinitionManager extends BasicSerializableObject { )); } - /** - * Generates a definition for inverting all colors on that shape - * @param {ShapeDefinition} definition - * @returns {ShapeDefinition} - */ - shapeActionInvertColors(definition) { - const key = "invert:" + definition.getHash(); - if (this.operationCache[key]) { - return /** @type {ShapeDefinition} */ (this.operationCache[key]); - } - const inverted = definition.cloneAndInvertColors(); - return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( - inverted - )); - } - /** * Generates a definition for painting it with the 4 colors * @param {ShapeDefinition} definition diff --git a/src/js/game/systems/belt.js b/src/js/game/systems/belt.js index db538a56..4d8151f6 100644 --- a/src/js/game/systems/belt.js +++ b/src/js/game/systems/belt.js @@ -13,11 +13,9 @@ import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; import { MapChunkView } from "../map_chunk_view"; import { defaultBuildingVariant } from "../meta_building"; -import { enumLayer } from "../root"; -import { MetaWireBaseBuilding } from "../buildings/wire_base"; -import { enumItemType } from "../base_item"; +import { getCodeFromBuildingData } from "../building_codes"; -export const BELT_ANIM_COUNT = 28; +export const BELT_ANIM_COUNT = 14; const logger = createLogger("belt"); @@ -31,18 +29,9 @@ export class BeltSystem extends GameSystemWithFilter { * @type {Object.>} */ this.beltSprites = { - [enumDirection.top]: Loader.getSprite("sprites/belt/forward_0.png"), - [enumDirection.left]: Loader.getSprite("sprites/belt/left_0.png"), - [enumDirection.right]: Loader.getSprite("sprites/belt/right_0.png"), - }; - - /** - * @type {Object.>} - */ - this.wireSprites = { - [enumDirection.top]: Loader.getSprite("sprites/buildings/wire_top.png"), - [enumDirection.left]: Loader.getSprite("sprites/buildings/wire_left.png"), - [enumDirection.right]: Loader.getSprite("sprites/buildings/wire_right.png"), + [enumDirection.top]: Loader.getSprite("sprites/belt/built/forward_0.png"), + [enumDirection.left]: Loader.getSprite("sprites/belt/built/left_0.png"), + [enumDirection.right]: Loader.getSprite("sprites/belt/built/right_0.png"), }; /** @@ -56,11 +45,13 @@ export class BeltSystem extends GameSystemWithFilter { for (let i = 0; i < BELT_ANIM_COUNT; ++i) { this.beltAnimations[enumDirection.top].push( - Loader.getSprite("sprites/belt/forward_" + i + ".png") + Loader.getSprite("sprites/belt/built/forward_" + i + ".png") + ); + this.beltAnimations[enumDirection.left].push( + Loader.getSprite("sprites/belt/built/left_" + i + ".png") ); - this.beltAnimations[enumDirection.left].push(Loader.getSprite("sprites/belt/left_" + i + ".png")); this.beltAnimations[enumDirection.right].push( - Loader.getSprite("sprites/belt/right_" + i + ".png") + Loader.getSprite("sprites/belt/built/right_" + i + ".png") ); } @@ -137,6 +128,9 @@ export class BeltSystem extends GameSystemWithFilter { const originalRect = staticComp.getTileSpaceBounds(); const affectedArea = originalRect.expandedInAllDirections(1); + /** @type {Set} */ + const changedPaths = new Set(); + for (let x = affectedArea.x; x < affectedArea.right(); ++x) { for (let y = affectedArea.y; y < affectedArea.bottom(); ++y) { if (originalRect.containsPoint(x, y)) { @@ -178,6 +172,13 @@ export class BeltSystem extends GameSystemWithFilter { targetStaticComp.rotation = rotation; metaBelt.updateVariants(targetEntity, rotationVariant, defaultBuildingVariant); + // Update code as well + targetStaticComp.code = getCodeFromBuildingData( + metaBelt, + defaultBuildingVariant, + rotationVariant + ); + // Now add it again this.addEntityToPaths(targetEntity); @@ -189,10 +190,17 @@ export class BeltSystem extends GameSystemWithFilter { // Make sure the chunks know about the update this.root.signals.entityChanged.dispatch(targetEntity); } + + if (targetBeltComp.assignedPath) { + changedPaths.add(targetBeltComp.assignedPath); + } } } } + // notify all paths *afterwards* to avoid multi-updates + changedPaths.forEach(path => path.onSurroundingsChanged()); + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { this.debug_verifyBeltPaths(); } @@ -310,14 +318,10 @@ export class BeltSystem extends GameSystemWithFilter { /** * Draws all belt paths * @param {DrawParameters} parameters - * @param {enumLayer} layer */ - drawLayerBeltItems(parameters, layer) { + drawBeltItems(parameters) { for (let i = 0; i < this.beltPaths.length; ++i) { - const path = this.beltPaths[i]; - if (path.layer === layer) { - path.draw(parameters); - } + this.beltPaths[i].draw(parameters); } } @@ -361,24 +365,10 @@ export class BeltSystem extends GameSystemWithFilter { const followUpBeltComp = followUpEntity.components.Belt; if (followUpBeltComp) { const followUpStatic = followUpEntity.components.StaticMapEntity; - const followUpAcceptor = followUpEntity.components.ItemAcceptor; - // Check if the belt accepts items from our direction - const acceptorSlots = followUpAcceptor.slots; - for (let i = 0; i < acceptorSlots.length; ++i) { - const slot = acceptorSlots[i]; - - // Make sure the acceptor slot is on the same layer - if (slot.layer !== entity.layer) { - continue; - } - - for (let k = 0; k < slot.directions.length; ++k) { - const localDirection = followUpStatic.localDirectionToWorld(slot.directions[k]); - if (enumInvertedDirections[localDirection] === followUpDirection) { - return followUpEntity; - } - } + const acceptedDirection = followUpStatic.localDirectionToWorld(enumDirection.top); + if (acceptedDirection === followUpDirection) { + return followUpEntity; } } } @@ -405,21 +395,12 @@ export class BeltSystem extends GameSystemWithFilter { const supplyBeltComp = supplyEntity.components.Belt; if (supplyBeltComp) { const supplyStatic = supplyEntity.components.StaticMapEntity; - const supplyEjector = supplyEntity.components.ItemEjector; + const otherDirection = supplyStatic.localDirectionToWorld( + enumInvertedDirections[supplyBeltComp.direction] + ); - // Check if the belt accepts items from our direction - const ejectorSlots = supplyEjector.slots; - for (let i = 0; i < ejectorSlots.length; ++i) { - const slot = ejectorSlots[i]; - - // Make sure the ejector slot is on the same layer - if (slot.layer !== entity.layer) { - continue; - } - const localDirection = supplyStatic.localDirectionToWorld(slot.direction); - if (enumInvertedDirections[localDirection] === supplyDirection) { - return supplyEntity; - } + if (otherDirection === supplyDirection) { + return supplyEntity; } } } @@ -505,65 +486,24 @@ export class BeltSystem extends GameSystemWithFilter { * @param {MapChunkView} chunk */ drawChunk(parameters, chunk) { - if (parameters.zoomLevel < globalConfig.mapChunkOverviewMinZoom) { - return; - } - // Limit speed to avoid belts going backwards - const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(enumLayer.regular), 10); + const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(), 10); // SYNC with systems/item_acceptor.js:drawEntityUnderlays! // 126 / 42 is the exact animation speed of the png animation const animationIndex = Math.floor( ((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) * - globalConfig.beltItemSpacingByLayer[enumLayer.regular] + globalConfig.itemSpacingOnBelts ); - const contents = chunk.contents; - for (let y = 0; y < globalConfig.mapChunkSize; ++y) { - for (let x = 0; x < globalConfig.mapChunkSize; ++x) { - const entity = contents[x][y]; + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + if (entity.components.Belt) { + const direction = entity.components.Belt.direction; + const sprite = this.beltAnimations[direction][animationIndex % BELT_ANIM_COUNT]; - if (entity && entity.components.Belt) { - const direction = entity.components.Belt.direction; - const sprite = this.beltAnimations[direction][animationIndex % BELT_ANIM_COUNT]; - - entity.components.StaticMapEntity.drawSpriteOnFullEntityBounds( - parameters, - sprite, - 0, - false - ); - } - } - } - 1; - } - - /** - * Draws a given chunk - * @param {DrawParameters} parameters - * @param {MapChunkView} chunk - */ - drawWiresChunk(parameters, chunk) { - if (parameters.zoomLevel < globalConfig.mapChunkOverviewMinZoom) { - return; - } - - const contents = chunk.wireContents; - for (let y = 0; y < globalConfig.mapChunkSize; ++y) { - for (let x = 0; x < globalConfig.mapChunkSize; ++x) { - const entity = contents[x][y]; - - if (entity && entity.components.Belt) { - const direction = entity.components.Belt.direction; - const sprite = this.wireSprites[direction]; - entity.components.StaticMapEntity.drawSpriteOnFullEntityBounds( - parameters, - sprite, - 0, - false - ); - } + // Culling happens within the static map entity component + entity.components.StaticMapEntity.drawSpriteOnBoundsClipped(parameters, sprite, 0); } } } diff --git a/src/js/game/systems/belt_reader.js b/src/js/game/systems/belt_reader.js new file mode 100644 index 00000000..abddd999 --- /dev/null +++ b/src/js/game/systems/belt_reader.js @@ -0,0 +1,55 @@ +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { BeltReaderComponent } from "../components/belt_reader"; +import { globalConfig } from "../../core/config"; +import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON } from "../items/boolean_item"; + +export class BeltReaderSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [BeltReaderComponent]); + } + + update() { + const now = this.root.time.now(); + const minimumTime = now - globalConfig.readerAnalyzeIntervalSeconds; + const minimumTimeForThroughput = now - 1; + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + + const readerComp = entity.components.BeltReader; + const pinsComp = entity.components.WiredPins; + + // Remove outdated items + while (readerComp.lastItemTimes[0] < minimumTime) { + readerComp.lastItemTimes.shift(); + } + + pinsComp.slots[1].value = readerComp.lastItem; + pinsComp.slots[0].value = + (readerComp.lastItemTimes[readerComp.lastItemTimes.length - 1] || 0) > + minimumTimeForThroughput + ? BOOL_TRUE_SINGLETON + : BOOL_FALSE_SINGLETON; + + if (now - readerComp.lastThroughputComputation > 0.5) { + // Compute throughput + readerComp.lastThroughputComputation = now; + + let throughput = 0; + if (readerComp.lastItemTimes.length < 2) { + throughput = 0; + } else { + let averageSpacing = 0; + let averageSpacingNum = 0; + for (let i = 0; i < readerComp.lastItemTimes.length - 1; ++i) { + averageSpacing += readerComp.lastItemTimes[i + 1] - readerComp.lastItemTimes[i]; + ++averageSpacingNum; + } + + throughput = 1 / (averageSpacing / averageSpacingNum); + } + + readerComp.lastThroughput = throughput; + } + } + } +} diff --git a/src/js/game/systems/belt_underlays.js b/src/js/game/systems/belt_underlays.js new file mode 100644 index 00000000..5bdf2331 --- /dev/null +++ b/src/js/game/systems/belt_underlays.js @@ -0,0 +1,84 @@ +import { globalConfig } from "../../core/config"; +import { drawRotatedSprite } from "../../core/draw_utils"; +import { Loader } from "../../core/loader"; +import { enumDirectionToAngle } from "../../core/vector"; +import { BeltUnderlaysComponent } from "../components/belt_underlays"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { BELT_ANIM_COUNT } from "./belt"; +import { MapChunkView } from "../map_chunk_view"; +import { DrawParameters } from "../../core/draw_parameters"; + +export class BeltUnderlaysSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [BeltUnderlaysComponent]); + + this.underlayBeltSprites = []; + + for (let i = 0; i < BELT_ANIM_COUNT; ++i) { + this.underlayBeltSprites.push(Loader.getSprite("sprites/belt/built/forward_" + i + ".png")); + } + } + + /** + * Draws a given chunk + * @param {DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + // Limit speed to avoid belts going backwards + const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(), 10); + + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const underlayComp = entity.components.BeltUnderlays; + if (!underlayComp) { + continue; + } + + const staticComp = entity.components.StaticMapEntity; + const underlays = underlayComp.underlays; + for (let i = 0; i < underlays.length; ++i) { + const { pos, direction } = underlays[i]; + const transformedPos = staticComp.localTileToWorld(pos); + + // Culling + if (!chunk.tileSpaceRectangle.containsPoint(transformedPos.x, transformedPos.y)) { + continue; + } + + const destX = transformedPos.x * globalConfig.tileSize; + const destY = transformedPos.y * globalConfig.tileSize; + + // Culling, #2 + if ( + !parameters.visibleRect.containsRect4Params( + destX, + destY, + globalConfig.tileSize, + globalConfig.tileSize + ) + ) { + continue; + } + + const angle = enumDirectionToAngle[staticComp.localDirectionToWorld(direction)]; + + // SYNC with systems/belt.js:drawSingleEntity! + const animationIndex = Math.floor( + ((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) * + globalConfig.itemSpacingOnBelts + ); + + drawRotatedSprite({ + parameters, + sprite: this.underlayBeltSprites[animationIndex % this.underlayBeltSprites.length], + x: destX + globalConfig.halfTileSize, + y: destY + globalConfig.halfTileSize, + angle: Math.radians(angle), + size: globalConfig.tileSize, + }); + } + } + } +} diff --git a/src/js/game/systems/constant_signal.js b/src/js/game/systems/constant_signal.js new file mode 100644 index 00000000..93417ef5 --- /dev/null +++ b/src/js/game/systems/constant_signal.js @@ -0,0 +1,135 @@ +import trim from "trim"; +import { DialogWithForm } from "../../core/modal_dialog_elements"; +import { FormElementInput } from "../../core/modal_dialog_forms"; +import { BaseItem } from "../base_item"; +import { enumColors } from "../colors"; +import { ConstantSignalComponent } from "../components/constant_signal"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { BOOL_FALSE_SINGLETON, BOOL_TRUE_SINGLETON } from "../items/boolean_item"; +import { COLOR_ITEM_SINGLETONS } from "../items/color_item"; +import { ShapeDefinition } from "../shape_definition"; + +export class ConstantSignalSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [ConstantSignalComponent]); + + this.root.signals.entityManuallyPlaced.add(this.querySigalValue, this); + } + + update() { + // Set signals + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + const pinsComp = entity.components.WiredPins; + const signalComp = entity.components.ConstantSignal; + pinsComp.slots[0].value = signalComp.signal; + } + } + + /** + * Asks the entity to enter a valid signal code + * @param {Entity} entity + */ + querySigalValue(entity) { + if (!entity.components.ConstantSignal) { + return; + } + + // Ok, query, but also save the uid because it could get stale + const uid = entity.uid; + + const signalValueInput = new FormElementInput({ + id: "signalValue", + label: null, + placeholder: "", + defaultValue: "", + validator: val => this.parseSignalCode(val), + }); + const dialog = new DialogWithForm({ + app: this.root.app, + title: "Set Signal", + desc: "Enter a shape code, color or '0' or '1'", + formElements: [signalValueInput], + buttons: ["cancel:bad:escape", "ok:good:enter"], + closeButton: false, + }); + this.root.hud.parts.dialogs.internalShowDialog(dialog); + + // When confirmed, set the signal + dialog.buttonSignals.ok.add(() => { + if (!this.root || !this.root.entityMgr) { + // Game got stopped + return; + } + + const entityRef = this.root.entityMgr.findByUid(uid, false); + if (!entityRef) { + // outdated + return; + } + + const constantComp = entityRef.components.ConstantSignal; + if (!constantComp) { + // no longer interesting + return; + } + + constantComp.signal = this.parseSignalCode(signalValueInput.getValue()); + }); + + // When cancelled, destroy the entity again + dialog.buttonSignals.cancel.add(() => { + if (!this.root || !this.root.entityMgr) { + // Game got stopped + return; + } + + const entityRef = this.root.entityMgr.findByUid(uid, false); + if (!entityRef) { + // outdated + return; + } + + const constantComp = entityRef.components.ConstantSignal; + if (!constantComp) { + // no longer interesting + return; + } + + this.root.logic.tryDeleteBuilding(entityRef); + }); + } + + /** + * Tries to parse a signal code + * @param {string} code + * @returns {BaseItem} + */ + parseSignalCode(code) { + if (!this.root || !this.root.shapeDefinitionMgr) { + // Stale reference + return null; + } + + code = trim(code); + const codeLower = code.toLowerCase(); + + if (enumColors[codeLower]) { + return COLOR_ITEM_SINGLETONS[codeLower]; + } + if (code === "1" || codeLower === "true") { + return BOOL_TRUE_SINGLETON; + } + + if (code === "0" || codeLower === "false") { + return BOOL_FALSE_SINGLETON; + } + + if (ShapeDefinition.isValidShortKey(code)) { + return this.root.shapeDefinitionMgr.getShapeItemFromShortKey(code); + } + + return null; + } +} diff --git a/src/js/game/systems/display.js b/src/js/game/systems/display.js new file mode 100644 index 00000000..2ad551f0 --- /dev/null +++ b/src/js/game/systems/display.js @@ -0,0 +1,97 @@ +import { globalConfig } from "../../core/config"; +import { Loader } from "../../core/loader"; +import { BaseItem } from "../base_item"; +import { enumColors } from "../colors"; +import { DisplayComponent } from "../components/display"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { isTrueItem } from "../items/boolean_item"; +import { ColorItem, COLOR_ITEM_SINGLETONS } from "../items/color_item"; +import { MapChunkView } from "../map_chunk_view"; + +export class DisplaySystem extends GameSystemWithFilter { + constructor(root) { + super(root, [DisplayComponent]); + + /** @type {Object} */ + this.displaySprites = {}; + + for (const colorId in enumColors) { + if (colorId === enumColors.uncolored) { + continue; + } + this.displaySprites[colorId] = Loader.getSprite("sprites/wires/display/" + colorId + ".png"); + } + } + + /** + * Returns the color / value a display should show + * @param {BaseItem} value + * @returns {BaseItem} + */ + getDisplayItem(value) { + if (!value) { + return null; + } + + switch (value.getItemType()) { + case "boolean": { + return isTrueItem(value) ? COLOR_ITEM_SINGLETONS[enumColors.white] : null; + } + + case "color": { + const item = /**@type {ColorItem} */ (value); + return item.color === enumColors.uncolored ? null : item; + } + + case "shape": { + return value; + } + + default: + assertAlways(false, "Unknown item type: " + value.getItemType()); + } + } + + /** + * Draws a given chunk + * @param {import("../../core/draw_utils").DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + if (entity && entity.components.Display) { + const pinsComp = entity.components.WiredPins; + const network = pinsComp.slots[0].linkedNetwork; + + if (!network || !network.currentValue) { + continue; + } + + const value = this.getDisplayItem(network.currentValue); + + if (!value) { + continue; + } + + const origin = entity.components.StaticMapEntity.origin; + if (value.getItemType() === "color") { + this.displaySprites[/** @type {ColorItem} */ (value).color].drawCachedCentered( + parameters, + (origin.x + 0.5) * globalConfig.tileSize, + (origin.y + 0.5) * globalConfig.tileSize, + globalConfig.tileSize + ); + } else if (value.getItemType() === "shape") { + value.drawItemCenteredClipped( + (origin.x + 0.5) * globalConfig.tileSize, + (origin.y + 0.5) * globalConfig.tileSize, + parameters, + 30 + ); + } + } + } + } +} diff --git a/src/js/game/systems/energy_consumer.js b/src/js/game/systems/energy_consumer.js deleted file mode 100644 index 6552fb9a..00000000 --- a/src/js/game/systems/energy_consumer.js +++ /dev/null @@ -1,90 +0,0 @@ -import { DrawParameters } from "../../core/draw_parameters"; -import { Loader } from "../../core/loader"; -import { clamp } from "../../core/utils"; -import { enumItemType } from "../base_item"; -import { EnergyConsumerComponent } from "../components/energy_consumer"; -import { Entity } from "../entity"; -import { GameSystemWithFilter } from "../game_system_with_filter"; -import { NEGATIVE_ENERGY_ITEM_SINGLETON } from "../items/negative_energy_item"; -import { POSITIVE_ENERGY_ITEM_SINGLETON } from "../items/positive_energy_item"; - -export class EnergyConsumerSystem extends GameSystemWithFilter { - constructor(root) { - super(root, [EnergyConsumerComponent]); - - this.batterySprites = [ - Loader.getSprite("sprites/wires/battery_empty.png"), - Loader.getSprite("sprites/wires/battery_low.png"), - Loader.getSprite("sprites/wires/battery_medium.png"), - Loader.getSprite("sprites/wires/battery_full.png"), - ]; - - this.piledWasteSprite = Loader.getSprite("sprites/wires/waste_piled.png"); - } - - update() { - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - const energyConsumerComp = entity.components.EnergyConsumer; - - if (energyConsumerComp.piledOutput >= 1.0) { - // Try to get rid of waste - - const ejectorComp = entity.components.ItemEjector; - const item = this.getItemSingletonByType(energyConsumerComp.wasteType); - if (ejectorComp.tryEject(energyConsumerComp.ejectorSlotIndex, item)) { - // Got rid of waste - energyConsumerComp.reduceWaste(1.0); - } - } - } - } - - /** - * - * @param {enumItemType} itemType - */ - getItemSingletonByType(itemType) { - switch (itemType) { - case enumItemType.positiveEnergy: - return POSITIVE_ENERGY_ITEM_SINGLETON; - case enumItemType.negativeEnergy: - return NEGATIVE_ENERGY_ITEM_SINGLETON; - default: - assertAlways(false, "Bad item type: " + itemType); - } - } - - /** - * Draws everything - * @param {DrawParameters} parameters - */ - draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawSingleEntity.bind(this)); - } - - /** - * Draws a given entity - * @param {DrawParameters} parameters - * @param {Entity} entity - */ - drawSingleEntity(parameters, entity) { - const staticComp = entity.components.StaticMapEntity; - const consumerComp = entity.components.EnergyConsumer; - - const position = staticComp.localTileToWorld(consumerComp.batteryPosition).toWorldSpaceCenterOfTile(); - - if (consumerComp.hasTooMuchWastePiled()) { - this.piledWasteSprite.drawCachedCentered(parameters, position.x, position.y, 12); - } else { - const percentage = consumerComp.stored / consumerComp.bufferSize; - const index = clamp( - Math.round(percentage * this.batterySprites.length), - 0, - this.batterySprites.length - 1 - ); - - this.batterySprites[index].drawCachedCentered(parameters, position.x, position.y, 12); - } - } -} diff --git a/src/js/game/systems/energy_generator.js b/src/js/game/systems/energy_generator.js deleted file mode 100644 index 76e14c01..00000000 --- a/src/js/game/systems/energy_generator.js +++ /dev/null @@ -1,97 +0,0 @@ -import { DrawParameters } from "../../core/draw_parameters"; -import { formatBigNumber } from "../../core/utils"; -import { T } from "../../translations"; -import { EnergyGeneratorComponent } from "../components/energy_generator"; -import { Entity } from "../entity"; -import { GameSystemWithFilter } from "../game_system_with_filter"; -import { POSITIVE_ENERGY_ITEM_SINGLETON } from "../items/positive_energy_item"; -import { ShapeDefinition } from "../shape_definition"; -import { Loader } from "../../core/loader"; -import { globalConfig } from "../../core/config"; - -export class EnergyGeneratorSystem extends GameSystemWithFilter { - constructor(root) { - super(root, [EnergyGeneratorComponent]); - - this.energyGeneratorOverlay = Loader.getSprite("sprites/misc/energy_generator_overlay.png"); - } - - draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this)); - } - - /** - * Returns which shape is required for a given generator - * @param {Entity} entity - */ - getShapeRequiredForGenerator(entity) { - return "CuCuCuCu"; - } - - update() { - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - const energyGenComp = entity.components.EnergyGenerator; - const ejectorComp = entity.components.ItemEjector; - - if (!energyGenComp.requiredKey) { - // Compute required key for this generator - energyGenComp.requiredKey = this.getShapeRequiredForGenerator(entity); - } - - if (energyGenComp.itemsInQueue > 0) { - // FIXME: Find slot dynamically - if (ejectorComp.tryEject(0, POSITIVE_ENERGY_ITEM_SINGLETON)) { - energyGenComp.itemsInQueue -= 1; - } - } - } - } - - /** - * @param {DrawParameters} parameters - * @param {Entity} entity - */ - drawEntity(parameters, entity) { - const context = parameters.context; - const staticComp = entity.components.StaticMapEntity; - - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } - - const energyGenComp = entity.components.EnergyGenerator; - if (!energyGenComp.requiredKey) { - // Not initialized yet - return; - } - - const pos = staticComp.getTileSpaceBounds().getCenter().toWorldSpace(); - - const definition = ShapeDefinition.fromShortKey(energyGenComp.requiredKey); - definition.draw(pos.x, pos.y, parameters, 30); - - // Draw background - this.energyGeneratorOverlay.drawCachedCentered( - parameters, - pos.x, - pos.y, - globalConfig.tileSize * 2 + 8 - ); - - // TODO - const energyGenerated = 5; - - // deliver: Deliver - // toGenerateEnergy: For energy - context.font = "bold 9px GameFont"; - context.fillStyle = "#64666e"; - context.textAlign = "left"; - context.fillText(T.buildings.energy_generator.deliver.toUpperCase(), pos.x - 25, pos.y - 18); - context.fillText(T.buildings.energy_generator.toGenerateEnergy.toUpperCase(), pos.x - 25, pos.y + 27); - - context.font = "700 9px GameFont"; - context.fillStyle = "#dee1ea"; - context.fillText("" + formatBigNumber(energyGenerated), pos.x + 1, pos.y + 27); - } -} diff --git a/src/js/game/systems/hub.js b/src/js/game/systems/hub.js index f1d4ee28..2270f941 100644 --- a/src/js/game/systems/hub.js +++ b/src/js/game/systems/hub.js @@ -1,10 +1,18 @@ -import { GameSystemWithFilter } from "../game_system_with_filter"; -import { HubComponent } from "../components/hub"; import { DrawParameters } from "../../core/draw_parameters"; -import { Entity } from "../entity"; -import { formatBigNumber } from "../../core/utils"; import { Loader } from "../../core/loader"; +import { formatBigNumber } from "../../core/utils"; import { T } from "../../translations"; +import { HubComponent } from "../components/hub"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { globalConfig } from "../../core/config"; +import { smoothenDpi } from "../../core/dpi_manager"; +import { drawSpriteClipped } from "../../core/draw_utils"; +import { Rectangle } from "../../core/rectangle"; +import { ORIGINAL_SPRITE_SCALE } from "../../core/sprites"; + +const HUB_SIZE_TILES = 4; +const HUB_SIZE_PIXELS = HUB_SIZE_TILES * globalConfig.tileSize; export class HubSystem extends GameSystemWithFilter { constructor(root) { @@ -13,54 +21,61 @@ export class HubSystem extends GameSystemWithFilter { this.hubSprite = Loader.getSprite("sprites/buildings/hub.png"); } + /** + * @param {DrawParameters} parameters + */ draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this)); + for (let i = 0; i < this.allEntities.length; ++i) { + this.drawEntity(parameters, this.allEntities[i]); + } } update() { for (let i = 0; i < this.allEntities.length; ++i) { + // Set hub goal const entity = this.allEntities[i]; - - const hubComponent = entity.components.Hub; - - const queue = hubComponent.definitionsToAnalyze; - for (let k = 0; k < queue.length; ++k) { - const definition = queue[k]; - this.root.hubGoals.handleDefinitionDelivered(definition); - } - - hubComponent.definitionsToAnalyze = []; + const pinsComp = entity.components.WiredPins; + pinsComp.slots[0].value = this.root.shapeDefinitionMgr.getShapeItemFromDefinition( + this.root.hubGoals.currentGoal.definition + ); } } - /** - * @param {DrawParameters} parameters - * @param {Entity} entity + * + * @param {HTMLCanvasElement} canvas + * @param {CanvasRenderingContext2D} context + * @param {number} w + * @param {number} h + * @param {number} dpi */ - drawEntity(parameters, entity) { - const context = parameters.context; - const staticComp = entity.components.StaticMapEntity; + redrawHubBaseTexture(canvas, context, w, h, dpi) { + // This method is quite ugly, please ignore it! - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } + context.scale(dpi, dpi); - const pos = staticComp.getTileSpaceBounds().getCenter().toWorldSpace(); + const parameters = new DrawParameters({ + context, + visibleRect: new Rectangle(0, 0, w, h), + desiredAtlasScale: ORIGINAL_SPRITE_SCALE, + zoomLevel: dpi * 0.75, + root: this.root, + }); - // Background - staticComp.drawSpriteOnFullEntityBounds(parameters, this.hubSprite, 2.2); + context.clearRect(0, 0, w, h); + + this.hubSprite.draw(context, 0, 0, w, h); const definition = this.root.hubGoals.currentGoal.definition; - - definition.draw(pos.x - 25, pos.y - 10, parameters, 40); + definition.drawCentered(45, 58, parameters, 36); const goals = this.root.hubGoals.currentGoal; - const textOffsetX = 2; - const textOffsetY = -6; + const textOffsetX = 70; + const textOffsetY = 61; // Deliver count const delivered = this.root.hubGoals.getCurrentGoalDelivered(); + const deliveredText = "" + formatBigNumber(delivered); if (delivered > 9999) { context.font = "bold 16px GameFont"; @@ -71,52 +86,87 @@ export class HubSystem extends GameSystemWithFilter { } context.fillStyle = "#64666e"; context.textAlign = "left"; - context.fillText("" + formatBigNumber(delivered), pos.x + textOffsetX, pos.y + textOffsetY); + context.fillText(deliveredText, textOffsetX, textOffsetY); // Required context.font = "13px GameFont"; context.fillStyle = "#a4a6b0"; - context.fillText( - "/ " + formatBigNumber(goals.required), - pos.x + textOffsetX, - pos.y + textOffsetY + 13 - ); + context.fillText("/ " + formatBigNumber(goals.required), textOffsetX, textOffsetY + 13); // Reward const rewardText = T.storyRewards[goals.reward].title.toUpperCase(); if (rewardText.length > 12) { - context.font = "bold 9px GameFont"; + context.font = "bold 8px GameFont"; } else { - context.font = "bold 11px GameFont"; + context.font = "bold 10px GameFont"; } context.fillStyle = "#fd0752"; context.textAlign = "center"; - context.fillText(rewardText, pos.x, pos.y + 46); + context.fillText(rewardText, HUB_SIZE_PIXELS / 2, 105); - // Level - context.font = "bold 11px GameFont"; + // Level "8" + context.font = "bold 10px GameFont"; context.fillStyle = "#fff"; - context.fillText("" + this.root.hubGoals.level, pos.x - 42, pos.y - 36); + context.fillText("" + this.root.hubGoals.level, 27, 32); - // Texts + // "LVL" context.textAlign = "center"; context.fillStyle = "#fff"; - context.font = "bold 7px GameFont"; - context.fillText(T.buildings.hub.levelShortcut, pos.x - 42, pos.y - 47); + context.font = "bold 6px GameFont"; + context.fillText(T.buildings.hub.levelShortcut, 27, 22); + // "Deliver" context.fillStyle = "#64666e"; - context.font = "bold 11px GameFont"; - context.fillText(T.buildings.hub.deliver.toUpperCase(), pos.x, pos.y - 40); + context.font = "bold 10px GameFont"; + context.fillText(T.buildings.hub.deliver.toUpperCase(), HUB_SIZE_PIXELS / 2, 30); + // "To unlock" const unlockText = T.buildings.hub.toUnlock.toUpperCase(); if (unlockText.length > 15) { context.font = "bold 8px GameFont"; } else { - context.font = "bold 11px GameFont"; + context.font = "bold 10px GameFont"; } - context.fillText(T.buildings.hub.toUnlock.toUpperCase(), pos.x, pos.y + 30); + context.fillText(T.buildings.hub.toUnlock.toUpperCase(), HUB_SIZE_PIXELS / 2, 92); context.textAlign = "left"; } + + /** + * @param {DrawParameters} parameters + * @param {Entity} entity + */ + drawEntity(parameters, entity) { + const staticComp = entity.components.StaticMapEntity; + if (!staticComp.shouldBeDrawn(parameters)) { + return; + } + + // Deliver count + const delivered = this.root.hubGoals.getCurrentGoalDelivered(); + const deliveredText = "" + formatBigNumber(delivered); + + const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel); + const canvas = parameters.root.buffers.getForKey({ + key: "hub", + subKey: dpi + "/" + this.root.hubGoals.level + "/" + deliveredText, + w: globalConfig.tileSize * 4, + h: globalConfig.tileSize * 4, + dpi, + redrawMethod: this.redrawHubBaseTexture.bind(this), + }); + + const extrude = 8; + drawSpriteClipped({ + parameters, + sprite: canvas, + x: staticComp.origin.x * globalConfig.tileSize - extrude, + y: staticComp.origin.y * globalConfig.tileSize - extrude, + w: HUB_SIZE_PIXELS + 2 * extrude, + h: HUB_SIZE_PIXELS + 2 * extrude, + originalW: HUB_SIZE_PIXELS * dpi, + originalH: HUB_SIZE_PIXELS * dpi, + }); + } } diff --git a/src/js/game/systems/item_acceptor.js b/src/js/game/systems/item_acceptor.js index 2c0f1686..6d6fec77 100644 --- a/src/js/game/systems/item_acceptor.js +++ b/src/js/game/systems/item_acceptor.js @@ -1,152 +1,80 @@ -import { GameSystemWithFilter } from "../game_system_with_filter"; -import { globalConfig } from "../../core/config"; -import { DrawParameters } from "../../core/draw_parameters"; -import { Entity } from "../entity"; -import { enumDirectionToVector, enumDirectionToAngle } from "../../core/vector"; -import { ItemAcceptorComponent } from "../components/item_acceptor"; -import { Loader } from "../../core/loader"; -import { drawRotatedSprite } from "../../core/draw_utils"; -import { BELT_ANIM_COUNT } from "./belt"; -import { fastArrayDelete } from "../../core/utils"; -import { enumLayer } from "../root"; - -export class ItemAcceptorSystem extends GameSystemWithFilter { - constructor(root) { - super(root, [ItemAcceptorComponent]); - - this.underlayBeltSprites = []; - - for (let i = 0; i < BELT_ANIM_COUNT; ++i) { - this.underlayBeltSprites.push(Loader.getSprite("sprites/belt/forward_" + i + ".png")); - } - } - - update() { - const progress = this.root.dynamicTickrate.deltaSeconds * 2; // * 2 because its only a half tile - - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - const aceptorComp = entity.components.ItemAcceptor; - const animations = aceptorComp.itemConsumptionAnimations; - - // Process item consumption animations to avoid items popping from the belts - for (let animIndex = 0; animIndex < animations.length; ++animIndex) { - const anim = animations[animIndex]; - const layer = aceptorComp.slots[anim.slotIndex].layer; - anim.animProgress += - progress * - this.root.hubGoals.getBeltBaseSpeed(layer) * - globalConfig.beltItemSpacingByLayer[layer]; - if (anim.animProgress > 1) { - // Original - // animations.splice(animIndex, 1); - - // Faster variant - fastArrayDelete(animations, animIndex); - - animIndex -= 1; - } - } - } - } - - /** - * Draws the acceptor items - * @param {DrawParameters} parameters - * @param {enumLayer} layer - */ - drawLayer(parameters, layer) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntityRegularLayer.bind(this, layer)); - } - - /** - * Draws the acceptor underlays - * @param {DrawParameters} parameters - * @param {enumLayer} layer - */ - drawUnderlays(parameters, layer) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntityUnderlays.bind(this, layer)); - } - - /** - * @param {enumLayer} layer - * @param {DrawParameters} parameters - * @param {Entity} entity - */ - drawEntityRegularLayer(layer, parameters, entity) { - const staticComp = entity.components.StaticMapEntity; - const acceptorComp = entity.components.ItemAcceptor; - - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } - - for (let animIndex = 0; animIndex < acceptorComp.itemConsumptionAnimations.length; ++animIndex) { - const { item, slotIndex, animProgress, direction } = acceptorComp.itemConsumptionAnimations[ - animIndex - ]; - - const slotData = acceptorComp.slots[slotIndex]; - if (slotData.layer !== layer) { - // Don't draw non-regular slots for now - continue; - } - - const slotWorldPos = staticComp.applyRotationToVector(slotData.pos).add(staticComp.origin); - const fadeOutDirection = enumDirectionToVector[staticComp.localDirectionToWorld(direction)]; - const finalTile = slotWorldPos.subScalars( - fadeOutDirection.x * (animProgress / 2 - 0.5), - fadeOutDirection.y * (animProgress / 2 - 0.5) - ); - item.draw( - (finalTile.x + 0.5) * globalConfig.tileSize, - (finalTile.y + 0.5) * globalConfig.tileSize, - parameters - ); - } - } - - /** - * @param {enumLayer} layer - * @param {DrawParameters} parameters - * @param {Entity} entity - */ - drawEntityUnderlays(layer, parameters, entity) { - const staticComp = entity.components.StaticMapEntity; - const acceptorComp = entity.components.ItemAcceptor; - - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } - - // Limit speed to avoid belts going backwards - const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(layer), 10); - - const underlays = acceptorComp.beltUnderlays; - for (let i = 0; i < underlays.length; ++i) { - const { pos, direction, layer: underlayLayer } = underlays[i]; - if (underlayLayer !== layer) { - // Not our layer - continue; - } - - const transformedPos = staticComp.localTileToWorld(pos); - const angle = enumDirectionToAngle[staticComp.localDirectionToWorld(direction)]; - - // SYNC with systems/belt.js:drawSingleEntity! - const animationIndex = Math.floor( - ((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) * - globalConfig.beltItemSpacingByLayer[layer] - ); - - drawRotatedSprite({ - parameters, - sprite: this.underlayBeltSprites[animationIndex % this.underlayBeltSprites.length], - x: (transformedPos.x + 0.5) * globalConfig.tileSize, - y: (transformedPos.y + 0.5) * globalConfig.tileSize, - angle: Math.radians(angle), - size: globalConfig.tileSize, - }); - } - } -} +import { globalConfig } from "../../core/config"; +import { DrawParameters } from "../../core/draw_parameters"; +import { fastArrayDelete } from "../../core/utils"; +import { enumDirectionToVector } from "../../core/vector"; +import { ItemAcceptorComponent } from "../components/item_acceptor"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { MapChunkView } from "../map_chunk_view"; + +export class ItemAcceptorSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [ItemAcceptorComponent]); + } + + update() { + const progress = + this.root.dynamicTickrate.deltaSeconds * + 2 * + this.root.hubGoals.getBeltBaseSpeed() * + globalConfig.itemSpacingOnBelts; // * 2 because its only a half tile + + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + const aceptorComp = entity.components.ItemAcceptor; + const animations = aceptorComp.itemConsumptionAnimations; + + // Process item consumption animations to avoid items popping from the belts + for (let animIndex = 0; animIndex < animations.length; ++animIndex) { + const anim = animations[animIndex]; + anim.animProgress += progress; + if (anim.animProgress > 1) { + fastArrayDelete(animations, animIndex); + animIndex -= 1; + } + } + } + } + + /** + * @param {DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const acceptorComp = entity.components.ItemAcceptor; + if (!acceptorComp) { + continue; + } + + const staticComp = entity.components.StaticMapEntity; + for (let animIndex = 0; animIndex < acceptorComp.itemConsumptionAnimations.length; ++animIndex) { + const { item, slotIndex, animProgress, direction } = acceptorComp.itemConsumptionAnimations[ + animIndex + ]; + + const slotData = acceptorComp.slots[slotIndex]; + const realSlotPos = staticComp.localTileToWorld(slotData.pos); + + if (!chunk.tileSpaceRectangle.containsPoint(realSlotPos.x, realSlotPos.y)) { + // Not within this chunk + continue; + } + + const fadeOutDirection = enumDirectionToVector[staticComp.localDirectionToWorld(direction)]; + const finalTile = realSlotPos.subScalars( + fadeOutDirection.x * (animProgress / 2 - 0.5), + fadeOutDirection.y * (animProgress / 2 - 0.5) + ); + + item.drawItemCenteredClipped( + (finalTile.x + 0.5) * globalConfig.tileSize, + (finalTile.y + 0.5) * globalConfig.tileSize, + parameters, + globalConfig.defaultItemDiameter + ); + } + } + } +} diff --git a/src/js/game/systems/item_ejector.js b/src/js/game/systems/item_ejector.js index 316dc053..925dcc2e 100644 --- a/src/js/game/systems/item_ejector.js +++ b/src/js/game/systems/item_ejector.js @@ -1,392 +1,384 @@ -import { globalConfig } from "../../core/config"; -import { DrawParameters } from "../../core/draw_parameters"; -import { createLogger } from "../../core/logging"; -import { Rectangle } from "../../core/rectangle"; -import { enumDirectionToVector, Vector } from "../../core/vector"; -import { BaseItem, enumItemType, enumItemTypeToLayer } from "../base_item"; -import { ItemEjectorComponent } from "../components/item_ejector"; -import { Entity } from "../entity"; -import { GameSystemWithFilter } from "../game_system_with_filter"; -import { enumLayer } from "../root"; - -const logger = createLogger("systems/ejector"); - -export class ItemEjectorSystem extends GameSystemWithFilter { - constructor(root) { - super(root, [ItemEjectorComponent]); - - this.root.signals.entityAdded.add(this.checkForCacheInvalidation, this); - this.root.signals.entityDestroyed.add(this.checkForCacheInvalidation, this); - this.root.signals.postLoadHook.add(this.recomputeCache, this); - - /** - * @type {Rectangle} - */ - this.areaToRecompute = null; - } - - /** - * - * @param {Entity} entity - */ - checkForCacheInvalidation(entity) { - if (!this.root.gameInitialized) { - return; - } - if (!entity.components.StaticMapEntity) { - return; - } - - // Optimize for the common case: adding or removing one building at a time. Clicking - // and dragging can cause up to 4 add/remove signals. - const staticComp = entity.components.StaticMapEntity; - const bounds = staticComp.getTileSpaceBounds(); - const expandedBounds = bounds.expandedInAllDirections(2); - - if (this.areaToRecompute) { - this.areaToRecompute = this.areaToRecompute.getUnion(expandedBounds); - } else { - this.areaToRecompute = expandedBounds; - } - } - - /** - * Precomputes the cache, which makes up for a huge performance improvement - */ - recomputeCache() { - if (this.areaToRecompute) { - logger.log("Recomputing cache using rectangle"); - if (G_IS_DEV && globalConfig.debug.renderChanges) { - this.root.hud.parts.changesDebugger.renderChange( - "ejector-area", - this.areaToRecompute, - "#fe50a6" - ); - } - this.recomputeAreaCache(); - this.areaToRecompute = null; - } else { - logger.log("Full cache recompute"); - if (G_IS_DEV && globalConfig.debug.renderChanges) { - this.root.hud.parts.changesDebugger.renderChange( - "ejector-full", - new Rectangle(-1000, -1000, 2000, 2000), - "#fe50a6" - ); - } - - // Try to find acceptors for every ejector - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - this.recomputeSingleEntityCache(entity); - } - } - } - - /** - * Recomputes the cache in the given area - */ - recomputeAreaCache() { - const area = this.areaToRecompute; - let entryCount = 0; - - logger.log("Recomputing area:", area.x, area.y, "/", area.w, area.h); - - // Store the entities we already recomputed, so we don't do work twice - const recomputedEntities = new Set(); - - for (let x = area.x; x < area.right(); ++x) { - for (let y = area.y; y < area.bottom(); ++y) { - const entities = this.root.map.getLayersContentsMultipleXY(x, y); - for (let i = 0; i < entities.length; ++i) { - const entity = entities[i]; - - // Recompute the entity in case its relevant for this system and it - // hasn't already been computed - if (!recomputedEntities.has(entity.uid) && entity.components.ItemEjector) { - recomputedEntities.add(entity.uid); - this.recomputeSingleEntityCache(entity); - } - } - } - } - return entryCount; - } - - /** - * @param {Entity} entity - */ - recomputeSingleEntityCache(entity) { - const ejectorComp = entity.components.ItemEjector; - const staticComp = entity.components.StaticMapEntity; - - // Clear the old cache. - ejectorComp.cachedConnectedSlots = null; - - for (let ejectorSlotIndex = 0; ejectorSlotIndex < ejectorComp.slots.length; ++ejectorSlotIndex) { - const ejectorSlot = ejectorComp.slots[ejectorSlotIndex]; - - // Clear the old cache. - ejectorSlot.cachedDestSlot = null; - ejectorSlot.cachedTargetEntity = null; - - // Figure out where and into which direction we eject items - const ejectSlotWsTile = staticComp.localTileToWorld(ejectorSlot.pos); - const ejectSlotWsDirection = staticComp.localDirectionToWorld(ejectorSlot.direction); - const ejectSlotWsDirectionVector = enumDirectionToVector[ejectSlotWsDirection]; - const ejectSlotTargetWsTile = ejectSlotWsTile.add(ejectSlotWsDirectionVector); - - // Try to find the given acceptor component to take the item - // Since there can be cross layer dependencies, check on all layers - const targetEntities = this.root.map.getLayersContentsMultipleXY( - ejectSlotTargetWsTile.x, - ejectSlotTargetWsTile.y - ); - - for (let i = 0; i < targetEntities.length; ++i) { - const targetEntity = targetEntities[i]; - - const targetAcceptorComp = targetEntity.components.ItemAcceptor; - const targetStaticComp = targetEntity.components.StaticMapEntity; - if (!targetAcceptorComp) { - // Entity doesn't accept items - continue; - } - - const matchingSlot = targetAcceptorComp.findMatchingSlot( - targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile), - targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection), - ejectorSlot.layer - ); - - if (!matchingSlot) { - // No matching slot found - continue; - } - - // Ok we found a connection - if (ejectorComp.cachedConnectedSlots) { - ejectorComp.cachedConnectedSlots.push(ejectorSlot); - } else { - ejectorComp.cachedConnectedSlots = [ejectorSlot]; - } - - // A slot can always be connected to one other slot only - ejectorSlot.cachedTargetEntity = targetEntity; - ejectorSlot.cachedDestSlot = matchingSlot; - break; - } - } - } - - update() { - if (this.areaToRecompute) { - this.recomputeCache(); - } - - // Precompute effective belt speed - let progressGrowth = 2 * this.root.dynamicTickrate.deltaSeconds; - - if (G_IS_DEV && globalConfig.debug.instantBelts) { - progressGrowth = 1; - } - - // Go over all cache entries - for (let i = 0; i < this.allEntities.length; ++i) { - const sourceEntity = this.allEntities[i]; - const sourceEjectorComp = sourceEntity.components.ItemEjector; - if (!sourceEjectorComp.enabled) { - continue; - } - - if (!sourceEjectorComp.cachedConnectedSlots) { - continue; - } - - const slots = sourceEjectorComp.cachedConnectedSlots; - for (let j = 0; j < slots.length; ++j) { - const sourceSlot = slots[j]; - const item = sourceSlot.item; - if (!item) { - // No item available to be ejected - continue; - } - - const destSlot = sourceSlot.cachedDestSlot; - const targetEntity = sourceSlot.cachedTargetEntity; - - // Advance items on the slot - sourceSlot.progress = Math.min( - 1, - sourceSlot.progress + - progressGrowth * - this.root.hubGoals.getBeltBaseSpeed(sourceSlot.layer) * - globalConfig.beltItemSpacingByLayer[sourceSlot.layer] - ); - - // Check if we are still in the process of ejecting, can't proceed then - if (sourceSlot.progress < 1.0) { - continue; - } - - // Check if the target acceptor can actually accept this item - const targetAcceptorComp = targetEntity.components.ItemAcceptor; - if (!targetAcceptorComp.canAcceptItem(destSlot.index, item)) { - continue; - } - - // Try to hand over the item - if (this.tryPassOverItem(item, targetEntity, destSlot.index)) { - // Handover successful, clear slot - targetAcceptorComp.onItemAccepted(destSlot.index, destSlot.acceptedDirection, item); - sourceSlot.item = null; - continue; - } - } - } - } - - /** - * - * @param {BaseItem} item - * @param {Entity} receiver - * @param {number} slotIndex - */ - tryPassOverItem(item, receiver, slotIndex) { - // Try figuring out how what to do with the item - // TODO: Kinda hacky. How to solve this properly? Don't want to go through inheritance hell. - // Also its just a few cases (hope it stays like this .. :x). - - const itemLayer = enumItemTypeToLayer[item.getItemType()]; - - const beltComp = receiver.components.Belt; - if (beltComp) { - const path = beltComp.assignedPath; - assert(path, "belt has no path"); - if (path.tryAcceptItem(item)) { - return true; - } - // Belt can have nothing else - return false; - } - - const energyConsumerComp = receiver.components.EnergyConsumer; - if (energyConsumerComp) { - if (energyConsumerComp.tryAcceptItem(item, slotIndex)) { - // All good - return true; - } - - // Energy consumer can have more components - } - - const itemProcessorComp = receiver.components.ItemProcessor; - if (itemProcessorComp) { - // Make sure its the same layer - if (itemLayer === receiver.layer) { - // Its an item processor .. - if (itemProcessorComp.tryTakeItem(item, slotIndex)) { - return true; - } - // Item processor can have nothing else - return false; - } - } - - const undergroundBeltComp = receiver.components.UndergroundBelt; - if (undergroundBeltComp) { - // Its an underground belt. yay. - if ( - undergroundBeltComp.tryAcceptExternalItem( - item, - this.root.hubGoals.getUndergroundBeltBaseSpeed() - ) - ) { - return true; - } - - // Underground belt can have nothing else - return false; - } - - const storageComp = receiver.components.Storage; - if (storageComp) { - // It's a storage - if (storageComp.canAcceptItem(item)) { - storageComp.takeItem(item); - return true; - } - - // Storage can't have anything else - return false; - } - - const energyGeneratorComp = receiver.components.EnergyGenerator; - if (energyGeneratorComp) { - if (energyGeneratorComp.tryTakeItem(item, slotIndex)) { - // Passed it over - return true; - } - - // Energy generator comp can't have anything else - return false; - } - - return false; - } - - /** - * Draws the given layer - * @param {DrawParameters} parameters - * @param {enumLayer} layer - */ - drawLayer(parameters, layer) { - this.forEachMatchingEntityOnScreen(parameters, this.drawSingleEntity.bind(this, layer)); - } - - /** - * @param {enumLayer} layer - * @param {DrawParameters} parameters - * @param {Entity} entity - */ - drawSingleEntity(layer, parameters, entity) { - const ejectorComp = entity.components.ItemEjector; - const staticComp = entity.components.StaticMapEntity; - - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } - - for (let i = 0; i < ejectorComp.slots.length; ++i) { - const slot = ejectorComp.slots[i]; - const ejectedItem = slot.item; - - if (!ejectedItem) { - // No item - continue; - } - - if (slot.layer !== layer) { - // Not our layer - continue; - } - - const realPosition = slot.pos.rotateFastMultipleOf90(staticComp.rotation); - const realDirection = Vector.transformDirectionFromMultipleOf90( - slot.direction, - staticComp.rotation - ); - const realDirectionVector = enumDirectionToVector[realDirection]; - - const tileX = - staticComp.origin.x + realPosition.x + 0.5 + realDirectionVector.x * 0.5 * slot.progress; - const tileY = - staticComp.origin.y + realPosition.y + 0.5 + realDirectionVector.y * 0.5 * slot.progress; - - const worldX = tileX * globalConfig.tileSize; - const worldY = tileY * globalConfig.tileSize; - - ejectedItem.draw(worldX, worldY, parameters); - } - } -} +import { globalConfig } from "../../core/config"; +import { DrawParameters } from "../../core/draw_parameters"; +import { createLogger } from "../../core/logging"; +import { Rectangle } from "../../core/rectangle"; +import { enumDirection, enumDirectionToVector } from "../../core/vector"; +import { BaseItem } from "../base_item"; +import { ItemEjectorComponent } from "../components/item_ejector"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { MapChunkView } from "../map_chunk_view"; + +const logger = createLogger("systems/ejector"); + +export class ItemEjectorSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [ItemEjectorComponent]); + + this.root.signals.entityAdded.add(this.checkForCacheInvalidation, this); + this.root.signals.entityDestroyed.add(this.checkForCacheInvalidation, this); + this.root.signals.postLoadHook.add(this.recomputeCache, this); + + /** + * @type {Rectangle} + */ + this.areaToRecompute = null; + } + + /** + * + * @param {Entity} entity + */ + checkForCacheInvalidation(entity) { + if (!this.root.gameInitialized) { + return; + } + if (!entity.components.StaticMapEntity) { + return; + } + + // Optimize for the common case: adding or removing one building at a time. Clicking + // and dragging can cause up to 4 add/remove signals. + const staticComp = entity.components.StaticMapEntity; + const bounds = staticComp.getTileSpaceBounds(); + const expandedBounds = bounds.expandedInAllDirections(2); + + if (this.areaToRecompute) { + this.areaToRecompute = this.areaToRecompute.getUnion(expandedBounds); + } else { + this.areaToRecompute = expandedBounds; + } + } + + /** + * Precomputes the cache, which makes up for a huge performance improvement + */ + recomputeCache() { + if (this.areaToRecompute) { + logger.log("Recomputing cache using rectangle"); + if (G_IS_DEV && globalConfig.debug.renderChanges) { + this.root.hud.parts.changesDebugger.renderChange( + "ejector-area", + this.areaToRecompute, + "#fe50a6" + ); + } + this.recomputeAreaCache(); + this.areaToRecompute = null; + } else { + logger.log("Full cache recompute"); + if (G_IS_DEV && globalConfig.debug.renderChanges) { + this.root.hud.parts.changesDebugger.renderChange( + "ejector-full", + new Rectangle(-1000, -1000, 2000, 2000), + "#fe50a6" + ); + } + + // Try to find acceptors for every ejector + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + this.recomputeSingleEntityCache(entity); + } + } + } + + /** + * Recomputes the cache in the given area + */ + recomputeAreaCache() { + const area = this.areaToRecompute; + let entryCount = 0; + + logger.log("Recomputing area:", area.x, area.y, "/", area.w, area.h); + + // Store the entities we already recomputed, so we don't do work twice + const recomputedEntities = new Set(); + + for (let x = area.x; x < area.right(); ++x) { + for (let y = area.y; y < area.bottom(); ++y) { + const entities = this.root.map.getLayersContentsMultipleXY(x, y); + for (let i = 0; i < entities.length; ++i) { + const entity = entities[i]; + + // Recompute the entity in case its relevant for this system and it + // hasn't already been computed + if (!recomputedEntities.has(entity.uid) && entity.components.ItemEjector) { + recomputedEntities.add(entity.uid); + this.recomputeSingleEntityCache(entity); + } + } + } + } + return entryCount; + } + + /** + * @param {Entity} entity + */ + recomputeSingleEntityCache(entity) { + const ejectorComp = entity.components.ItemEjector; + const staticComp = entity.components.StaticMapEntity; + + for (let slotIndex = 0; slotIndex < ejectorComp.slots.length; ++slotIndex) { + const ejectorSlot = ejectorComp.slots[slotIndex]; + + // Clear the old cache. + ejectorSlot.cachedDestSlot = null; + ejectorSlot.cachedTargetEntity = null; + ejectorSlot.cachedBeltPath = null; + + // Figure out where and into which direction we eject items + const ejectSlotWsTile = staticComp.localTileToWorld(ejectorSlot.pos); + const ejectSlotWsDirection = staticComp.localDirectionToWorld(ejectorSlot.direction); + const ejectSlotWsDirectionVector = enumDirectionToVector[ejectSlotWsDirection]; + const ejectSlotTargetWsTile = ejectSlotWsTile.add(ejectSlotWsDirectionVector); + + // Try to find the given acceptor component to take the item + // Since there can be cross layer dependencies, check on all layers + const targetEntities = this.root.map.getLayersContentsMultipleXY( + ejectSlotTargetWsTile.x, + ejectSlotTargetWsTile.y + ); + + for (let i = 0; i < targetEntities.length; ++i) { + const targetEntity = targetEntities[i]; + + const targetStaticComp = targetEntity.components.StaticMapEntity; + const targetBeltComp = targetEntity.components.Belt; + + // Check for belts (special case) + if (targetBeltComp) { + const beltAcceptingDirection = targetStaticComp.localDirectionToWorld(enumDirection.top); + if (ejectSlotWsDirection === beltAcceptingDirection) { + ejectorSlot.cachedTargetEntity = targetEntity; + ejectorSlot.cachedBeltPath = targetBeltComp.assignedPath; + break; + } + } + + // Check for item acceptors + const targetAcceptorComp = targetEntity.components.ItemAcceptor; + if (!targetAcceptorComp) { + // Entity doesn't accept items + continue; + } + + const matchingSlot = targetAcceptorComp.findMatchingSlot( + targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile), + targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection) + ); + + if (!matchingSlot) { + // No matching slot found + continue; + } + + // A slot can always be connected to one other slot only + ejectorSlot.cachedTargetEntity = targetEntity; + ejectorSlot.cachedDestSlot = matchingSlot; + break; + } + } + } + + update() { + if (this.areaToRecompute) { + this.recomputeCache(); + } + + // Precompute effective belt speed + let progressGrowth = 2 * this.root.dynamicTickrate.deltaSeconds; + + if (G_IS_DEV && globalConfig.debug.instantBelts) { + progressGrowth = 1; + } + + // Go over all cache entries + for (let i = 0; i < this.allEntities.length; ++i) { + const sourceEntity = this.allEntities[i]; + const sourceEjectorComp = sourceEntity.components.ItemEjector; + if (!sourceEjectorComp.enabled) { + continue; + } + + const slots = sourceEjectorComp.slots; + for (let j = 0; j < slots.length; ++j) { + const sourceSlot = slots[j]; + const item = sourceSlot.item; + if (!item) { + // No item available to be ejected + continue; + } + + const targetEntity = sourceSlot.cachedTargetEntity; + + // Advance items on the slot + sourceSlot.progress = Math.min( + 1, + sourceSlot.progress + + progressGrowth * + this.root.hubGoals.getBeltBaseSpeed() * + globalConfig.itemSpacingOnBelts + ); + + if (G_IS_DEV && globalConfig.debug.disableEjectorProcessing) { + sourceSlot.progress = 1.0; + } + + // Check if we are still in the process of ejecting, can't proceed then + if (sourceSlot.progress < 1.0) { + continue; + } + + // Check if we are ejecting to a belt path + const destPath = sourceSlot.cachedBeltPath; + if (destPath) { + // Try passing the item over + if (destPath.tryAcceptItem(item)) { + sourceSlot.item = null; + } + + // Always stop here, since there can *either* be a belt path *or* + // a slot + continue; + } + + // Check if the target acceptor can actually accept this item + const destSlot = sourceSlot.cachedDestSlot; + if (destSlot) { + const targetAcceptorComp = targetEntity.components.ItemAcceptor; + if (!targetAcceptorComp.canAcceptItem(destSlot.index, item)) { + continue; + } + + // Try to hand over the item + if (this.tryPassOverItem(item, targetEntity, destSlot.index)) { + // Handover successful, clear slot + targetAcceptorComp.onItemAccepted(destSlot.index, destSlot.acceptedDirection, item); + sourceSlot.item = null; + continue; + } + } + } + } + } + + /** + * + * @param {BaseItem} item + * @param {Entity} receiver + * @param {number} slotIndex + */ + tryPassOverItem(item, receiver, slotIndex) { + // Try figuring out how what to do with the item + // TODO: Kinda hacky. How to solve this properly? Don't want to go through inheritance hell. + // Also its just a few cases (hope it stays like this .. :x). + + const beltComp = receiver.components.Belt; + if (beltComp) { + const path = beltComp.assignedPath; + assert(path, "belt has no path"); + if (path.tryAcceptItem(item)) { + return true; + } + // Belt can have nothing else + return false; + } + + const itemProcessorComp = receiver.components.ItemProcessor; + if (itemProcessorComp) { + // Check for potential filters + if (!this.root.systemMgr.systems.itemProcessor.checkRequirements(receiver, item, slotIndex)) { + return false; + } + + // Its an item processor .. + if (itemProcessorComp.tryTakeItem(item, slotIndex)) { + return true; + } + // Item processor can have nothing else + return false; + } + + const undergroundBeltComp = receiver.components.UndergroundBelt; + if (undergroundBeltComp) { + // Its an underground belt. yay. + if ( + undergroundBeltComp.tryAcceptExternalItem( + item, + this.root.hubGoals.getUndergroundBeltBaseSpeed() + ) + ) { + return true; + } + + // Underground belt can have nothing else + return false; + } + + const storageComp = receiver.components.Storage; + if (storageComp) { + // It's a storage + if (storageComp.canAcceptItem(item)) { + storageComp.takeItem(item); + return true; + } + + // Storage can't have anything else + return false; + } + + return false; + } + + /** + * @param {DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + const contents = chunk.containedEntitiesByLayer.regular; + + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const ejectorComp = entity.components.ItemEjector; + if (!ejectorComp) { + continue; + } + + const staticComp = entity.components.StaticMapEntity; + + for (let i = 0; i < ejectorComp.slots.length; ++i) { + const slot = ejectorComp.slots[i]; + const ejectedItem = slot.item; + + if (!ejectedItem) { + // No item + continue; + } + + const realPosition = staticComp.localTileToWorld(slot.pos); + if (!chunk.tileSpaceRectangle.containsPoint(realPosition.x, realPosition.y)) { + // Not within this chunk + continue; + } + + const realDirection = staticComp.localDirectionToWorld(slot.direction); + const realDirectionVector = enumDirectionToVector[realDirection]; + + const tileX = realPosition.x + 0.5 + realDirectionVector.x * 0.5 * slot.progress; + const tileY = realPosition.y + 0.5 + realDirectionVector.y * 0.5 * slot.progress; + + const worldX = tileX * globalConfig.tileSize; + const worldY = tileY * globalConfig.tileSize; + + ejectedItem.drawItemCenteredClipped( + worldX, + worldY, + parameters, + globalConfig.defaultItemDiameter + ); + } + } + } +} diff --git a/src/js/game/systems/item_processor.js b/src/js/game/systems/item_processor.js index 8713f599..d58aa697 100644 --- a/src/js/game/systems/item_processor.js +++ b/src/js/game/systems/item_processor.js @@ -1,12 +1,21 @@ -import { globalConfig } from "../../core/config"; -import { BaseItem, enumItemType } from "../base_item"; -import { enumColorMixingResults, enumInvertedColors } from "../colors"; -import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; +import { BaseItem } from "../base_item"; +import { enumColorMixingResults, enumColors } from "../colors"; +import { + enumItemProcessorRequirements, + enumItemProcessorTypes, + ItemProcessorComponent, +} from "../components/item_processor"; import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; -import { ColorItem } from "../items/color_item"; +import { BOOL_TRUE_SINGLETON, isTruthyItem } from "../items/boolean_item"; +import { ColorItem, COLOR_ITEM_SINGLETONS } from "../items/color_item"; import { ShapeItem } from "../items/shape_item"; +/** + * We need to allow queuing charges, otherwise the throughput will stall + */ +const MAX_QUEUED_CHARGES = 2; + export class ItemProcessorSystem extends GameSystemWithFilter { constructor(root) { super(root, [ItemProcessorComponent]); @@ -19,72 +28,205 @@ export class ItemProcessorSystem extends GameSystemWithFilter { const processorComp = entity.components.ItemProcessor; const ejectorComp = entity.components.ItemEjector; - // First of all, process the current recipe - processorComp.secondsUntilEject = Math.max( - 0, - processorComp.secondsUntilEject - this.root.dynamicTickrate.deltaSeconds - ); + const currentCharge = processorComp.ongoingCharges[0]; - if (G_IS_DEV && globalConfig.debug.instantProcessors) { - processorComp.secondsUntilEject = 0; - } + if (currentCharge) { + // Process next charge + if (currentCharge.remainingTime > 0.0) { + currentCharge.remainingTime -= this.root.dynamicTickrate.deltaSeconds; + if (currentCharge.remainingTime < 0.0) { + // Add bonus time, this is the time we spent too much + processorComp.bonusTime += -currentCharge.remainingTime; + } + } - // Check if we have any finished items we can eject - if ( - processorComp.secondsUntilEject === 0 && // it was processed in time - processorComp.itemsToEject.length > 0 // we have some items left to eject - ) { - for (let itemIndex = 0; itemIndex < processorComp.itemsToEject.length; ++itemIndex) { - const { item, requiredSlot, preferredSlot } = processorComp.itemsToEject[itemIndex]; + // Check if it finished + if (currentCharge.remainingTime <= 0.0) { + const itemsToEject = currentCharge.items; - let slot = null; - if (requiredSlot !== null && requiredSlot !== undefined) { - // We have a slot override, check if that is free - if (ejectorComp.canEjectOnSlot(requiredSlot)) { - slot = requiredSlot; - } - } else if (preferredSlot !== null && preferredSlot !== undefined) { - // We have a slot preference, try using it but otherwise use a free slot - if (ejectorComp.canEjectOnSlot(preferredSlot)) { - slot = preferredSlot; + // Go over all items and try to eject them + for (let j = 0; j < itemsToEject.length; ++j) { + const { item, requiredSlot, preferredSlot } = itemsToEject[j]; + + let slot = null; + if (requiredSlot !== null && requiredSlot !== undefined) { + // We have a slot override, check if that is free + if (ejectorComp.canEjectOnSlot(requiredSlot)) { + slot = requiredSlot; + } + } else if (preferredSlot !== null && preferredSlot !== undefined) { + // We have a slot preference, try using it but otherwise use a free slot + if (ejectorComp.canEjectOnSlot(preferredSlot)) { + slot = preferredSlot; + } else { + slot = ejectorComp.getFirstFreeSlot(); + } } else { - slot = ejectorComp.getFirstFreeSlot(entity.layer); + // We can eject on any slot + slot = ejectorComp.getFirstFreeSlot(); + } + + if (slot !== null) { + // Alright, we can actually eject + if (!ejectorComp.tryEject(slot, item)) { + assert(false, "Failed to eject"); + } else { + itemsToEject.splice(j, 1); + j -= 1; + } } - } else { - // We can eject on any slot - slot = ejectorComp.getFirstFreeSlot(entity.layer); } - if (slot !== null) { - // Alright, we can actually eject - if (!ejectorComp.tryEject(slot, item)) { - assert(false, "Failed to eject"); - } else { - processorComp.itemsToEject.splice(itemIndex, 1); - itemIndex -= 1; - } + // If the charge was entirely emptied to the outputs, start the next charge + if (itemsToEject.length === 0) { + processorComp.ongoingCharges.shift(); } } } // Check if we have an empty queue and can start a new charge - if (processorComp.itemsToEject.length === 0) { - if (processorComp.inputSlots.length >= processorComp.inputsPerCharge) { - const energyConsumerComp = entity.components.EnergyConsumer; - if (energyConsumerComp) { - // Check if we have enough energy - if (energyConsumerComp.tryStartNextCharge()) { - this.startNewCharge(entity); - } - } else { - // No further checks required - this.startNewCharge(entity); - } + if (processorComp.ongoingCharges.length < MAX_QUEUED_CHARGES) { + if (this.canProcess(entity)) { + this.startNewCharge(entity); } } } } + /** + * Returns true if the entity should accept the given item on the given slot. + * This should only be called with matching items! I.e. if a color item is expected + * on the given slot, then only a color item must be passed. + * @param {Entity} entity + * @param {BaseItem} item The item to accept + * @param {number} slotIndex The slot index + * @returns {boolean} + */ + checkRequirements(entity, item, slotIndex) { + const itemProcessorComp = entity.components.ItemProcessor; + const pinsComp = entity.components.WiredPins; + + switch (itemProcessorComp.processingRequirement) { + case enumItemProcessorRequirements.painterQuad: { + if (slotIndex === 0) { + // Always accept the shape + return true; + } + + // Check the network value at the given slot + const network = pinsComp.slots[slotIndex - 1].linkedNetwork; + const slotIsEnabled = network && isTruthyItem(network.currentValue); + if (!slotIsEnabled) { + return false; + } + return true; + } + + case enumItemProcessorRequirements.filter: { + const network = pinsComp.slots[0].linkedNetwork; + if (!network || !network.currentValue) { + // Item filter is not connected + return false; + } + + // Otherwise, all good + return true; + } + + // By default, everything is accepted + default: + return true; + } + } + + /** + * Checks whether it's possible to process something + * @param {Entity} entity + */ + canProcess(entity) { + const processorComp = entity.components.ItemProcessor; + + switch (processorComp.processingRequirement) { + // DEFAULT + // By default, we can start processing once all inputs are there + case null: { + return processorComp.inputSlots.length >= processorComp.inputsPerCharge; + } + + // QUAD PAINTER + // For the quad painter, it might be possible to start processing earlier + case enumItemProcessorRequirements.painterQuad: { + const pinsComp = entity.components.WiredPins; + + /** @type {Object.} */ + const itemsBySlot = {}; + for (let i = 0; i < processorComp.inputSlots.length; ++i) { + itemsBySlot[processorComp.inputSlots[i].sourceSlot] = processorComp.inputSlots[i]; + } + + // First slot is the shape, so if it's not there we can't do anything + if (!itemsBySlot[0]) { + return false; + } + + const shapeItem = /** @type {ShapeItem} */ (itemsBySlot[0].item); + const slotStatus = []; + + // Check which slots are enabled + for (let i = 0; i < 4; ++i) { + // Extract the network value on the Nth pin + const networkValue = pinsComp.slots[i].linkedNetwork + ? pinsComp.slots[i].linkedNetwork.currentValue + : null; + + // If there is no "1" on that slot, don't paint there + if (!isTruthyItem(networkValue)) { + slotStatus.push(false); + continue; + } + + slotStatus.push(true); + } + + // All slots are disabled + if (!slotStatus.includes(true)) { + return false; + } + + // Check if all colors of the enabled slots are there + for (let i = 0; i < slotStatus.length; ++i) { + if (slotStatus[i] && !itemsBySlot[1 + i]) { + // A slot which is enabled wasn't enabled. Make sure if there is anything on the quadrant, + // it is not possible to paint, but if there is nothing we can ignore it + for (let j = 0; j < 4; ++j) { + const layer = shapeItem.definition.layers[j]; + if (layer && layer[i]) { + return false; + } + } + } + } + + return true; + } + + // FILTER + // Double check with linked network + case enumItemProcessorRequirements.filter: { + const network = entity.components.WiredPins.slots[0].linkedNetwork; + if (!network || !network.currentValue) { + // Item filter is not connected + return false; + } + + return processorComp.inputSlots.length >= processorComp.inputsPerCharge; + } + + default: + assertAlways(false, "Unknown requirement for " + processorComp.processingRequirement); + } + } + /** * Starts a new charge for the entity * @param {Entity} entity @@ -102,9 +244,6 @@ export class ItemProcessorSystem extends GameSystemWithFilter { itemsBySlot[items[i].sourceSlot] = items[i]; } - const baseSpeed = this.root.hubGoals.getProcessorBaseSpeed(processorComp.type); - processorComp.secondsUntilEject = 1 / baseSpeed; - /** @type {Array<{item: BaseItem, requiredSlot?: number, preferredSlot?: number}>} */ const outItems = []; @@ -142,7 +281,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { const definition = cutDefinitions[i]; if (!definition.isEntirelyEmpty()) { outItems.push({ - item: new ShapeItem(definition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(definition), requiredSlot: i, }); } @@ -163,7 +302,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { const definition = cutDefinitions[i]; if (!definition.isEntirelyEmpty()) { outItems.push({ - item: new ShapeItem(definition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(definition), requiredSlot: i, }); } @@ -180,12 +319,12 @@ export class ItemProcessorSystem extends GameSystemWithFilter { const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateCW(inputDefinition); outItems.push({ - item: new ShapeItem(rotatedDefinition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinition), }); break; } - // ROTATER ( CCW) + // ROTATER (CCW) case enumItemProcessorTypes.rotaterCCW: { const inputItem = /** @type {ShapeItem} */ (items[0].item); assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape"); @@ -193,7 +332,20 @@ export class ItemProcessorSystem extends GameSystemWithFilter { const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateCCW(inputDefinition); outItems.push({ - item: new ShapeItem(rotatedDefinition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinition), + }); + break; + } + + // ROTATER (FL) + case enumItemProcessorTypes.rotaterFL: { + const inputItem = /** @type {ShapeItem} */ (items[0].item); + assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape"); + const inputDefinition = inputItem.definition; + + const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateFL(inputDefinition); + outItems.push({ + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinition), }); break; } @@ -212,7 +364,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { upperItem.definition ); outItems.push({ - item: new ShapeItem(stackedDefinition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(stackedDefinition), }); break; } @@ -243,7 +395,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { resultColor = mixedColor; } outItems.push({ - item: new ColorItem(resultColor), + item: COLOR_ITEM_SINGLETONS[resultColor], }); break; @@ -261,7 +413,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { ); outItems.push({ - item: new ShapeItem(colorizedDefinition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(colorizedDefinition), }); break; @@ -288,11 +440,11 @@ export class ItemProcessorSystem extends GameSystemWithFilter { colorItem.color ); outItems.push({ - item: new ShapeItem(colorizedDefinition1), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(colorizedDefinition1), }); outItems.push({ - item: new ShapeItem(colorizedDefinition2), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(colorizedDefinition2), }); break; @@ -302,31 +454,73 @@ export class ItemProcessorSystem extends GameSystemWithFilter { case enumItemProcessorTypes.painterQuad: { const shapeItem = /** @type {ShapeItem} */ (itemsBySlot[0].item); - const colorItem1 = /** @type {ColorItem} */ (itemsBySlot[1].item); - const colorItem2 = /** @type {ColorItem} */ (itemsBySlot[2].item); - const colorItem3 = /** @type {ColorItem} */ (itemsBySlot[3].item); - const colorItem4 = /** @type {ColorItem} */ (itemsBySlot[4].item); - assert(shapeItem instanceof ShapeItem, "Input for painter is not a shape"); - assert(colorItem1 instanceof ColorItem, "Input for painter is not a color"); - assert(colorItem2 instanceof ColorItem, "Input for painter is not a color"); - assert(colorItem3 instanceof ColorItem, "Input for painter is not a color"); - assert(colorItem4 instanceof ColorItem, "Input for painter is not a color"); + + /** @type {Array} */ + const colors = [null, null, null, null]; + for (let i = 0; i < 4; ++i) { + if (itemsBySlot[i + 1]) { + colors[i] = /** @type {ColorItem} */ (itemsBySlot[i + 1].item).color; + } + } const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith4Colors( shapeItem.definition, - [colorItem2.color, colorItem3.color, colorItem4.color, colorItem1.color] + /** @type {[string, string, string, string]} */ (colors) ); outItems.push({ - item: new ShapeItem(colorizedDefinition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(colorizedDefinition), }); + break; + } + + // FILTER + case enumItemProcessorTypes.filter: { + // TODO + trackProduction = false; + + const item = itemsBySlot[0].item; + + const network = entity.components.WiredPins.slots[0].linkedNetwork; + if (!network || !network.currentValue) { + outItems.push({ + item, + requiredSlot: 1, + }); + break; + } + + const value = network.currentValue; + if (value.equals(BOOL_TRUE_SINGLETON) || value.equals(item)) { + outItems.push({ + item, + requiredSlot: 0, + }); + } else { + outItems.push({ + item, + requiredSlot: 1, + }); + } break; } - // HUB + // READER + case enumItemProcessorTypes.reader: { + // Pass through the item + const item = itemsBySlot[0].item; + outItems.push({ item }); + // Track the item + const readerComp = entity.components.BeltReader; + readerComp.lastItemTimes.push(this.root.time.now()); + readerComp.lastItem = item; + break; + } + + // HUB case enumItemProcessorTypes.hub: { trackProduction = false; @@ -334,37 +528,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter { assert(hubComponent, "Hub item processor has no hub component"); for (let i = 0; i < items.length; ++i) { - const shapeItem = /** @type {ShapeItem} */ (items[i].item); - hubComponent.queueShapeDefinition(shapeItem.definition); - } - - break; - } - - // ADVANCED PROCESSING - - case enumItemProcessorTypes.advancedProcessor: { - const item = items[0].item; - - if (item.getItemType() === enumItemType.color) { - const colorItem = /** @type {ColorItem} */ (items[0].item); - const newColor = enumInvertedColors[colorItem.color]; - outItems.push({ - item: new ColorItem(newColor), - requiredSlot: 0, - }); - } else if (item.getItemType() === enumItemType.shape) { - const shapeItem = /** @type {ShapeItem} */ (items[0].item); - const newItem = this.root.shapeDefinitionMgr.shapeActionInvertColors( - shapeItem.definition - ); - - outItems.push({ - item: new ShapeItem(newItem), - requiredSlot: 0, - }); - } else { - assertAlways(false, "Bad item type: " + item.getItemType() + " for advanced processor."); + const item = /** @type {ShapeItem} */ (items[i].item); + this.root.hubGoals.handleDefinitionDelivered(item.definition); } break; @@ -381,6 +546,35 @@ export class ItemProcessorSystem extends GameSystemWithFilter { } } - processorComp.itemsToEject = outItems; + // Queue Charge + const baseSpeed = this.root.hubGoals.getProcessorBaseSpeed(processorComp.type); + const originalTime = 1 / baseSpeed; + + const bonusTimeToApply = Math.min(originalTime, processorComp.bonusTime); + const timeToProcess = originalTime - bonusTimeToApply; + + // Substract one tick because we already process it this frame + // if (processorComp.bonusTime > originalTime) { + // if (processorComp.type === enumItemProcessorTypes.reader) { + // console.log( + // "Bonus time", + // round4Digits(processorComp.bonusTime), + // "Original time", + // round4Digits(originalTime), + // "Overcomit by", + // round4Digits(processorComp.bonusTime - originalTime), + // "->", + // round4Digits(timeToProcess), + // "reduced by", + // round4Digits(bonusTimeToApply) + // ); + // } + // } + processorComp.bonusTime -= bonusTimeToApply; + + processorComp.ongoingCharges.push({ + items: outItems, + remainingTime: timeToProcess, + }); } } diff --git a/src/js/game/systems/item_processor_overlays.js b/src/js/game/systems/item_processor_overlays.js new file mode 100644 index 00000000..2ec91b88 --- /dev/null +++ b/src/js/game/systems/item_processor_overlays.js @@ -0,0 +1,138 @@ +import { globalConfig } from "../../core/config"; +import { Loader } from "../../core/loader"; +import { smoothPulse, round4Digits } from "../../core/utils"; +import { enumItemProcessorRequirements, enumItemProcessorTypes } from "../components/item_processor"; +import { Entity } from "../entity"; +import { GameSystem } from "../game_system"; +import { isTruthyItem } from "../items/boolean_item"; +import { MapChunkView } from "../map_chunk_view"; + +export class ItemProcessorOverlaysSystem extends GameSystem { + constructor(root) { + super(root); + + this.spriteDisabled = Loader.getSprite("sprites/misc/processor_disabled.png"); + this.spriteDisconnected = Loader.getSprite("sprites/misc/processor_disconnected.png"); + + this.readerOverlaySprite = Loader.getSprite("sprites/misc/reader_overlay.png"); + + this.drawnUids = new Set(); + + this.root.signals.gameFrameStarted.add(this.clearDrawnUids, this); + } + + clearDrawnUids() { + this.drawnUids.clear(); + } + + /** + * + * @param {import("../../core/draw_utils").DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const processorComp = entity.components.ItemProcessor; + if (!processorComp) { + continue; + } + + const requirement = processorComp.processingRequirement; + + if (!requirement && processorComp.type !== enumItemProcessorTypes.reader) { + continue; + } + + if (this.drawnUids.has(entity.uid)) { + continue; + } + + this.drawnUids.add(entity.uid); + + switch (requirement) { + case enumItemProcessorRequirements.painterQuad: { + this.drawConnectedSlotRequirement(parameters, entity, { drawIfFalse: true }); + break; + } + case enumItemProcessorRequirements.filter: { + this.drawConnectedSlotRequirement(parameters, entity, { drawIfFalse: false }); + break; + } + } + + if (processorComp.type === enumItemProcessorTypes.reader) { + this.drawReaderOverlays(parameters, entity); + } + } + } + + /** + * + * @param {import("../../core/draw_utils").DrawParameters} parameters + * @param {Entity} entity + */ + drawReaderOverlays(parameters, entity) { + const staticComp = entity.components.StaticMapEntity; + const readerComp = entity.components.BeltReader; + + this.readerOverlaySprite.drawCachedCentered( + parameters, + (staticComp.origin.x + 0.5) * globalConfig.tileSize, + (staticComp.origin.y + 0.5) * globalConfig.tileSize, + globalConfig.tileSize + ); + + parameters.context.fillStyle = "#333439"; + parameters.context.textAlign = "center"; + parameters.context.font = "bold 10px GameFont"; + parameters.context.fillText( + "" + Math.round(readerComp.lastThroughput * 10) / 10, + (staticComp.origin.x + 0.5) * globalConfig.tileSize, + (staticComp.origin.y + 0.62) * globalConfig.tileSize + ); + + parameters.context.textAlign = "left"; + } + + /** + * + * @param {import("../../core/draw_utils").DrawParameters} parameters + * @param {Entity} entity + * @param {object} param0 + * @param {boolean=} param0.drawIfFalse + */ + drawConnectedSlotRequirement(parameters, entity, { drawIfFalse = true }) { + const staticComp = entity.components.StaticMapEntity; + const pinsComp = entity.components.WiredPins; + + let anySlotConnected = false; + + // Check if any slot has a value + for (let i = 0; i < pinsComp.slots.length; ++i) { + const slot = pinsComp.slots[i]; + const network = slot.linkedNetwork; + if (network && network.currentValue) { + anySlotConnected = true; + + if (isTruthyItem(network.currentValue) || !drawIfFalse) { + // No need to draw anything + return; + } + } + } + + const pulse = smoothPulse(this.root.time.now()); + parameters.context.globalAlpha = 0.6 + 0.4 * pulse; + const sprite = anySlotConnected ? this.spriteDisabled : this.spriteDisconnected; + sprite.drawCachedCentered( + parameters, + (staticComp.origin.x + 0.5) * globalConfig.tileSize, + (staticComp.origin.y + 0.5) * globalConfig.tileSize, + globalConfig.tileSize * (0.7 + 0.2 * pulse) + ); + + parameters.context.globalAlpha = 1; + } +} diff --git a/src/js/game/systems/lever.js b/src/js/game/systems/lever.js new file mode 100644 index 00000000..75b6cf28 --- /dev/null +++ b/src/js/game/systems/lever.js @@ -0,0 +1,44 @@ +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { LeverComponent } from "../components/lever"; +import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON } from "../items/boolean_item"; +import { MapChunkView } from "../map_chunk_view"; +import { globalConfig } from "../../core/config"; +import { Loader } from "../../core/loader"; + +export class LeverSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [LeverComponent]); + + this.spriteOn = Loader.getSprite("sprites/wires/lever_on.png"); + this.spriteOff = Loader.getSprite("sprites/buildings/lever.png"); + } + + update() { + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + + const leverComp = entity.components.Lever; + const pinsComp = entity.components.WiredPins; + + // Simply sync the status to the first slot + pinsComp.slots[0].value = leverComp.toggled ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON; + } + } + + /** + * Draws a given chunk + * @param {import("../../core/draw_utils").DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const leverComp = entity.components.Lever; + if (leverComp) { + const sprite = leverComp.toggled ? this.spriteOn : this.spriteOff; + entity.components.StaticMapEntity.drawSpriteOnBoundsClipped(parameters, sprite); + } + } + } +} diff --git a/src/js/game/systems/logic_gate.js b/src/js/game/systems/logic_gate.js new file mode 100644 index 00000000..3bfc20cd --- /dev/null +++ b/src/js/game/systems/logic_gate.js @@ -0,0 +1,304 @@ +import { BaseItem } from "../base_item"; +import { enumColors } from "../colors"; +import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate"; +import { enumPinSlotType } from "../components/wired_pins"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { BOOL_FALSE_SINGLETON, BOOL_TRUE_SINGLETON, isTruthyItem, BooleanItem } from "../items/boolean_item"; +import { COLOR_ITEM_SINGLETONS, ColorItem } from "../items/color_item"; +import { ShapeDefinition } from "../shape_definition"; +import { ShapeItem } from "../items/shape_item"; + +export class LogicGateSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [LogicGateComponent]); + + this.boundOperations = { + [enumLogicGateType.and]: this.compute_AND.bind(this), + [enumLogicGateType.not]: this.compute_NOT.bind(this), + [enumLogicGateType.xor]: this.compute_XOR.bind(this), + [enumLogicGateType.or]: this.compute_OR.bind(this), + [enumLogicGateType.transistor]: this.compute_IF.bind(this), + + [enumLogicGateType.rotater]: this.compute_ROTATE.bind(this), + [enumLogicGateType.analyzer]: this.compute_ANALYZE.bind(this), + [enumLogicGateType.cutter]: this.compute_CUT.bind(this), + [enumLogicGateType.unstacker]: this.compute_UNSTACK.bind(this), + [enumLogicGateType.shapecompare]: this.compute_SHAPECOMPARE.bind(this), + }; + } + + update() { + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + const logicComp = entity.components.LogicGate; + const slotComp = entity.components.WiredPins; + + const slotValues = []; + + // Store if any conflict was found + let anyConflict = false; + + // Gather inputs from all connected networks + for (let i = 0; i < slotComp.slots.length; ++i) { + const slot = slotComp.slots[i]; + if (slot.type !== enumPinSlotType.logicalAcceptor) { + continue; + } + if (slot.linkedNetwork) { + if (slot.linkedNetwork.valueConflict) { + anyConflict = true; + break; + } + + slotValues.push(slot.linkedNetwork.currentValue); + } else { + slotValues.push(null); + } + } + + // Handle conflicts + if (anyConflict) { + for (let i = 0; i < slotComp.slots.length; ++i) { + const slot = slotComp.slots[i]; + if (slot.type !== enumPinSlotType.logicalEjector) { + continue; + } + slot.value = null; + } + continue; + } + + // Compute actual result + const result = this.boundOperations[logicComp.type](slotValues); + + if (Array.isArray(result)) { + let resultIndex = 0; + for (let i = 0; i < slotComp.slots.length; ++i) { + const slot = slotComp.slots[i]; + if (slot.type !== enumPinSlotType.logicalEjector) { + continue; + } + slot.value = result[resultIndex++]; + } + } else { + // @TODO: For now we hardcode the value to always be slot 0 + assert( + slotValues.length === slotComp.slots.length - 1, + "Bad slot config, should have N acceptor slots and 1 ejector" + ); + assert(slotComp.slots[0].type === enumPinSlotType.logicalEjector, "Slot 0 should be ejector"); + slotComp.slots[0].value = result; + } + } + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_AND(parameters) { + assert(parameters.length === 2, "bad parameter count for AND"); + return isTruthyItem(parameters[0]) && isTruthyItem(parameters[1]) + ? BOOL_TRUE_SINGLETON + : BOOL_FALSE_SINGLETON; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_NOT(parameters) { + return isTruthyItem(parameters[0]) ? BOOL_FALSE_SINGLETON : BOOL_TRUE_SINGLETON; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_XOR(parameters) { + assert(parameters.length === 2, "bad parameter count for XOR"); + return isTruthyItem(parameters[0]) !== isTruthyItem(parameters[1]) + ? BOOL_TRUE_SINGLETON + : BOOL_FALSE_SINGLETON; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_OR(parameters) { + assert(parameters.length === 2, "bad parameter count for OR"); + return isTruthyItem(parameters[0]) || isTruthyItem(parameters[1]) + ? BOOL_TRUE_SINGLETON + : BOOL_FALSE_SINGLETON; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_IF(parameters) { + assert(parameters.length === 2, "bad parameter count for IF"); + const flag = parameters[0]; + const value = parameters[1]; + + // pass through item + if (isTruthyItem(flag)) { + return value; + } + + return null; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_ROTATE(parameters) { + const item = parameters[0]; + if (!item || item.getItemType() !== "shape") { + // Not a shape + return null; + } + + const definition = /** @type {ShapeItem} */ (item).definition; + const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateCW(definition); + return this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinition); + } + + /** + * @param {Array} parameters + * @returns {[BaseItem, BaseItem]} + */ + compute_ANALYZE(parameters) { + const item = parameters[0]; + if (!item || item.getItemType() !== "shape") { + // Not a shape + return [null, null]; + } + + const definition = /** @type {ShapeItem} */ (item).definition; + const lowerLayer = /** @type {import("../shape_definition").ShapeLayer} */ (definition.layers[0]); + if (!lowerLayer) { + return [null, null]; + } + + const topRightContent = lowerLayer[0]; + + if (!topRightContent || topRightContent.subShape === null) { + return [null, null]; + } + + const newDefinition = new ShapeDefinition({ + layers: [ + [ + { subShape: topRightContent.subShape, color: enumColors.uncolored }, + { subShape: topRightContent.subShape, color: enumColors.uncolored }, + { subShape: topRightContent.subShape, color: enumColors.uncolored }, + { subShape: topRightContent.subShape, color: enumColors.uncolored }, + ], + ], + }); + + return [ + COLOR_ITEM_SINGLETONS[topRightContent.color], + this.root.shapeDefinitionMgr.getShapeItemFromDefinition(newDefinition), + ]; + } + + /** + * @param {Array} parameters + * @returns {[BaseItem, BaseItem]} + */ + compute_CUT(parameters) { + const item = parameters[0]; + if (!item || item.getItemType() !== "shape") { + // Not a shape + return [null, null]; + } + + const definition = /** @type {ShapeItem} */ (item).definition; + const result = this.root.shapeDefinitionMgr.shapeActionCutHalf(definition); + return [ + result[0].isEntirelyEmpty() + ? null + : this.root.shapeDefinitionMgr.getShapeItemFromDefinition(result[0]), + result[1].isEntirelyEmpty() + ? null + : this.root.shapeDefinitionMgr.getShapeItemFromDefinition(result[1]), + ]; + } + + /** + * @param {Array} parameters + * @returns {[BaseItem, BaseItem]} + */ + compute_UNSTACK(parameters) { + const item = parameters[0]; + if (!item || item.getItemType() !== "shape") { + // Not a shape + return [null, null]; + } + + const definition = /** @type {ShapeItem} */ (item).definition; + const layers = /** @type {Array} */ (definition.layers); + + const upperLayerDefinition = new ShapeDefinition({ + layers: [layers[layers.length - 1]], + }); + + const lowerLayers = layers.slice(0, layers.length - 1); + const lowerLayerDefinition = + lowerLayers.length > 0 ? new ShapeDefinition({ layers: lowerLayers }) : null; + + return [ + lowerLayerDefinition + ? this.root.shapeDefinitionMgr.getShapeItemFromDefinition(lowerLayerDefinition) + : null, + this.root.shapeDefinitionMgr.getShapeItemFromDefinition(upperLayerDefinition), + ]; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_SHAPECOMPARE(parameters) { + const itemA = parameters[0]; + const itemB = parameters[1]; + + if (!itemA || !itemB) { + // Empty + return BOOL_FALSE_SINGLETON; + } + + if (itemA.getItemType() !== itemB.getItemType()) { + // Not the same type + return BOOL_FALSE_SINGLETON; + } + + switch (itemA.getItemType()) { + case "shape": { + return /** @type {ShapeItem} */ (itemA).definition.getHash() === + /** @type {ShapeItem} */ (itemB).definition.getHash() + ? BOOL_TRUE_SINGLETON + : BOOL_FALSE_SINGLETON; + } + case "color": { + return /** @type {ColorItem} */ (itemA).color === /** @type {ColorItem} */ (itemB).color + ? BOOL_TRUE_SINGLETON + : BOOL_FALSE_SINGLETON; + } + + case "boolean": { + return /** @type {BooleanItem} */ (itemA).value === /** @type {BooleanItem} */ (itemB).value + ? BOOL_TRUE_SINGLETON + : BOOL_FALSE_SINGLETON; + } + + default: { + assertAlways(false, "Bad item type: " + itemA.getItemType()); + } + } + } +} diff --git a/src/js/game/systems/map_resources.js b/src/js/game/systems/map_resources.js index 6504d457..c368e684 100644 --- a/src/js/game/systems/map_resources.js +++ b/src/js/game/systems/map_resources.js @@ -1,67 +1,113 @@ -import { GameSystem } from "../game_system"; -import { DrawParameters } from "../../core/draw_parameters"; -import { globalConfig } from "../../core/config"; -import { MapChunkView } from "../map_chunk_view"; - -export class MapResourcesSystem extends GameSystem { - /** - * Draws the map resources - * @param {DrawParameters} parameters - * @param {MapChunkView} chunk - */ - drawChunk(parameters, chunk) { - const renderItems = parameters.zoomLevel >= globalConfig.mapChunkOverviewMinZoom; - - parameters.context.globalAlpha = 0.5; - - const layer = chunk.lowerLayer; - for (let x = 0; x < globalConfig.mapChunkSize; ++x) { - const row = layer[x]; - const worldX = (chunk.tileX + x) * globalConfig.tileSize; - for (let y = 0; y < globalConfig.mapChunkSize; ++y) { - const lowerItem = row[y]; - if (lowerItem) { - const worldY = (chunk.tileY + y) * globalConfig.tileSize; - - if ( - !parameters.visibleRect.containsRect4Params( - worldX, - worldY, - globalConfig.tileSize, - globalConfig.tileSize - ) - ) { - // Clipped - continue; - } - - parameters.context.fillStyle = lowerItem.getBackgroundColorAsResource(); - parameters.context.fillRect(worldX, worldY, globalConfig.tileSize, globalConfig.tileSize); - if (renderItems) { - lowerItem.draw( - worldX + globalConfig.halfTileSize, - worldY + globalConfig.halfTileSize, - parameters - ); - } - } - } - } - parameters.context.globalAlpha = 1; - - if (!renderItems) { - // Render patches instead - const patches = chunk.patches; - for (let i = 0; i < patches.length; ++i) { - const { pos, item, size } = patches[i]; - - item.draw( - (chunk.tileX + pos.x + 0.5) * globalConfig.tileSize, - (chunk.tileY + pos.y + 0.5) * globalConfig.tileSize, - parameters, - 80 - ); - } - } - } -} +import { globalConfig } from "../../core/config"; +import { DrawParameters } from "../../core/draw_parameters"; +import { GameSystem } from "../game_system"; +import { MapChunkView } from "../map_chunk_view"; +import { THEME } from "../theme"; +import { drawSpriteClipped } from "../../core/draw_utils"; + +export class MapResourcesSystem extends GameSystem { + /** + * Draws the map resources + * @param {DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + const basicChunkBackground = this.root.buffers.getForKey({ + key: "mapresourcebg", + subKey: chunk.renderKey, + w: globalConfig.mapChunkSize, + h: globalConfig.mapChunkSize, + dpi: 1, + redrawMethod: this.generateChunkBackground.bind(this, chunk), + }); + + parameters.context.imageSmoothingEnabled = false; + drawSpriteClipped({ + parameters, + sprite: basicChunkBackground, + x: chunk.tileX * globalConfig.tileSize, + y: chunk.tileY * globalConfig.tileSize, + w: globalConfig.mapChunkWorldSize, + h: globalConfig.mapChunkWorldSize, + originalW: globalConfig.mapChunkSize, + originalH: globalConfig.mapChunkSize, + }); + parameters.context.imageSmoothingEnabled = true; + + parameters.context.globalAlpha = 0.5; + + if (this.root.app.settings.getAllSettings().lowQualityMapResources) { + // LOW QUALITY: Draw patch items only + for (let i = 0; i < chunk.patches.length; ++i) { + const patch = chunk.patches[i]; + const destX = chunk.x * globalConfig.mapChunkWorldSize + patch.pos.x * globalConfig.tileSize; + const destY = chunk.y * globalConfig.mapChunkWorldSize + patch.pos.y * globalConfig.tileSize; + const diameter = Math.min(80, 40 / parameters.zoomLevel); + + patch.item.drawItemCenteredClipped(destX, destY, parameters, diameter); + } + } else { + // HIGH QUALITY: Draw all items + const layer = chunk.lowerLayer; + for (let x = 0; x < globalConfig.mapChunkSize; ++x) { + const row = layer[x]; + const worldX = (chunk.tileX + x) * globalConfig.tileSize; + for (let y = 0; y < globalConfig.mapChunkSize; ++y) { + const lowerItem = row[y]; + if (lowerItem) { + const worldY = (chunk.tileY + y) * globalConfig.tileSize; + + const destX = worldX + globalConfig.halfTileSize; + const destY = worldY + globalConfig.halfTileSize; + + lowerItem.drawItemCenteredClipped( + destX, + destY, + parameters, + globalConfig.defaultItemDiameter + ); + } + } + } + } + parameters.context.globalAlpha = 1; + } + + /** + * + * @param {MapChunkView} chunk + * @param {HTMLCanvasElement} canvas + * @param {CanvasRenderingContext2D} context + * @param {number} w + * @param {number} h + * @param {number} dpi + */ + generateChunkBackground(chunk, canvas, context, w, h, dpi) { + if (this.root.app.settings.getAllSettings().disableTileGrid) { + // The map doesn't draw a background, so we have to + context.fillStyle = THEME.map.background; + context.fillRect(0, 0, w, h); + } else { + context.clearRect(0, 0, w, h); + } + + context.globalAlpha = 0.5; + const layer = chunk.lowerLayer; + for (let x = 0; x < globalConfig.mapChunkSize; ++x) { + const row = layer[x]; + for (let y = 0; y < globalConfig.mapChunkSize; ++y) { + const item = row[y]; + if (item) { + context.fillStyle = item.getBackgroundColorAsResource(); + context.fillRect(x, y, 1, 1); + } + } + } + + if (this.root.app.settings.getAllSettings().displayChunkBorders) { + context.fillStyle = THEME.map.chunkBorders; + context.fillRect(0, 0, w, 1); + context.fillRect(0, 1, 1, h); + } + } +} diff --git a/src/js/game/systems/miner.js b/src/js/game/systems/miner.js index f317d0d1..94f2791e 100644 --- a/src/js/game/systems/miner.js +++ b/src/js/game/systems/miner.js @@ -1,143 +1,194 @@ -import { globalConfig } from "../../core/config"; -import { DrawParameters } from "../../core/draw_parameters"; -import { enumDirectionToVector } from "../../core/vector"; -import { BaseItem } from "../base_item"; -import { MinerComponent } from "../components/miner"; -import { Entity } from "../entity"; -import { GameSystemWithFilter } from "../game_system_with_filter"; -import { MapChunkView } from "../map_chunk_view"; -import { enumLayer } from "../root"; - -export class MinerSystem extends GameSystemWithFilter { - constructor(root) { - super(root, [MinerComponent]); - } - - update() { - let miningSpeed = this.root.hubGoals.getMinerBaseSpeed(); - if (G_IS_DEV && globalConfig.debug.instantMiners) { - miningSpeed *= 100; - } - - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - - // Check if miner is above an actual tile - - const minerComp = entity.components.Miner; - - if (!minerComp.cachedMinedItem) { - const staticComp = entity.components.StaticMapEntity; - const tileBelow = this.root.map.getLowerLayerContentXY( - staticComp.origin.x, - staticComp.origin.y - ); - if (!tileBelow) { - continue; - } - minerComp.cachedMinedItem = tileBelow; - } - - // First, try to get rid of chained items - if (minerComp.itemChainBuffer.length > 0) { - if (this.tryPerformMinerEject(entity, minerComp.itemChainBuffer[0])) { - minerComp.itemChainBuffer.shift(); - continue; - } - } - - if (this.root.time.isIngameTimerExpired(minerComp.lastMiningTime, 1 / miningSpeed)) { - if (this.tryPerformMinerEject(entity, minerComp.cachedMinedItem)) { - // Analytics hook - this.root.signals.itemProduced.dispatch(minerComp.cachedMinedItem); - - // Actually mine - minerComp.lastMiningTime = this.root.time.now(); - } - } - } - } - - /** - * - * @param {Entity} entity - * @param {BaseItem} item - */ - tryPerformMinerEject(entity, item) { - const minerComp = entity.components.Miner; - const ejectComp = entity.components.ItemEjector; - const staticComp = entity.components.StaticMapEntity; - - // Check if we are a chained miner - if (minerComp.chainable) { - const ejectingSlot = ejectComp.slots[0]; - const ejectingPos = staticComp.localTileToWorld(ejectingSlot.pos); - const ejectingDirection = staticComp.localDirectionToWorld(ejectingSlot.direction); - - const targetTile = ejectingPos.add(enumDirectionToVector[ejectingDirection]); - const targetContents = this.root.map.getTileContent(targetTile, enumLayer.regular); - - // Check if we are connected to another miner and thus do not eject directly - if (targetContents) { - const targetMinerComp = targetContents.components.Miner; - if (targetMinerComp) { - if (targetMinerComp.tryAcceptChainedItem(item)) { - return true; - } else { - return false; - } - } - } - } - - // Seems we are a regular miner or at the end of a row, try actually ejecting - if (ejectComp.tryEject(0, item)) { - return true; - } - return false; - } - - /** - * - * @param {DrawParameters} parameters - * @param {MapChunkView} chunk - */ - drawChunk(parameters, chunk) { - const contents = chunk.contents; - for (let y = 0; y < globalConfig.mapChunkSize; ++y) { - for (let x = 0; x < globalConfig.mapChunkSize; ++x) { - const entity = contents[x][y]; - - if (entity && entity.components.Miner) { - const staticComp = entity.components.StaticMapEntity; - const minerComp = entity.components.Miner; - if (!staticComp.shouldBeDrawn(parameters)) { - continue; - } - if (!minerComp.cachedMinedItem) { - continue; - } - - if (minerComp.cachedMinedItem) { - const padding = 3; - parameters.context.fillStyle = minerComp.cachedMinedItem.getBackgroundColorAsResource(); - parameters.context.fillRect( - staticComp.origin.x * globalConfig.tileSize + padding, - staticComp.origin.y * globalConfig.tileSize + padding, - globalConfig.tileSize - 2 * padding, - globalConfig.tileSize - 2 * padding - ); - } - - if (minerComp.cachedMinedItem) { - minerComp.cachedMinedItem.draw( - (0.5 + staticComp.origin.x) * globalConfig.tileSize, - (0.5 + staticComp.origin.y) * globalConfig.tileSize, - parameters - ); - } - } - } - } - } -} +import { globalConfig } from "../../core/config"; +import { DrawParameters } from "../../core/draw_parameters"; +import { enumDirectionToVector } from "../../core/vector"; +import { BaseItem } from "../base_item"; +import { MinerComponent } from "../components/miner"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { MapChunkView } from "../map_chunk_view"; + +export class MinerSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [MinerComponent]); + + this.needsRecompute = true; + + this.root.signals.entityAdded.add(this.onEntityChanged, this); + this.root.signals.entityChanged.add(this.onEntityChanged, this); + this.root.signals.entityDestroyed.add(this.onEntityChanged, this); + } + + /** + * Called whenever an entity got changed + * @param {Entity} entity + */ + onEntityChanged(entity) { + const minerComp = entity.components.Miner; + if (minerComp && minerComp.chainable) { + // Miner component, need to recompute + this.needsRecompute = true; + } + } + + update() { + let miningSpeed = this.root.hubGoals.getMinerBaseSpeed(); + if (G_IS_DEV && globalConfig.debug.instantMiners) { + miningSpeed *= 100; + } + + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + const minerComp = entity.components.Miner; + + // Reset everything on recompute + if (this.needsRecompute) { + minerComp.cachedChainedMiner = null; + } + + // Check if miner is above an actual tile + + if (!minerComp.cachedMinedItem) { + const staticComp = entity.components.StaticMapEntity; + const tileBelow = this.root.map.getLowerLayerContentXY( + staticComp.origin.x, + staticComp.origin.y + ); + if (!tileBelow) { + continue; + } + minerComp.cachedMinedItem = tileBelow; + } + + // First, try to get rid of chained items + if (minerComp.itemChainBuffer.length > 0) { + if (this.tryPerformMinerEject(entity, minerComp.itemChainBuffer[0])) { + minerComp.itemChainBuffer.shift(); + continue; + } + } + + const mineDuration = 1 / miningSpeed; + const timeSinceMine = this.root.time.now() - minerComp.lastMiningTime; + if (timeSinceMine > mineDuration) { + // Store how much we overflowed + const buffer = Math.min(timeSinceMine - mineDuration, this.root.dynamicTickrate.deltaSeconds); + + if (this.tryPerformMinerEject(entity, minerComp.cachedMinedItem)) { + // Analytics hook + this.root.signals.itemProduced.dispatch(minerComp.cachedMinedItem); + // Store mining time + minerComp.lastMiningTime = this.root.time.now() - buffer; + } + } + } + + // After this frame we are done + this.needsRecompute = false; + } + + /** + * Finds the target chained miner for a given entity + * @param {Entity} entity + * @returns {Entity|false} The chained entity or null if not found + */ + findChainedMiner(entity) { + const ejectComp = entity.components.ItemEjector; + const staticComp = entity.components.StaticMapEntity; + + const ejectingSlot = ejectComp.slots[0]; + const ejectingPos = staticComp.localTileToWorld(ejectingSlot.pos); + const ejectingDirection = staticComp.localDirectionToWorld(ejectingSlot.direction); + + const targetTile = ejectingPos.add(enumDirectionToVector[ejectingDirection]); + const targetContents = this.root.map.getTileContent(targetTile, "regular"); + + // Check if we are connected to another miner and thus do not eject directly + if (targetContents) { + const targetMinerComp = targetContents.components.Miner; + if (targetMinerComp && targetMinerComp.chainable) { + return targetContents; + } + } + + return false; + } + + /** + * + * @param {Entity} entity + * @param {BaseItem} item + */ + tryPerformMinerEject(entity, item) { + const minerComp = entity.components.Miner; + const ejectComp = entity.components.ItemEjector; + + // Check if we are a chained miner + if (minerComp.chainable) { + const targetEntity = minerComp.cachedChainedMiner; + + // Check if the cache has to get recomputed + if (targetEntity === null) { + minerComp.cachedChainedMiner = this.findChainedMiner(entity); + } + + // Check if we now have a target + if (targetEntity) { + const targetMinerComp = targetEntity.components.Miner; + if (targetMinerComp.tryAcceptChainedItem(item)) { + return true; + } else { + return false; + } + } + } + + // Seems we are a regular miner or at the end of a row, try actually ejecting + if (ejectComp.tryEject(0, item)) { + return true; + } + + return false; + } + + /** + * + * @param {DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + const contents = chunk.containedEntitiesByLayer.regular; + + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const minerComp = entity.components.Miner; + if (!minerComp) { + continue; + } + + const staticComp = entity.components.StaticMapEntity; + if (!minerComp.cachedMinedItem) { + continue; + } + + // Draw the item background - this is to hide the ejected item animation from + // the item ejecto + + const padding = 3; + const destX = staticComp.origin.x * globalConfig.tileSize + padding; + const destY = staticComp.origin.y * globalConfig.tileSize + padding; + const dimensions = globalConfig.tileSize - 2 * padding; + + if (parameters.visibleRect.containsRect4Params(destX, destY, dimensions, dimensions)) { + parameters.context.fillStyle = minerComp.cachedMinedItem.getBackgroundColorAsResource(); + parameters.context.fillRect(destX, destY, dimensions, dimensions); + } + + minerComp.cachedMinedItem.drawItemCenteredClipped( + (0.5 + staticComp.origin.x) * globalConfig.tileSize, + (0.5 + staticComp.origin.y) * globalConfig.tileSize, + parameters, + globalConfig.defaultItemDiameter + ); + } + } +} diff --git a/src/js/game/systems/static_map_entity.js b/src/js/game/systems/static_map_entity.js index a212dcf6..3e891f7b 100644 --- a/src/js/game/systems/static_map_entity.js +++ b/src/js/game/systems/static_map_entity.js @@ -1,103 +1,82 @@ -import { GameSystem } from "../game_system"; -import { DrawParameters } from "../../core/draw_parameters"; -import { globalConfig } from "../../core/config"; -import { MapChunkView } from "../map_chunk_view"; -import { Loader } from "../../core/loader"; -import { enumDirection } from "../../core/vector"; -import { enumLayer } from "../root"; - -export class StaticMapEntitySystem extends GameSystem { - constructor(root) { - super(root); - - this.beltOverviewSprites = { - [enumDirection.top]: Loader.getSprite("sprites/map_overview/belt_forward.png"), - [enumDirection.right]: Loader.getSprite("sprites/map_overview/belt_right.png"), - [enumDirection.left]: Loader.getSprite("sprites/map_overview/belt_left.png"), - }; - } - - /** - * Draws the static entities - * @param {DrawParameters} parameters - * @param {MapChunkView} chunk - */ - drawChunk(parameters, chunk) { - if (G_IS_DEV && globalConfig.debug.doNotRenderStatics) { - return; - } - - const drawOutlinesOnly = parameters.zoomLevel < globalConfig.mapChunkOverviewMinZoom; - - const drawnUids = new Set(); - - const contents = chunk.contents; - for (let y = 0; y < globalConfig.mapChunkSize; ++y) { - for (let x = 0; x < globalConfig.mapChunkSize; ++x) { - const entity = contents[x][y]; - - if (entity) { - if (drawnUids.has(entity.uid)) { - continue; - } - drawnUids.add(entity.uid); - const staticComp = entity.components.StaticMapEntity; - if (drawOutlinesOnly) { - const rect = staticComp.getTileSpaceBounds(); - parameters.context.fillStyle = staticComp.silhouetteColor || "#aaa"; - const beltComp = entity.components.Belt; - if (beltComp) { - const sprite = this.beltOverviewSprites[beltComp.direction]; - staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 0, false); - } else { - parameters.context.fillRect( - rect.x * globalConfig.tileSize, - rect.y * globalConfig.tileSize, - rect.w * globalConfig.tileSize, - rect.h * globalConfig.tileSize - ); - } - } else { - const spriteKey = staticComp.spriteKey; - if (spriteKey) { - const sprite = Loader.getSprite(spriteKey); - staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 2, false); - } - } - } - } - } - } - - /** - * Draws the static wire entities - * @param {DrawParameters} parameters - * @param {MapChunkView} chunk - */ - drawWiresChunk(parameters, chunk) { - if (G_IS_DEV && globalConfig.debug.doNotRenderStatics) { - return; - } - - const drawnUids = new Set(); - const contents = chunk.wireContents; - for (let y = 0; y < globalConfig.mapChunkSize; ++y) { - for (let x = 0; x < globalConfig.mapChunkSize; ++x) { - const entity = contents[x][y]; - if (entity) { - if (drawnUids.has(entity.uid)) { - continue; - } - drawnUids.add(entity.uid); - const staticComp = entity.components.StaticMapEntity; - - const spriteKey = staticComp.spriteKey; - if (spriteKey) { - const sprite = Loader.getSprite(spriteKey); - staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 2, false); - } - } - } - } - } -} +import { globalConfig } from "../../core/config"; +import { DrawParameters } from "../../core/draw_parameters"; +import { GameSystem } from "../game_system"; +import { MapChunkView } from "../map_chunk_view"; + +export class StaticMapEntitySystem extends GameSystem { + constructor(root) { + super(root); + + /** @type {Set} */ + this.drawnUids = new Set(); + + this.root.signals.gameFrameStarted.add(this.clearUidList, this); + } + + /** + * Clears the uid list when a new frame started + */ + clearUidList() { + this.drawnUids.clear(); + } + + /** + * Draws the static entities + * @param {DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + if (G_IS_DEV && globalConfig.debug.doNotRenderStatics) { + return; + } + + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + + const staticComp = entity.components.StaticMapEntity; + const sprite = staticComp.getSprite(); + if (sprite) { + // Avoid drawing an entity twice which has been drawn for + // another chunk already + if (this.drawnUids.has(entity.uid)) { + continue; + } + + this.drawnUids.add(entity.uid); + staticComp.drawSpriteOnBoundsClipped(parameters, sprite, 2); + } + } + } + + /** + * Draws the static wire entities + * @param {DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawWiresChunk(parameters, chunk) { + if (G_IS_DEV && globalConfig.debug.doNotRenderStatics) { + return; + } + + const drawnUids = new Set(); + const contents = chunk.wireContents; + for (let y = 0; y < globalConfig.mapChunkSize; ++y) { + for (let x = 0; x < globalConfig.mapChunkSize; ++x) { + const entity = contents[x][y]; + if (entity) { + if (drawnUids.has(entity.uid)) { + continue; + } + drawnUids.add(entity.uid); + const staticComp = entity.components.StaticMapEntity; + + const sprite = staticComp.getSprite(); + if (sprite) { + staticComp.drawSpriteOnBoundsClipped(parameters, sprite, 2); + } + } + } + } + } +} diff --git a/src/js/game/systems/storage.js b/src/js/game/systems/storage.js index 7f946e5b..5a2b57bb 100644 --- a/src/js/game/systems/storage.js +++ b/src/js/game/systems/storage.js @@ -1,29 +1,41 @@ import { GameSystemWithFilter } from "../game_system_with_filter"; import { StorageComponent } from "../components/storage"; -import { Entity } from "../entity"; import { DrawParameters } from "../../core/draw_parameters"; import { formatBigNumber, lerp } from "../../core/utils"; import { Loader } from "../../core/loader"; -import { enumLayer } from "../root"; +import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON } from "../items/boolean_item"; +import { MapChunkView } from "../map_chunk_view"; export class StorageSystem extends GameSystemWithFilter { constructor(root) { super(root, [StorageComponent]); this.storageOverlaySprite = Loader.getSprite("sprites/misc/storage_overlay.png"); + + /** + * Stores which uids were already drawn to avoid drawing entities twice + * @type {Set} + */ + this.drawnUids = new Set(); + + this.root.signals.gameFrameStarted.add(this.clearDrawnUids, this); + } + + clearDrawnUids() { + this.drawnUids.clear(); } update() { for (let i = 0; i < this.allEntities.length; ++i) { const entity = this.allEntities[i]; const storageComp = entity.components.Storage; + const pinsComp = entity.components.WiredPins; // Eject from storage if (storageComp.storedItem && storageComp.storedCount > 0) { const ejectorComp = entity.components.ItemEjector; - /* FIXME: WIRES */ - const nextSlot = ejectorComp.getFirstFreeSlot(enumLayer.regular); + const nextSlot = ejectorComp.getFirstFreeSlot(); if (nextSlot !== null) { if (ejectorComp.tryEject(nextSlot, storageComp.storedItem)) { storageComp.storedCount--; @@ -37,41 +49,52 @@ export class StorageSystem extends GameSystemWithFilter { let targetAlpha = storageComp.storedCount > 0 ? 1 : 0; storageComp.overlayOpacity = lerp(storageComp.overlayOpacity, targetAlpha, 0.05); - } - } - draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this)); + pinsComp.slots[0].value = storageComp.storedItem; + pinsComp.slots[1].value = storageComp.getIsFull() ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON; + } } /** * @param {DrawParameters} parameters - * @param {Entity} entity + * @param {MapChunkView} chunk */ - drawEntity(parameters, entity) { - const context = parameters.context; - const staticComp = entity.components.StaticMapEntity; + drawChunk(parameters, chunk) { + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const storageComp = entity.components.Storage; + if (!storageComp) { + continue; + } - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } + const storedItem = storageComp.storedItem; + if (!storedItem) { + continue; + } - const storageComp = entity.components.Storage; + if (this.drawnUids.has(entity.uid)) { + continue; + } - const storedItem = storageComp.storedItem; - if (storedItem !== null) { + this.drawnUids.add(entity.uid); + + const staticComp = entity.components.StaticMapEntity; + + const context = parameters.context; context.globalAlpha = storageComp.overlayOpacity; const center = staticComp.getTileSpaceBounds().getCenter().toWorldSpace(); - storedItem.draw(center.x, center.y, parameters, 30); + storedItem.drawItemCenteredClipped(center.x, center.y, parameters, 30); this.storageOverlaySprite.drawCached(parameters, center.x - 15, center.y + 15, 30, 15); - context.font = "bold 10px GameFont"; - context.textAlign = "center"; - context.fillStyle = "#64666e"; - context.fillText(formatBigNumber(storageComp.storedCount), center.x, center.y + 25.5); - - context.textAlign = "left"; + if (parameters.visibleRect.containsCircle(center.x, center.y + 25, 20)) { + context.font = "bold 10px GameFont"; + context.textAlign = "center"; + context.fillStyle = "#64666e"; + context.fillText(formatBigNumber(storageComp.storedCount), center.x, center.y + 25.5); + context.textAlign = "left"; + } context.globalAlpha = 1; } } diff --git a/src/js/game/systems/underground_belt.js b/src/js/game/systems/underground_belt.js index f5e1b0ab..90d29e50 100644 --- a/src/js/game/systems/underground_belt.js +++ b/src/js/game/systems/underground_belt.js @@ -13,7 +13,6 @@ import { enumUndergroundBeltMode, UndergroundBeltComponent } from "../components import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; import { fastArrayDelete } from "../../core/utils"; -import { enumLayer } from "../root"; const logger = createLogger("tunnels"); @@ -298,7 +297,7 @@ export class UndergroundBeltSystem extends GameSystemWithFilter { ) { currentTile = currentTile.add(searchVector); - const potentialReceiver = this.root.map.getTileContent(currentTile, enumLayer.regular); + const potentialReceiver = this.root.map.getTileContent(currentTile, "regular"); if (!potentialReceiver) { // Empty tile continue; @@ -395,7 +394,7 @@ export class UndergroundBeltSystem extends GameSystemWithFilter { if (remainingTime <= 0) { const ejectorComp = entity.components.ItemEjector; - const nextSlotIndex = ejectorComp.getFirstFreeSlot(entity.layer); + const nextSlotIndex = ejectorComp.getFirstFreeSlot(); if (nextSlotIndex !== null) { if (ejectorComp.tryEject(nextSlotIndex, nextItem)) { items.shift(); diff --git a/src/js/game/systems/wire.js b/src/js/game/systems/wire.js new file mode 100644 index 00000000..fa9287e1 --- /dev/null +++ b/src/js/game/systems/wire.js @@ -0,0 +1,774 @@ +import { globalConfig } from "../../core/config"; +import { gMetaBuildingRegistry } from "../../core/global_registries"; +import { Loader } from "../../core/loader"; +import { createLogger } from "../../core/logging"; +import { Rectangle } from "../../core/rectangle"; +import { StaleAreaDetector } from "../../core/stale_area_detector"; +import { fastArrayDeleteValueIfContained } from "../../core/utils"; +import { + arrayAllDirections, + enumDirection, + enumDirectionToVector, + enumInvertedDirections, + Vector, +} from "../../core/vector"; +import { BaseItem } from "../base_item"; +import { isTrueItem } from "../items/boolean_item"; +import { arrayWireRotationVariantToType, MetaWireBuilding } from "../buildings/wire"; +import { getCodeFromBuildingData } from "../building_codes"; +import { enumWireType, WireComponent } from "../components/wire"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { WireTunnelComponent } from "../components/wire_tunnel"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { MapChunkView } from "../map_chunk_view"; +import { defaultBuildingVariant } from "../meta_building"; + +const logger = createLogger("wires"); + +let networkUidCounter = 0; + +const VERBOSE_WIRES = G_IS_DEV && false; + +export class WireNetwork { + constructor() { + /** + * Who contributes to this network + * @type {Array<{ entity: Entity, slot: import("../components/wired_pins").WirePinSlot }>} */ + this.providers = []; + + /** + * Who takes values from this network + * @type {Array<{ entity: Entity, slot: import("../components/wired_pins").WirePinSlot }>} */ + this.receivers = []; + + /** + * All connected slots + * @type {Array<{ entity: Entity, slot: import("../components/wired_pins").WirePinSlot }>} + */ + this.allSlots = []; + + /** + * All connected tunnels + * @type {Array} + */ + this.tunnels = []; + + /** + * Which wires are in this network + * @type {Array} + */ + this.wires = []; + + /** + * The current value of this network + * @type {BaseItem} + */ + this.currentValue = null; + + /** + * Whether this network has a value conflict, that is, more than one + * sender has sent a value + * @type {boolean} + */ + this.valueConflict = false; + + /** + * Unique network identifier + * @type {number} + */ + this.uid = ++networkUidCounter; + } +} + +export class WireSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [WireComponent]); + + this.wireSprites = { + regular: { + [enumWireType.regular]: Loader.getSprite("sprites/wires/sets/regular_forward.png"), + [enumWireType.turn]: Loader.getSprite("sprites/wires/sets/regular_turn.png"), + [enumWireType.split]: Loader.getSprite("sprites/wires/sets/regular_split.png"), + [enumWireType.cross]: Loader.getSprite("sprites/wires/sets/regular_cross.png"), + }, + conflict: { + [enumWireType.regular]: Loader.getSprite("sprites/wires/sets/conflict_forward.png"), + [enumWireType.turn]: Loader.getSprite("sprites/wires/sets/conflict_turn.png"), + [enumWireType.split]: Loader.getSprite("sprites/wires/sets/conflict_split.png"), + [enumWireType.cross]: Loader.getSprite("sprites/wires/sets/conflict_cross.png"), + }, + shape: { + [enumWireType.regular]: Loader.getSprite("sprites/wires/sets/shape_forward.png"), + [enumWireType.turn]: Loader.getSprite("sprites/wires/sets/shape_turn.png"), + [enumWireType.split]: Loader.getSprite("sprites/wires/sets/shape_split.png"), + [enumWireType.cross]: Loader.getSprite("sprites/wires/sets/shape_cross.png"), + }, + color: { + [enumWireType.regular]: Loader.getSprite("sprites/wires/sets/color_forward.png"), + [enumWireType.turn]: Loader.getSprite("sprites/wires/sets/color_turn.png"), + [enumWireType.split]: Loader.getSprite("sprites/wires/sets/color_split.png"), + [enumWireType.cross]: Loader.getSprite("sprites/wires/sets/color_cross.png"), + }, + }; + + this.root.signals.entityDestroyed.add(this.queuePlacementUpdate, this); + this.root.signals.entityAdded.add(this.queuePlacementUpdate, this); + + this.root.signals.entityDestroyed.add(this.queueRecomputeIfWire, this); + this.root.signals.entityChanged.add(this.queueRecomputeIfWire, this); + this.root.signals.entityAdded.add(this.queueRecomputeIfWire, this); + + this.needsRecompute = true; + this.isFirstRecompute = true; + + this.staleArea = new StaleAreaDetector({ + root: this.root, + name: "wires", + recomputeMethod: this.updateSurroundingWirePlacement.bind(this), + }); + + /** + * @type {Array} + */ + this.networks = []; + } + + /** + * Invalidates the wires network if the given entity is relevant for it + * @param {Entity} entity + */ + queueRecomputeIfWire(entity) { + if (!this.root.gameInitialized) { + return; + } + + if (this.isEntityRelevantForWires(entity)) { + this.needsRecompute = true; + this.networks = []; + } + } + + /** + * Recomputes the whole wires network + */ + recomputeWiresNetwork() { + this.needsRecompute = false; + logger.log("Recomputing wires network"); + + this.networks = []; + + const wireEntities = this.root.entityMgr.getAllWithComponent(WireComponent); + const tunnelEntities = this.root.entityMgr.getAllWithComponent(WireTunnelComponent); + const pinEntities = this.root.entityMgr.getAllWithComponent(WiredPinsComponent); + + // Clear all network references, but not on the first update since thats the deserializing one + if (!this.isFirstRecompute) { + for (let i = 0; i < wireEntities.length; ++i) { + wireEntities[i].components.Wire.linkedNetwork = null; + } + for (let i = 0; i < tunnelEntities.length; ++i) { + tunnelEntities[i].components.WireTunnel.linkedNetworks = []; + } + + for (let i = 0; i < pinEntities.length; ++i) { + const slots = pinEntities[i].components.WiredPins.slots; + for (let k = 0; k < slots.length; ++k) { + slots[k].linkedNetwork = null; + } + } + } else { + logger.log("Recomputing wires first time"); + this.isFirstRecompute = false; + } + + VERBOSE_WIRES && logger.log("Recomputing slots"); + + // Iterate over all ejector slots + for (let i = 0; i < pinEntities.length; ++i) { + const entity = pinEntities[i]; + const slots = entity.components.WiredPins.slots; + for (let k = 0; k < slots.length; ++k) { + const slot = slots[k]; + + // Ejectors are computed directly, acceptors are just set + if (slot.type === enumPinSlotType.logicalEjector && !slot.linkedNetwork) { + this.findNetworkForEjector(entity, slot); + } + } + } + } + + /** + * Finds the network for the given slot + * @param {Entity} initialEntity + * @param {import("../components/wired_pins").WirePinSlot} slot + */ + findNetworkForEjector(initialEntity, slot) { + let currentNetwork = new WireNetwork(); + VERBOSE_WIRES && + logger.log( + "Finding network for entity", + initialEntity.uid, + initialEntity.components.StaticMapEntity.origin.toString(), + "(nw-id:", + currentNetwork.uid, + ")" + ); + const entitiesToVisit = [ + { + entity: initialEntity, + slot, + }, + ]; + + while (entitiesToVisit.length > 0) { + const nextData = entitiesToVisit.pop(); + const nextEntity = nextData.entity; + + const wireComp = nextEntity.components.Wire; + const staticComp = nextEntity.components.StaticMapEntity; + + VERBOSE_WIRES && logger.log("Visiting", staticComp.origin.toString(), "(", nextEntity.uid, ")"); + + // Where to search for neighbours + let newSearchDirections = []; + let newSearchTile = null; + + //// WIRE + if (wireComp) { + // Sanity check + assert( + !wireComp.linkedNetwork || wireComp.linkedNetwork === currentNetwork, + "Mismatching wire network on wire entity " + + (wireComp.linkedNetwork ? wireComp.linkedNetwork.uid : "") + + " vs " + + currentNetwork.uid + + " @ " + + staticComp.origin.toString() + ); + + if (!wireComp.linkedNetwork) { + // This one is new! :D + VERBOSE_WIRES && logger.log(" Visited new wire:", staticComp.origin.toString()); + wireComp.linkedNetwork = currentNetwork; + currentNetwork.wires.push(nextEntity); + + newSearchDirections = arrayAllDirections; + newSearchTile = nextEntity.components.StaticMapEntity.origin; + } + } + + //// PINS + const pinsComp = nextEntity.components.WiredPins; + if (pinsComp) { + const slot = nextData.slot; + assert(slot, "No slot set for next entity"); + + if (slot.type === enumPinSlotType.logicalEjector) { + VERBOSE_WIRES && + logger.log(" Visiting ejector slot", staticComp.origin.toString(), "->", slot.type); + } else if (slot.type === enumPinSlotType.logicalAcceptor) { + VERBOSE_WIRES && + logger.log(" Visiting acceptor slot", staticComp.origin.toString(), "->", slot.type); + } else { + assertAlways(false, "Bad slot type: " + slot.type); + } + + // Sanity check + assert( + !slot.linkedNetwork || slot.linkedNetwork === currentNetwork, + "Mismatching wire network on pin slot entity " + + (slot.linkedNetwork ? slot.linkedNetwork.uid : "") + + " vs " + + currentNetwork.uid + ); + if (!slot.linkedNetwork) { + // This one is new + VERBOSE_WIRES && logger.log(" Visited new slot:", staticComp.origin.toString()); + + // Add to the right list + if (slot.type === enumPinSlotType.logicalEjector) { + currentNetwork.providers.push({ entity: nextEntity, slot }); + } else if (slot.type === enumPinSlotType.logicalAcceptor) { + currentNetwork.receivers.push({ entity: nextEntity, slot }); + } else { + assertAlways(false, "unknown slot type:" + slot.type); + } + + // Register on the network + currentNetwork.allSlots.push({ entity: nextEntity, slot }); + slot.linkedNetwork = currentNetwork; + + // Specify where to search next + newSearchDirections = [staticComp.localDirectionToWorld(slot.direction)]; + newSearchTile = staticComp.localTileToWorld(slot.pos); + } + } + + if (newSearchTile) { + // Find new surrounding wire targets + const newTargets = this.findSurroundingWireTargets( + newSearchTile, + newSearchDirections, + currentNetwork + ); + + VERBOSE_WIRES && logger.log(" Found", newTargets, "new targets to visit!"); + for (let i = 0; i < newTargets.length; ++i) { + entitiesToVisit.push(newTargets[i]); + } + } + } + + if ( + currentNetwork.providers.length > 0 && + (currentNetwork.wires.length > 0 || + currentNetwork.receivers.length > 0 || + currentNetwork.tunnels.length > 0) + ) { + this.networks.push(currentNetwork); + VERBOSE_WIRES && logger.log("Attached new network with uid", currentNetwork); + } else { + // Unregister network again + for (let i = 0; i < currentNetwork.wires.length; ++i) { + currentNetwork.wires[i].components.Wire.linkedNetwork = null; + } + + for (let i = 0; i < currentNetwork.tunnels.length; ++i) { + fastArrayDeleteValueIfContained( + currentNetwork.tunnels[i].components.WireTunnel.linkedNetworks, + currentNetwork + ); + } + + for (let i = 0; i < currentNetwork.allSlots.length; ++i) { + currentNetwork.allSlots[i].slot.linkedNetwork = null; + } + } + } + + /** + * Finds surrounding entities which are not yet assigned to a network + * @param {Vector} initialTile + * @param {Array} directions + * @param {WireNetwork} network + * @returns {Array} + */ + findSurroundingWireTargets(initialTile, directions, network) { + let result = []; + + VERBOSE_WIRES && + logger.log(" Searching for new targets at", initialTile.toString(), "and d=", directions); + + // Go over all directions we should search for + for (let i = 0; i < directions.length; ++i) { + const direction = directions[i]; + const offset = enumDirectionToVector[direction]; + const initialSearchTile = initialTile.add(offset); + + // Store which tunnels we already visited to avoid infinite loops + const visitedTunnels = new Set(); + + // First, find the initial connected entities + const initialContents = this.root.map.getLayersContentsMultipleXY( + initialSearchTile.x, + initialSearchTile.y + ); + + // Link the initial tile to the initial entities, since it may change + /** @type {Array<{entity: Entity, tile: Vector}>} */ + const contents = []; + for (let j = 0; j < initialContents.length; ++j) { + contents.push({ + entity: initialContents[j], + tile: initialSearchTile, + }); + } + + for (let k = 0; k < contents.length; ++k) { + const { entity, tile } = contents[k]; + const wireComp = entity.components.Wire; + + // Check for wire + if (wireComp && !wireComp.linkedNetwork) { + // Wires accept connections from everywhere + result.push({ + entity, + }); + } + + // Check for connected slots + const pinComp = entity.components.WiredPins; + if (pinComp) { + const staticComp = entity.components.StaticMapEntity; + + // Go over all slots and see if they are connected + const pinSlots = pinComp.slots; + for (let j = 0; j < pinSlots.length; ++j) { + const slot = pinSlots[j]; + + // Check if the position matches + const pinPos = staticComp.localTileToWorld(slot.pos); + if (!pinPos.equals(tile)) { + continue; + } + + // Check if the direction (inverted) matches + const pinDirection = staticComp.localDirectionToWorld(slot.direction); + if (pinDirection !== enumInvertedDirections[direction]) { + continue; + } + + if (!slot.linkedNetwork) { + result.push({ + entity, + slot, + }); + } + } + + // Pin slots mean it can be nothing else + continue; + } + + // Check if its a tunnel, if so, go to the forwarded item + const tunnelComp = entity.components.WireTunnel; + if (tunnelComp) { + if (visitedTunnels.has(entity.uid)) { + continue; + } + + const staticComp = entity.components.StaticMapEntity; + + if ( + !tunnelComp.multipleDirections && + !( + direction === staticComp.localDirectionToWorld(enumDirection.top) || + direction === staticComp.localDirectionToWorld(enumDirection.bottom) + ) + ) { + // It's a coating, and it doesn't connect here + continue; + } + + // Compute where this tunnel connects to + const forwardedTile = staticComp.origin.add(offset); + VERBOSE_WIRES && + logger.log( + " Found tunnel", + entity.uid, + "at", + tile, + "-> forwarding to", + forwardedTile + ); + + // Figure out which entities are connected + const connectedContents = this.root.map.getLayersContentsMultipleXY( + forwardedTile.x, + forwardedTile.y + ); + + // Attach the entities and the tile we search at, because it may change + for (let h = 0; h < connectedContents.length; ++h) { + contents.push({ + entity: connectedContents[h], + tile: forwardedTile, + }); + } + + // Add the tunnel to the network + if (tunnelComp.linkedNetworks.indexOf(network) < 0) { + tunnelComp.linkedNetworks.push(network); + } + if (network.tunnels.indexOf(entity) < 0) { + network.tunnels.push(entity); + } + + // Remember this tunnel + visitedTunnels.add(entity.uid); + } + } + } + + VERBOSE_WIRES && logger.log(" -> Found", result.length); + + return result; + } + + /** + * Updates the wires network + */ + update() { + this.staleArea.update(); + + if (this.needsRecompute) { + this.recomputeWiresNetwork(); + } + + // Re-compute values of all networks + for (let i = 0; i < this.networks.length; ++i) { + const network = this.networks[i]; + + // Reset conflicts + network.valueConflict = false; + + // Aggregate values of all senders + const senders = network.providers; + let value = null; + for (let k = 0; k < senders.length; ++k) { + const senderSlot = senders[k]; + const slotValue = senderSlot.slot.value; + + // The first sender can just put in his value + if (!value) { + value = slotValue; + continue; + } + + // If the slot is empty itself, just skip it + if (!slotValue) { + continue; + } + + // If there is already an value, compare if it matches -> + // otherwise there is a conflict + if (value.equals(slotValue)) { + // All good + continue; + } + + // There is a conflict, this means the value will be null anyways + network.valueConflict = true; + break; + } + + // Assign value + if (network.valueConflict) { + network.currentValue = null; + } else { + network.currentValue = value; + } + } + } + + /** + * Returns the given tileset and opacity + * @param {WireComponent} wireComp + * @returns {{ spriteSet: Object, opacity: number}} + */ + getSpriteSetAndOpacityForWire(wireComp) { + if (!wireComp.linkedNetwork) { + // There is no network, it's empty + return { + spriteSet: this.wireSprites.regular, + opacity: 0.3, + }; + } + + const network = wireComp.linkedNetwork; + if (network.valueConflict) { + // There is a conflict + return { + spriteSet: this.wireSprites.conflict, + opacity: 1, + }; + } + + const value = network.currentValue; + if (!value) { + // There is no value stored + return { + spriteSet: this.wireSprites.regular, + opacity: 0.3, + }; + } + + const valueType = value.getItemType(); + if (valueType === "shape") { + return { + spriteSet: this.wireSprites.shape, + opacity: 1, + }; + } else if (valueType === "color") { + return { + spriteSet: this.wireSprites.color, + opacity: 1, + }; + } else if (valueType === "boolean") { + return { + spriteSet: this.wireSprites.regular, + opacity: isTrueItem(value) ? 1 : 0.5, + }; + } else { + assertAlways(false, "Unknown item type: " + valueType); + } + + return { + spriteSet: this.wireSprites.regular, + opacity: 1, + }; + } + + /** + * Draws a given chunk + * @param {import("../../core/draw_utils").DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + const contents = chunk.wireContents; + for (let y = 0; y < globalConfig.mapChunkSize; ++y) { + for (let x = 0; x < globalConfig.mapChunkSize; ++x) { + const entity = contents[x][y]; + if (entity && entity.components.Wire) { + const wireComp = entity.components.Wire; + const wireType = wireComp.type; + + const { opacity, spriteSet } = this.getSpriteSetAndOpacityForWire(wireComp); + + const sprite = spriteSet[wireType]; + + assert(sprite, "Unknown wire type: " + wireType); + const staticComp = entity.components.StaticMapEntity; + parameters.context.globalAlpha = opacity; + staticComp.drawSpriteOnBoundsClipped(parameters, sprite, 0); + parameters.context.globalAlpha = 1; + + if (G_IS_DEV && globalConfig.debug.renderWireRotations) { + parameters.context.fillStyle = "red"; + parameters.context.font = "5px Tahoma"; + parameters.context.fillText( + "" + staticComp.originalRotation, + staticComp.origin.x * globalConfig.tileSize, + staticComp.origin.y * globalConfig.tileSize + 5 + ); + + parameters.context.fillStyle = "rgba(255, 0, 0, 0.2)"; + if (staticComp.originalRotation % 180 === 0) { + parameters.context.fillRect( + (staticComp.origin.x + 0.5) * globalConfig.tileSize, + staticComp.origin.y * globalConfig.tileSize, + 3, + globalConfig.tileSize + ); + } else { + parameters.context.fillRect( + staticComp.origin.x * globalConfig.tileSize, + (staticComp.origin.y + 0.5) * globalConfig.tileSize, + globalConfig.tileSize, + 3 + ); + } + } + } + + // DEBUG Rendering + if (G_IS_DEV && globalConfig.debug.renderWireNetworkInfos) { + if (entity) { + const staticComp = entity.components.StaticMapEntity; + const wireComp = entity.components.Wire; + + // Draw network info for wires + if (wireComp && wireComp.linkedNetwork) { + parameters.context.fillStyle = "red"; + parameters.context.font = "5px Tahoma"; + parameters.context.fillText( + "W" + wireComp.linkedNetwork.uid, + (staticComp.origin.x + 0.5) * globalConfig.tileSize, + (staticComp.origin.y + 0.5) * globalConfig.tileSize + ); + } + } + } + } + } + } + + /** + * Returns whether this entity is relevant for the wires network + * @param {Entity} entity + */ + isEntityRelevantForWires(entity) { + return entity.components.Wire || entity.components.WiredPins || entity.components.WireTunnel; + } + + /** + * + * @param {Entity} entity + */ + queuePlacementUpdate(entity) { + if (!this.root.gameInitialized) { + return; + } + + if (!this.isEntityRelevantForWires(entity)) { + return; + } + + const staticComp = entity.components.StaticMapEntity; + if (!staticComp) { + return; + } + + // Invalidate affected area + const originalRect = staticComp.getTileSpaceBounds(); + const affectedArea = originalRect.expandedInAllDirections(1); + this.staleArea.invalidate(affectedArea); + } + + /** + * Updates the wire placement after an entity has been added / deleted + * @param {Rectangle} affectedArea + */ + updateSurroundingWirePlacement(affectedArea) { + const metaWire = gMetaBuildingRegistry.findByClass(MetaWireBuilding); + + for (let x = affectedArea.x; x < affectedArea.right(); ++x) { + for (let y = affectedArea.y; y < affectedArea.bottom(); ++y) { + const targetEntities = this.root.map.getLayersContentsMultipleXY(x, y); + for (let i = 0; i < targetEntities.length; ++i) { + const targetEntity = targetEntities[i]; + + const targetWireComp = targetEntity.components.Wire; + const targetStaticComp = targetEntity.components.StaticMapEntity; + + if (!targetWireComp) { + // Not a wire + continue; + } + + const { + rotation, + rotationVariant, + } = metaWire.computeOptimalDirectionAndRotationVariantAtTile({ + root: this.root, + tile: new Vector(x, y), + rotation: targetStaticComp.originalRotation, + variant: defaultBuildingVariant, + layer: targetEntity.layer, + }); + + // Compute delta to see if anything changed + const newType = arrayWireRotationVariantToType[rotationVariant]; + + if (targetStaticComp.rotation !== rotation || newType !== targetWireComp.type) { + // Change stuff + targetStaticComp.rotation = rotation; + metaWire.updateVariants(targetEntity, rotationVariant, defaultBuildingVariant); + + // Update code as well + targetStaticComp.code = getCodeFromBuildingData( + metaWire, + defaultBuildingVariant, + rotationVariant + ); + + // Make sure the chunks know about the update + this.root.signals.entityChanged.dispatch(targetEntity); + } + } + } + } + } +} diff --git a/src/js/game/systems/wired_pins.js b/src/js/game/systems/wired_pins.js index 853568ef..202691b8 100644 --- a/src/js/game/systems/wired_pins.js +++ b/src/js/game/systems/wired_pins.js @@ -1,27 +1,28 @@ import { globalConfig } from "../../core/config"; import { DrawParameters } from "../../core/draw_parameters"; +import { drawRotatedSprite } from "../../core/draw_utils"; import { Loader } from "../../core/loader"; -import { Vector } from "../../core/vector"; +import { STOP_PROPAGATION } from "../../core/signal"; +import { enumDirectionToAngle, Vector } from "../../core/vector"; import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; -import { enumLayer } from "../root"; -import { STOP_PROPAGATION } from "../../core/signal"; -import { drawRotatedSprite } from "../../core/draw_utils"; +import { MapChunkView } from "../map_chunk_view"; + +/** @type {Object} */ +const enumTypeToSize = { + boolean: 9, + shape: 9, + color: 14, +}; export class WiredPinsSystem extends GameSystemWithFilter { constructor(root) { super(root, [WiredPinsComponent]); this.pinSprites = { - [enumPinSlotType.positiveEnergyEjector]: Loader.getSprite("sprites/wires/pin_positive_eject.png"), - [enumPinSlotType.positiveEnergyAcceptor]: Loader.getSprite( - "sprites/wires/pin_positive_accept.png" - ), - [enumPinSlotType.negativeEnergyEjector]: Loader.getSprite("sprites/wires/pin_negative_eject.png"), - [enumPinSlotType.negativeEnergyAcceptor]: Loader.getSprite( - "sprites/wires/pin_negative_accept.png" - ), + [enumPinSlotType.logicalEjector]: Loader.getSprite("sprites/wires/logical_ejector.png"), + [enumPinSlotType.logicalAcceptor]: Loader.getSprite("sprites/wires/logical_acceptor.png"), }; this.root.signals.prePlacementCheck.add(this.prePlacementCheck, this); @@ -43,7 +44,7 @@ export class WiredPinsSystem extends GameSystemWithFilter { // If this entity is placed on the wires layer, make sure we don't // place it above a pin - if (entity.layer === enumLayer.wires) { + if (entity.layer === "wires") { for (let x = rect.x; x < rect.x + rect.w; ++x) { for (let y = rect.y; y < rect.y + rect.h; ++y) { // Find which entities are in same tiles of both layers @@ -58,7 +59,7 @@ export class WiredPinsSystem extends GameSystemWithFilter { continue; } - if (otherEntity.components.ReplaceableMapEntity) { + if (staticComp.getMetaBuilding().getIsReplaceable()) { // Don't mind here, even if there would be a collision we // could replace it continue; @@ -108,11 +109,13 @@ export class WiredPinsSystem extends GameSystemWithFilter { } // Check if there is any entity on that tile (Wired pins are always on the wires layer) - const collidingEntity = this.root.map.getLayerContentXY(worldPos.x, worldPos.y, enumLayer.wires); + const collidingEntity = this.root.map.getLayerContentXY(worldPos.x, worldPos.y, "wires"); // If there's an entity, and it can't get removed -> That's a collision - if (collidingEntity && !collidingEntity.components.ReplaceableMapEntity) { - return true; + if (collidingEntity) { + if (!collidingEntity.components.StaticMapEntity.getMetaBuilding().getIsReplaceable()) { + return true; + } } } return false; @@ -133,10 +136,10 @@ export class WiredPinsSystem extends GameSystemWithFilter { for (let i = 0; i < pinsComp.slots.length; ++i) { const slot = pinsComp.slots[i]; const worldPos = entity.components.StaticMapEntity.localTileToWorld(slot.pos); - const collidingEntity = this.root.map.getLayerContentXY(worldPos.x, worldPos.y, enumLayer.wires); + const collidingEntity = this.root.map.getLayerContentXY(worldPos.x, worldPos.y, "wires"); if (collidingEntity) { assertAlways( - collidingEntity.components.ReplaceableMapEntity, + collidingEntity.components.StaticMapEntity.getMetaBuilding().getIsReplaceable(), "Tried to replace non-repleaceable entity for pins" ); if (!this.root.logic.tryDeleteBuilding(collidingEntity)) { @@ -146,43 +149,88 @@ export class WiredPinsSystem extends GameSystemWithFilter { } } - update() { - // TODO - } - - /** - * Draws the pins - * @param {DrawParameters} parameters - */ - draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawSingleEntity.bind(this)); - } + update() {} /** * Draws a given entity * @param {DrawParameters} parameters - * @param {Entity} entity + * @param {MapChunkView} chunk */ - drawSingleEntity(parameters, entity) { - const staticComp = entity.components.StaticMapEntity; - const slots = entity.components.WiredPins.slots; + drawChunk(parameters, chunk) { + const contents = chunk.containedEntities; - for (let i = 0; i < slots.length; ++i) { - const slot = slots[i]; - const tile = staticComp.localTileToWorld(slot.pos); + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const pinsComp = entity.components.WiredPins; + if (!pinsComp) { + continue; + } - const worldPos = tile.toWorldSpaceCenterOfTile(); + const staticComp = entity.components.StaticMapEntity; + const slots = pinsComp.slots; - drawRotatedSprite({ - parameters, - sprite: this.pinSprites[slot.type], - x: worldPos.x, - y: worldPos.y, - angle: Math.radians(staticComp.rotation), - size: globalConfig.tileSize, - offsetX: 0, - offsetY: 0, - }); + for (let j = 0; j < slots.length; ++j) { + const slot = slots[j]; + const tile = staticComp.localTileToWorld(slot.pos); + + if (!chunk.tileSpaceRectangle.containsPoint(tile.x, tile.y)) { + // Doesn't belong to this chunk + continue; + } + const worldPos = tile.toWorldSpaceCenterOfTile(); + + // Culling + if ( + !parameters.visibleRect.containsCircle(worldPos.x, worldPos.y, globalConfig.halfTileSize) + ) { + continue; + } + + const effectiveRotation = Math.radians( + staticComp.rotation + enumDirectionToAngle[slot.direction] + ); + + if (staticComp.getMetaBuilding().getRenderPins()) { + drawRotatedSprite({ + parameters, + sprite: this.pinSprites[slot.type], + x: worldPos.x, + y: worldPos.y, + angle: effectiveRotation, + size: globalConfig.tileSize + 2, + offsetX: 0, + offsetY: 0, + }); + } + + // Draw contained item to visualize whats emitted + const value = slot.value; + if (value) { + const offset = new Vector(0, -9.1).rotated(effectiveRotation); + + value.drawItemCenteredClipped( + worldPos.x + offset.x, + worldPos.y + offset.y, + parameters, + enumTypeToSize[value.getItemType()] + ); + } + + // Debug view + if (G_IS_DEV && globalConfig.debug.renderWireNetworkInfos) { + const offset = new Vector(0, -10).rotated(effectiveRotation); + const network = slot.linkedNetwork; + parameters.context.fillStyle = "blue"; + parameters.context.font = "5px Tahoma"; + parameters.context.textAlign = "center"; + parameters.context.fillText( + network ? "S" + network.uid : "???", + (tile.x + 0.5) * globalConfig.tileSize + offset.x, + (tile.y + 0.5) * globalConfig.tileSize + offset.y + ); + parameters.context.textAlign = "left"; + } + } } } } diff --git a/src/js/game/themes/dark.json b/src/js/game/themes/dark.json index 626efa19..7466201f 100644 --- a/src/js/game/themes/dark.json +++ b/src/js/game/themes/dark.json @@ -1,48 +1,57 @@ -{ - "uiStyle": "dark", - "map": { - "background": "#2e2f37", - "grid": "rgba(255, 255, 255, 0.02)", - "gridLineWidth": 0.5, - - "selectionOverlay": "rgba(74, 163, 223, 0.7)", - "selectionOutline": "rgba(74, 163, 223, 0.5)", - "selectionBackground": "rgba(74, 163, 223, 0.2)", - - "directionLock": { - "regular": { - "color": "rgb(74, 237, 134)", - "background": "rgba(74, 237, 134, 0.2)" - }, - "wires": { - "color": "rgb(209, 107, 203)", - "background": "rgba(209, 107, 203, 0.2)" - } - }, - - "colorBlindPickerTile": "rgba(255, 255, 255, 0.5)", - - "resources": { - "shape": "#3d3f4a", - "red": "#4a3d3f", - "green": "#3e4a3d", - "blue": "#35384a" - }, - "chunkOverview": { - "empty": "#444856", - "filled": "#646b7d" - }, - - "wires": { - "pins": { - "energyEjector": "#c425d7" - } - } - }, - - "items": { - "outline": "#111418", - "outlineWidth": 0.75, - "circleBackground": "rgba(20, 30, 40, 0.3)" - } -} +{ + "uiStyle": "dark", + "map": { + "background": "#2e2f37", + "grid": "rgba(255, 255, 255, 0.02)", + "gridLineWidth": 0.5, + + "selectionOverlay": "rgba(74, 163, 223, 0.7)", + "selectionOutline": "rgba(74, 163, 223, 0.5)", + "selectionBackground": "rgba(74, 163, 223, 0.2)", + + "chunkBorders": "rgba(127, 190, 255, 0.04)", + + "directionLock": { + "regular": { + "color": "rgb(74, 237, 134)", + "background": "rgba(74, 237, 134, 0.2)" + }, + "wires": { + "color": "rgb(209, 107, 203)", + "background": "rgba(209, 107, 203, 0.2)" + } + }, + + "colorBlindPickerTile": "rgba(255, 255, 255, 0.5)", + + "resources": { + "shape": "#3d3f4a", + "red": "#4a3d3f", + "green": "#3e4a3d", + "blue": "#35384a" + }, + "chunkOverview": { + "empty": "#444856", + "filled": "#646b7d" + }, + + "wires": { + "overlayColor": "rgba(97, 161, 152, 0.75)", + "previewColor": "rgb(97, 161, 152, 0.5)", + "highlightColor": "rgba(0, 0, 255, 0.5)" + }, + + "connectedMiners": { + "overlay": "rgba(40, 50, 60, 0.5)", + "textColor": "#fff", + "textColorCapped": "#ef5072", + "background": "rgba(40, 50, 60, 0.8)" + } + }, + + "items": { + "outline": "#111418", + "outlineWidth": 0.75, + "circleBackground": "rgba(20, 30, 40, 0.3)" + } +} diff --git a/src/js/game/themes/light.json b/src/js/game/themes/light.json index 21599585..728135ab 100644 --- a/src/js/game/themes/light.json +++ b/src/js/game/themes/light.json @@ -1,49 +1,58 @@ -{ - "uiStyle": "light", - "map": { - "background": "#fff", - "grid": "#fafafa", - "gridLineWidth": 1, - - "selectionOverlay": "rgba(74, 163, 223, 0.7)", - "selectionOutline": "rgba(74, 163, 223, 0.5)", - "selectionBackground": "rgba(74, 163, 223, 0.2)", - - "directionLock": { - "regular": { - "color": "rgb(74, 237, 134)", - "background": "rgba(74, 237, 134, 0.2)" - }, - "wires": { - "color": "rgb(209, 107, 203)", - "background": "rgba(209, 107, 203, 0.2)" - } - }, - - "colorBlindPickerTile": "rgba(50, 50, 50, 0.4)", - - "resources": { - "shape": "#eaebec", - "red": "#ffbfc1", - "green": "#cbffc4", - "blue": "#bfdaff" - }, - - "chunkOverview": { - "empty": "#a6afbb", - "filled": "#c5ccd6" - }, - - "wires": { - "pins": { - "energyEjector": "#c425d7" - } - } - }, - - "items": { - "outline": "#55575a", - "outlineWidth": 0.75, - "circleBackground": "rgba(40, 50, 65, 0.1)" - } -} +{ + "uiStyle": "light", + "map": { + "background": "#fff", + "grid": "#fafafa", + "gridLineWidth": 1, + + "selectionOverlay": "rgba(74, 163, 223, 0.7)", + "selectionOutline": "rgba(74, 163, 223, 0.5)", + "selectionBackground": "rgba(74, 163, 223, 0.2)", + + "chunkBorders": "rgba(0, 30, 50, 0.03)", + + "directionLock": { + "regular": { + "color": "rgb(74, 237, 134)", + "background": "rgba(74, 237, 134, 0.2)" + }, + "wires": { + "color": "rgb(209, 107, 203)", + "background": "rgba(209, 107, 203, 0.2)" + } + }, + + "colorBlindPickerTile": "rgba(50, 50, 50, 0.4)", + + "resources": { + "shape": "#eaebec", + "red": "#ffbfc1", + "green": "#cbffc4", + "blue": "#bfdaff" + }, + + "chunkOverview": { + "empty": "#a6afbb", + "filled": "#c5ccd6" + }, + + "wires": { + "overlayColor": "rgba(97, 161, 152, 0.75)", + "previewColor": "rgb(97, 161, 152, 0.4)", + "highlightColor": "rgba(72, 137, 255, 1)" + }, + + "connectedMiners": { + "overlay": "rgba(40, 50, 60, 0.5)", + "textColor": "#fff", + "textColorCapped": "#ef5072", + "background": "rgba(40, 50, 60, 0.8)" + } + }, + + "items": { + "outline": "#55575a", + "outlineWidth": 0.75, + "circleBackground": "rgba(40, 50, 65, 0.1)" + } +} diff --git a/src/js/game/time/game_time.js b/src/js/game/time/game_time.js index 7d0c310d..07b224a7 100644 --- a/src/js/game/time/game_time.js +++ b/src/js/game/time/game_time.js @@ -1,219 +1,200 @@ -/* typehints:start */ -import { GameRoot } from "../root"; -/* typehints:end */ - -import { types, BasicSerializableObject } from "../../savegame/serialization"; -import { RegularGameSpeed } from "./regular_game_speed"; -import { BaseGameSpeed } from "./base_game_speed"; -import { PausedGameSpeed } from "./paused_game_speed"; -import { FastForwardGameSpeed } from "./fast_forward_game_speed"; -import { gGameSpeedRegistry } from "../../core/global_registries"; -import { globalConfig } from "../../core/config"; -import { checkTimerExpired, quantizeFloat } from "../../core/utils"; -import { createLogger } from "../../core/logging"; - -const logger = createLogger("game_time"); - -export class GameTime extends BasicSerializableObject { - /** - * @param {GameRoot} root - */ - constructor(root) { - super(); - this.root = root; - - // Current ingame time seconds, not incremented while paused - this.timeSeconds = 0; - - // Current "realtime", a timer which always is incremented no matter whether the game is paused or no - this.realtimeSeconds = 0; - - // The adjustment, used when loading savegames so we can continue where we were - this.realtimeAdjust = 0; - - /** @type {BaseGameSpeed} */ - this.speed = new RegularGameSpeed(this.root); - - // Store how much time we have in bucket - this.logicTimeBudget = 0; - } - - static getId() { - return "GameTime"; - } - - static getSchema() { - return { - timeSeconds: types.float, - speed: types.obj(gGameSpeedRegistry), - realtimeSeconds: types.float, - }; - } - - /** - * Fetches the new "real" time, called from the core once per frame, since performance now() is kinda slow - */ - updateRealtimeNow() { - this.realtimeSeconds = performance.now() / 1000.0 + this.realtimeAdjust; - } - - /** - * Returns the ingame time in milliseconds - */ - getTimeMs() { - return this.timeSeconds * 1000.0; - } - - /** - * Safe check to check if a timer is expired. quantizes numbers - * @param {number} lastTick Last tick of the timer - * @param {number} tickRateSeconds Interval of the timer in seconds - */ - isIngameTimerExpired(lastTick, tickRateSeconds) { - return checkTimerExpired(this.timeSeconds, lastTick, tickRateSeconds); - } - - /** - * Returns how many seconds we are in the grace period - * @returns {number} - */ - getRemainingGracePeriodSeconds() { - return 0; - } - - /** - * Returns if we are currently in the grace period - * @returns {boolean} - */ - getIsWithinGracePeriod() { - return this.getRemainingGracePeriodSeconds() > 0; - } - - /** - * Internal method to generate new logic time budget - * @param {number} deltaMs - */ - internalAddDeltaToBudget(deltaMs) { - // Only update if game is supposed to update - if (this.root.hud.shouldPauseGame()) { - this.logicTimeBudget = 0; - } else { - const multiplier = this.getSpeed().getTimeMultiplier(); - this.logicTimeBudget += deltaMs * multiplier; - } - - // Check for too big pile of updates -> reduce it to 1 - let maxLogicSteps = Math.max( - 3, - (this.speed.getMaxLogicStepsInQueue() * this.root.dynamicTickrate.currentTickRate) / 60 - ); - if (G_IS_DEV && globalConfig.debug.framePausesBetweenTicks) { - maxLogicSteps *= 1 + globalConfig.debug.framePausesBetweenTicks; - } - - if (this.logicTimeBudget > this.root.dynamicTickrate.deltaMs * maxLogicSteps) { - this.logicTimeBudget = this.root.dynamicTickrate.deltaMs * maxLogicSteps; - } - } - - /** - * Performs update ticks based on the queued logic budget - * @param {number} deltaMs - * @param {function():boolean} updateMethod - */ - performTicks(deltaMs, updateMethod) { - this.internalAddDeltaToBudget(deltaMs); - - const speedAtStart = this.root.time.getSpeed(); - - let effectiveDelta = this.root.dynamicTickrate.deltaMs; - if (G_IS_DEV && globalConfig.debug.framePausesBetweenTicks) { - effectiveDelta += globalConfig.debug.framePausesBetweenTicks * this.root.dynamicTickrate.deltaMs; - } - - // Update physics & logic - while (this.logicTimeBudget >= effectiveDelta) { - this.logicTimeBudget -= effectiveDelta; - - if (!updateMethod()) { - // Gameover happened or so, do not update anymore - return; - } - - // Step game time - this.timeSeconds = quantizeFloat(this.timeSeconds + this.root.dynamicTickrate.deltaSeconds); - - // Game time speed changed, need to abort since our logic steps are no longer valid - if (speedAtStart.getId() !== this.speed.getId()) { - logger.warn( - "Skipping update because speed changed from", - speedAtStart.getId(), - "to", - this.speed.getId() - ); - break; - } - - // If we queued async tasks, perform them next frame and do not update anymore - if (this.root.hud.parts.processingOverlay.hasTasks()) { - break; - } - } - } - - /** - * Returns ingame time in seconds - * @returns {number} seconds - */ - now() { - return this.timeSeconds; - } - - /** - * Returns "real" time in seconds - * @returns {number} seconds - */ - realtimeNow() { - return this.realtimeSeconds; - } - - /** - * Returns "real" time in seconds - * @returns {number} seconds - */ - systemNow() { - return (this.realtimeSeconds - this.realtimeAdjust) * 1000.0; - } - - getIsPaused() { - return this.speed.getId() === PausedGameSpeed.getId(); - } - - getSpeed() { - return this.speed; - } - - setSpeed(speed) { - assert(speed instanceof BaseGameSpeed, "Not a valid game speed"); - if (this.speed.getId() === speed.getId()) { - logger.warn("Same speed set than current one:", speed.constructor.getId()); - } - this.speed = speed; - } - - deserialize(data) { - const errorCode = super.deserialize(data); - if (errorCode) { - return errorCode; - } - - // Adjust realtime now difference so they match - this.realtimeAdjust = this.realtimeSeconds - performance.now() / 1000.0; - this.updateRealtimeNow(); - - // Make sure we have a quantizied time - this.timeSeconds = quantizeFloat(this.timeSeconds); - - this.speed.initializeAfterDeserialize(this.root); - } -} +/* typehints:start */ +import { GameRoot } from "../root"; +/* typehints:end */ + +import { types, BasicSerializableObject } from "../../savegame/serialization"; +import { RegularGameSpeed } from "./regular_game_speed"; +import { BaseGameSpeed } from "./base_game_speed"; +import { PausedGameSpeed } from "./paused_game_speed"; +import { gGameSpeedRegistry } from "../../core/global_registries"; +import { globalConfig } from "../../core/config"; +import { createLogger } from "../../core/logging"; + +const logger = createLogger("game_time"); + +export class GameTime extends BasicSerializableObject { + /** + * @param {GameRoot} root + */ + constructor(root) { + super(); + this.root = root; + + // Current ingame time seconds, not incremented while paused + this.timeSeconds = 0; + + // Current "realtime", a timer which always is incremented no matter whether the game is paused or no + this.realtimeSeconds = 0; + + // The adjustment, used when loading savegames so we can continue where we were + this.realtimeAdjust = 0; + + /** @type {BaseGameSpeed} */ + this.speed = new RegularGameSpeed(this.root); + + // Store how much time we have in bucket + this.logicTimeBudget = 0; + } + + static getId() { + return "GameTime"; + } + + static getSchema() { + return { + timeSeconds: types.float, + speed: types.obj(gGameSpeedRegistry), + realtimeSeconds: types.float, + }; + } + + /** + * Fetches the new "real" time, called from the core once per frame, since performance now() is kinda slow + */ + updateRealtimeNow() { + this.realtimeSeconds = performance.now() / 1000.0 + this.realtimeAdjust; + } + + /** + * Returns the ingame time in milliseconds + */ + getTimeMs() { + return this.timeSeconds * 1000.0; + } + + /** + * Returns how many seconds we are in the grace period + * @returns {number} + */ + getRemainingGracePeriodSeconds() { + return 0; + } + + /** + * Returns if we are currently in the grace period + * @returns {boolean} + */ + getIsWithinGracePeriod() { + return this.getRemainingGracePeriodSeconds() > 0; + } + + /** + * Internal method to generate new logic time budget + * @param {number} deltaMs + */ + internalAddDeltaToBudget(deltaMs) { + // Only update if game is supposed to update + if (this.root.hud.shouldPauseGame()) { + this.logicTimeBudget = 0; + } else { + const multiplier = this.getSpeed().getTimeMultiplier(); + this.logicTimeBudget += deltaMs * multiplier; + } + + // Check for too big pile of updates -> reduce it to 1 + let maxLogicSteps = Math.max( + 3, + (this.speed.getMaxLogicStepsInQueue() * this.root.dynamicTickrate.currentTickRate) / 60 + ); + if (G_IS_DEV && globalConfig.debug.framePausesBetweenTicks) { + maxLogicSteps *= 1 + globalConfig.debug.framePausesBetweenTicks; + } + + if (this.logicTimeBudget > this.root.dynamicTickrate.deltaMs * maxLogicSteps) { + this.logicTimeBudget = this.root.dynamicTickrate.deltaMs * maxLogicSteps; + } + } + + /** + * Performs update ticks based on the queued logic budget + * @param {number} deltaMs + * @param {function():boolean} updateMethod + */ + performTicks(deltaMs, updateMethod) { + this.internalAddDeltaToBudget(deltaMs); + + const speedAtStart = this.root.time.getSpeed(); + + let effectiveDelta = this.root.dynamicTickrate.deltaMs; + if (G_IS_DEV && globalConfig.debug.framePausesBetweenTicks) { + effectiveDelta += globalConfig.debug.framePausesBetweenTicks * this.root.dynamicTickrate.deltaMs; + } + + // Update physics & logic + while (this.logicTimeBudget >= effectiveDelta) { + this.logicTimeBudget -= effectiveDelta; + + if (!updateMethod()) { + // Gameover happened or so, do not update anymore + return; + } + + // Step game time + this.timeSeconds += this.root.dynamicTickrate.deltaSeconds; + + // Game time speed changed, need to abort since our logic steps are no longer valid + if (speedAtStart.getId() !== this.speed.getId()) { + logger.warn( + "Skipping update because speed changed from", + speedAtStart.getId(), + "to", + this.speed.getId() + ); + break; + } + } + } + + /** + * Returns ingame time in seconds + * @returns {number} seconds + */ + now() { + return this.timeSeconds; + } + + /** + * Returns "real" time in seconds + * @returns {number} seconds + */ + realtimeNow() { + return this.realtimeSeconds; + } + + /** + * Returns "real" time in seconds + * @returns {number} seconds + */ + systemNow() { + return (this.realtimeSeconds - this.realtimeAdjust) * 1000.0; + } + + getIsPaused() { + return this.speed.getId() === PausedGameSpeed.getId(); + } + + getSpeed() { + return this.speed; + } + + setSpeed(speed) { + assert(speed instanceof BaseGameSpeed, "Not a valid game speed"); + if (this.speed.getId() === speed.getId()) { + logger.warn("Same speed set than current one:", speed.constructor.getId()); + } + this.speed = speed; + } + + deserialize(data) { + const errorCode = super.deserialize(data); + if (errorCode) { + return errorCode; + } + + // Adjust realtime now difference so they match + this.realtimeAdjust = this.realtimeSeconds - performance.now() / 1000.0; + this.updateRealtimeNow(); + + this.speed.initializeAfterDeserialize(this.root); + } +} diff --git a/src/js/game/tutorial_goals.js b/src/js/game/tutorial_goals.js index 366877ee..9084f508 100644 --- a/src/js/game/tutorial_goals.js +++ b/src/js/game/tutorial_goals.js @@ -1,178 +1,182 @@ -import { ShapeDefinition } from "./shape_definition"; -import { finalGameShape } from "./upgrades"; - -/** - * Don't forget to also update tutorial_goals_mappings.js as well as the translations! - * @enum {string} - */ -export const enumHubGoalRewards = { - reward_cutter_and_trash: "reward_cutter_and_trash", - reward_rotater: "reward_rotater", - reward_painter: "reward_painter", - reward_mixer: "reward_mixer", - reward_stacker: "reward_stacker", - reward_splitter: "reward_splitter", - reward_tunnel: "reward_tunnel", - - reward_rotater_ccw: "reward_rotater_ccw", - reward_miner_chainable: "reward_miner_chainable", - reward_underground_belt_tier_2: "reward_underground_belt_tier_2", - reward_splitter_compact: "reward_splitter_compact", - reward_cutter_quad: "reward_cutter_quad", - reward_painter_double: "reward_painter_double", - reward_painter_quad: "reward_painter_quad", - reward_storage: "reward_storage", - - reward_blueprints: "reward_blueprints", - reward_freeplay: "reward_freeplay", - - no_reward: "no_reward", - no_reward_freeplay: "no_reward_freeplay", -}; - -export const tutorialGoals = [ - // 1 - // Circle - { - shape: "CuCuCuCu", // belts t1 - required: 40, - reward: enumHubGoalRewards.reward_cutter_and_trash, - }, - - // 2 - // Cutter - { - shape: "----CuCu", // - required: 40, - reward: enumHubGoalRewards.no_reward, - }, - - // 3 - // Rectangle - { - shape: "RuRuRuRu", // miners t1 - required: 100, - reward: enumHubGoalRewards.reward_splitter, - }, - - // 4 - { - shape: "RuRu----", // processors t2 - required: 120, - reward: enumHubGoalRewards.reward_rotater, - }, - - // 5 - // Rotater - { - shape: "Cu----Cu", // belts t2 - required: 200, - reward: enumHubGoalRewards.reward_tunnel, - }, - - // 6 - { - shape: "Cu------", // miners t2 - required: 400, - reward: enumHubGoalRewards.reward_painter, - }, - - // 7 - // Painter - { - shape: "CrCrCrCr", // unused - required: 800, - reward: enumHubGoalRewards.reward_rotater_ccw, - }, - - // 8 - { - shape: "RbRb----", // painter t2 - required: 1000, - reward: enumHubGoalRewards.reward_mixer, - }, - - // 9 - // Mixing (purple) - { - shape: "CpCpCpCp", // belts t3 - required: 1400, - reward: enumHubGoalRewards.reward_splitter_compact, - }, - - // 10 - // Star shape + cyan - { - shape: "ScScScSc", // miners t3 - required: 1600, - reward: enumHubGoalRewards.reward_stacker, - }, - - // 11 - // Stacker - { - shape: "CgScScCg", // processors t3 - required: 1800, - reward: enumHubGoalRewards.reward_miner_chainable, - }, - - // 12 - // Blueprints - { - shape: "CbCbCbRb:CwCwCwCw", - required: 2000, - reward: enumHubGoalRewards.reward_blueprints, - }, - - // 13 - { - shape: "RpRpRpRp:CwCwCwCw", // painting t3 - required: 12000, - reward: enumHubGoalRewards.reward_underground_belt_tier_2, - }, - - // 14 - { - shape: "SrSrSrSr:CyCyCyCy", // unused - required: 16000, - reward: enumHubGoalRewards.reward_storage, - }, - - // 15 - { - shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", // belts t4 (two variants) - required: 25000, - reward: enumHubGoalRewards.reward_cutter_quad, - }, - - // 16 - { - shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants) - required: 50000, - reward: enumHubGoalRewards.reward_painter_double, - }, - - // 17 - { - shape: "WrRgWrRg:CwCrCwCr:SgSgSgSg", // processors t4 (two variants) - required: 120000, - reward: enumHubGoalRewards.reward_painter_quad, - }, - - // 18 - { - shape: finalGameShape, - required: 250000, - reward: enumHubGoalRewards.reward_freeplay, - }, -]; - -if (G_IS_DEV) { - tutorialGoals.forEach(({ shape }) => { - try { - ShapeDefinition.fromShortKey(shape); - } catch (ex) { - throw new Error("Invalid tutorial goal: '" + ex + "' for shape" + shape); - } - }); -} +import { ShapeDefinition } from "./shape_definition"; +import { finalGameShape } from "./upgrades"; + +/** + * Don't forget to also update tutorial_goals_mappings.js as well as the translations! + * @enum {string} + */ +export const enumHubGoalRewards = { + reward_cutter_and_trash: "reward_cutter_and_trash", + reward_rotater: "reward_rotater", + reward_painter: "reward_painter", + reward_mixer: "reward_mixer", + reward_stacker: "reward_stacker", + reward_splitter: "reward_splitter", + reward_tunnel: "reward_tunnel", + + reward_rotater_ccw: "reward_rotater_ccw", + reward_rotater_fl: "reward_rotater_fl", + reward_miner_chainable: "reward_miner_chainable", + reward_underground_belt_tier_2: "reward_underground_belt_tier_2", + reward_splitter_compact: "reward_splitter_compact", + reward_cutter_quad: "reward_cutter_quad", + reward_painter_double: "reward_painter_double", + reward_painter_quad: "reward_painter_quad", + reward_storage: "reward_storage", + + // @todo: unlock + reward_merger_compact: "reward_compact_merger", + + reward_blueprints: "reward_blueprints", + reward_freeplay: "reward_freeplay", + + no_reward: "no_reward", + no_reward_freeplay: "no_reward_freeplay", +}; + +export const tutorialGoals = [ + // 1 + // Circle + { + shape: "CuCuCuCu", // belts t1 + required: 40, + reward: enumHubGoalRewards.reward_cutter_and_trash, + }, + + // 2 + // Cutter + { + shape: "----CuCu", // + required: 40, + reward: enumHubGoalRewards.no_reward, + }, + + // 3 + // Rectangle + { + shape: "RuRuRuRu", // miners t1 + required: 100, + reward: enumHubGoalRewards.reward_splitter, + }, + + // 4 + { + shape: "RuRu----", // processors t2 + required: 120, + reward: enumHubGoalRewards.reward_rotater, + }, + + // 5 + // Rotater + { + shape: "Cu----Cu", // belts t2 + required: 200, + reward: enumHubGoalRewards.reward_tunnel, + }, + + // 6 + { + shape: "Cu------", // miners t2 + required: 400, + reward: enumHubGoalRewards.reward_painter, + }, + + // 7 + // Painter + { + shape: "CrCrCrCr", // unused + required: 800, + reward: enumHubGoalRewards.reward_rotater_ccw, + }, + + // 8 + { + shape: "RbRb----", // painter t2 + required: 1000, + reward: enumHubGoalRewards.reward_mixer, + }, + + // 9 + // Mixing (purple) + { + shape: "CpCpCpCp", // belts t3 + required: 1400, + reward: enumHubGoalRewards.reward_splitter_compact, + }, + + // 10 + // Star shape + cyan + { + shape: "ScScScSc", // miners t3 + required: 1600, + reward: enumHubGoalRewards.reward_stacker, + }, + + // 11 + // Stacker + { + shape: "CgScScCg", // processors t3 + required: 1800, + reward: enumHubGoalRewards.reward_miner_chainable, + }, + + // 12 + // Blueprints + { + shape: "CbCbCbRb:CwCwCwCw", + required: 2000, + reward: enumHubGoalRewards.reward_blueprints, + }, + + // 13 + { + shape: "RpRpRpRp:CwCwCwCw", // painting t3 + required: 12000, + reward: enumHubGoalRewards.reward_underground_belt_tier_2, + }, + + // 14 + { + shape: "SrSrSrSr:CyCyCyCy", // unused + required: 16000, + reward: enumHubGoalRewards.reward_storage, + }, + + // 15 + { + shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", // belts t4 (two variants) + required: 25000, + reward: enumHubGoalRewards.reward_cutter_quad, + }, + + // 16 + { + shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants) + required: 50000, + reward: enumHubGoalRewards.reward_painter_double, + }, + + // 17 + { + shape: "WrRgWrRg:CwCrCwCr:SgSgSgSg", // processors t4 (two variants) + required: 120000, + reward: enumHubGoalRewards.reward_painter_quad, + }, + + // 18 + { + shape: finalGameShape, + required: 250000, + reward: enumHubGoalRewards.reward_freeplay, + }, +]; + +if (G_IS_DEV) { + tutorialGoals.forEach(({ shape }) => { + try { + ShapeDefinition.fromShortKey(shape); + } catch (ex) { + throw new Error("Invalid tutorial goal: '" + ex + "' for shape" + shape); + } + }); +} diff --git a/src/js/game/tutorial_goals_mappings.js b/src/js/game/tutorial_goals_mappings.js index 905a623a..923c2814 100644 --- a/src/js/game/tutorial_goals_mappings.js +++ b/src/js/game/tutorial_goals_mappings.js @@ -33,6 +33,7 @@ export const enumHubGoalRewardsToContentUnlocked = { [enumHubGoalRewards.reward_tunnel]: typed([[MetaUndergroundBeltBuilding, defaultBuildingVariant]]), [enumHubGoalRewards.reward_rotater_ccw]: typed([[MetaRotaterBuilding, enumRotaterVariants.ccw]]), + [enumHubGoalRewards.reward_rotater_fl]: typed([[MetaRotaterBuilding, enumRotaterVariants.fl]]), [enumHubGoalRewards.reward_miner_chainable]: typed([[MetaMinerBuilding, enumMinerVariants.chainable]]), [enumHubGoalRewards.reward_underground_belt_tier_2]: typed([ [MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2], diff --git a/src/js/globals.d.ts b/src/js/globals.d.ts index bc99d55e..51e4a2c3 100644 --- a/src/js/globals.d.ts +++ b/src/js/globals.d.ts @@ -36,11 +36,6 @@ declare interface CanvasRenderingContext2D { webkitImageSmoothingEnabled: boolean; } -declare interface HTMLCanvasElement { - opaque: boolean; - webkitOpaque: boolean; -} - // Just for compatibility with the shared code declare interface Logger { log(...args); @@ -127,13 +122,6 @@ declare interface NodeRequire { context(src: string, flag: boolean, regexp: RegExp): WebpackContext; } -// HTML Element -declare interface Element { - style: any; - innerText: string; - innerHTML: string; -} - declare interface Object { entries(obj: object): Array<[string, any]>; } @@ -143,22 +131,24 @@ declare interface Math { degrees(number): number; } +declare type Class = new (...args: any[]) => T; + declare interface String { padStart(size: number, fill?: string): string; padEnd(size: number, fill: string): string; } declare interface FactoryTemplate { - entries: Array T>; + entries: Array>; entryIds: Array; idToEntry: any; getId(): string; getAllIds(): Array; - register(entry: new (...args: any[]) => T): void; + register(entry: Class): void; hasId(id: string): boolean; - findById(id: string): new (...args: any[]) => T; - getEntries(): Array T>; + findById(id: string): Class; + getEntries(): Array>; getNumEntries(): number; } @@ -168,10 +158,10 @@ declare interface SingletonFactoryTemplate { getId(): string; getAllIds(): Array; - register(classHandle: new (...args: any[]) => T): void; + register(classHandle: Class): void; hasId(id: string): boolean; findById(id: string): T; - findByClass(classHandle: new (...args: any[]) => T): T; + findByClass(classHandle: Class): T; getEntries(): Array; getNumEntries(): number; } @@ -202,3 +192,14 @@ declare interface TypedSignal> { removeAll(); } + +declare type Layer = "regular" | "wires"; +declare type ItemType = "shape" | "color" | "boolean"; + +declare module "worker-loader?inline=true&fallback=false!*" { + class WebpackWorker extends Worker { + constructor(); + } + + export default WebpackWorker; +} diff --git a/src/js/languages.js b/src/js/languages.js index cac22bcf..c46c3e88 100644 --- a/src/js/languages.js +++ b/src/js/languages.js @@ -81,6 +81,13 @@ export const LANGUAGES = { region: "", }, + "tr": { + name: "Türkçe", + data: require("./built-temp/base-tr.json"), + code: "tr", + region: "", + }, + "zh-CN": { // simplified name: "中文简体", diff --git a/src/js/platform/ad_providers/adinplay.js b/src/js/platform/ad_providers/adinplay.js index 00a08fcb..3897ec04 100644 --- a/src/js/platform/ad_providers/adinplay.js +++ b/src/js/platform/ad_providers/adinplay.js @@ -102,7 +102,10 @@ export class AdinplayAdProvider extends AdProviderInterface { // Add the player const videoElement = this.adContainerMainElement.querySelector(".videoInner"); - this.adContainerMainElement.querySelector(".adInner").style.maxWidth = w + "px"; + /** @type {HTMLElement} */ + const adInnerElement = this.adContainerMainElement.querySelector(".adInner"); + + adInnerElement.style.maxWidth = w + "px"; const self = this; window.aiptag.cmd.player.push(function () { diff --git a/src/js/platform/browser/game_analytics.js b/src/js/platform/browser/game_analytics.js index 73da3696..7336ffd9 100644 --- a/src/js/platform/browser/game_analytics.js +++ b/src/js/platform/browser/game_analytics.js @@ -85,10 +85,9 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface { * @returns {Promise} */ sendToApi(endpoint, data) { - return Promise.race([ - new Promise((resolve, reject) => { - setTimeout(() => reject("Request to " + endpoint + " timed out"), 20000); - }), + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => reject("Request to " + endpoint + " timed out"), 20000); + fetch(analyticsUrl + endpoint, { method: "POST", mode: "cors", @@ -103,13 +102,19 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface { body: JSON.stringify(data), }) .then(res => { + clearTimeout(timeout); if (!res.ok || res.status !== 200) { - throw new Error("Fetch error: Bad status " + res.status); + reject("Fetch error: Bad status " + res.status); + } else { + return res.json(); } - return res; }) - .then(res => res.json()), - ]); + .then(resolve) + .catch(reason => { + clearTimeout(timeout); + reject(reason); + }); + }); } /** diff --git a/src/js/platform/browser/sound.js b/src/js/platform/browser/sound.js index 508dcf8c..a837c2e4 100644 --- a/src/js/platform/browser/sound.js +++ b/src/js/platform/browser/sound.js @@ -146,9 +146,10 @@ class MusicInstance extends MusicInstanceInterface { return this.playing; } - play() { + play(volume) { if (this.howl) { this.playing = true; + this.howl.volume(volume); if (this.instance) { this.howl.play(this.instance); } else { @@ -157,6 +158,12 @@ class MusicInstance extends MusicInstanceInterface { } } + setVolume(volume) { + if (this.howl) { + this.howl.volume(volume); + } + } + deinitialize() { if (this.howl) { this.howl.unload(); @@ -178,6 +185,9 @@ export class SoundImplBrowser extends SoundInterface { } initialize() { + // NOTICE: We override the initialize() method here with custom logic because + // we have a sound sprites instance + this.sfxHandle = new SoundSpritesContainer(); // @ts-ignore @@ -191,11 +201,11 @@ export class SoundImplBrowser extends SoundInterface { this.music[musicPath] = music; } - this.musicMuted = this.app.settings.getAllSettings().musicMuted; - this.soundsMuted = this.app.settings.getAllSettings().soundsMuted; + this.musicVolume = this.app.settings.getAllSettings().musicVolume; + this.soundVolume = this.app.settings.getAllSettings().soundVolume; if (G_IS_DEV && globalConfig.debug.disableMusic) { - this.musicMuted = true; + this.musicVolume = 0.0; } return Promise.resolve(); diff --git a/src/js/platform/browser/wrapper.js b/src/js/platform/browser/wrapper.js index bbe9d221..56705025 100644 --- a/src/js/platform/browser/wrapper.js +++ b/src/js/platform/browser/wrapper.js @@ -82,7 +82,7 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface { return new Promise(resolve => { logger.log("Detecting storage"); - if (!window.indexedDB || G_IS_DEV) { + if (!window.indexedDB) { logger.log("Indexed DB not supported"); this.app.storage = new StorageImplBrowser(this.app); resolve(); @@ -95,6 +95,7 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface { request = window.indexedDB.open("indexeddb_feature_detection", 1); } catch (ex) { logger.warn("Error while opening indexed db:", ex); + this.app.storage = new StorageImplBrowser(this.app); resolve(); return; } diff --git a/src/js/platform/game_analytics.js b/src/js/platform/game_analytics.js index ea6aa293..765b2d67 100644 --- a/src/js/platform/game_analytics.js +++ b/src/js/platform/game_analytics.js @@ -1,8 +1,6 @@ -/* typehints:start */ -import { Application } from "../application"; -import { ShapeDefinition } from "../game/shape_definition"; -import { Savegame } from "../savegame/savegame"; -/* typehints:end */ +/** + * @typedef {import("../application").Application} Application + */ export class GameAnalyticsInterface { constructor(app) { diff --git a/src/js/platform/sound.js b/src/js/platform/sound.js index 60d472f8..0678abcf 100644 --- a/src/js/platform/sound.js +++ b/src/js/platform/sound.js @@ -28,7 +28,7 @@ export const SOUNDS = { }; export const MUSIC = { - theme: "theme", + theme: G_IS_STANDALONE ? "theme-full" : "theme-short", menu: "menu", }; @@ -61,7 +61,11 @@ export class MusicInstanceInterface { abstract; } - play() { + play(volume) { + abstract; + } + + setVolume(volume) { abstract; } @@ -99,8 +103,8 @@ export class SoundInterface { this.pageIsVisible = true; - this.musicMuted = false; - this.soundsMuted = false; + this.musicVolume = 1.0; + this.soundVolume = 1.0; } /** @@ -120,11 +124,11 @@ export class SoundInterface { this.music[musicPath] = music; } - this.musicMuted = this.app.settings.getAllSettings().musicMuted; - this.soundsMuted = this.app.settings.getAllSettings().soundsMuted; + this.musicVolume = this.app.settings.getAllSettings().musicVolume; + this.soundVolume = this.app.settings.getAllSettings().soundVolume; if (G_IS_DEV && globalConfig.debug.disableMusic) { - this.musicMuted = true; + this.musicVolume = 0.0; } return Promise.resolve(); @@ -162,44 +166,38 @@ export class SoundInterface { } /** - * Returns if the music is muted - * @returns {boolean} + * Returns the music volume + * @returns {number} */ - getMusicMuted() { - return this.musicMuted; + getMusicVolume() { + return this.musicVolume; } /** - * Returns if sounds are muted - * @returns {boolean} + * Returns the sound volume + * @returns {number} */ - getSoundsMuted() { - return this.soundsMuted; + getSoundVolume() { + return this.soundVolume; } /** - * Sets if the music is muted - * @param {boolean} muted + * Sets the music volume + * @param {number} volume */ - setMusicMuted(muted) { - this.musicMuted = muted; - if (this.musicMuted) { - if (this.currentMusic) { - this.currentMusic.stop(); - } - } else { - if (this.currentMusic) { - this.currentMusic.play(); - } + setMusicVolume(volume) { + this.musicVolume = clamp(volume, 0, 1); + if (this.currentMusic) { + this.currentMusic.setVolume(this.musicVolume); } } /** - * Sets if the sounds are muted - * @param {boolean} muted + * Sets the sound volume + * @param {number} volume */ - setSoundsMuted(muted) { - this.soundsMuted = muted; + setSoundVolume(volume) { + this.soundVolume = clamp(volume, 0, 1); } /** @@ -210,8 +208,8 @@ export class SoundInterface { this.pageIsVisible = pageIsVisible; if (this.currentMusic) { if (pageIsVisible) { - if (!this.currentMusic.isPlaying() && !this.musicMuted) { - this.currentMusic.play(); + if (!this.currentMusic.isPlaying()) { + this.currentMusic.play(this.musicVolume); } } else { this.currentMusic.stop(); @@ -223,14 +221,11 @@ export class SoundInterface { * @param {string} key */ playUiSound(key) { - if (this.soundsMuted) { - return; - } if (!this.sounds[key]) { logger.warn("Sound", key, "not found, probably not loaded yet"); return; } - this.sounds[key].play(1.0); + this.sounds[key].play(this.soundVolume); } /** @@ -244,7 +239,7 @@ export class SoundInterface { logger.warn("Music", key, "not found, probably not loaded yet"); return; } - if (!this.pageIsVisible || this.soundsMuted) { + if (!this.pageIsVisible) { return; } @@ -253,9 +248,9 @@ export class SoundInterface { return; } - let volume = 1.0; + let volume = this.soundVolume; if (!root.camera.isWorldPointOnScreen(worldPosition)) { - volume = 0.2; + volume = this.soundVolume / 5; // In the old implementation this value was fixed to 0.2 => 20% of 1.0 } volume *= clamp(root.camera.zoomLevel / 3); this.sounds[key].play(clamp(volume)); @@ -275,9 +270,9 @@ export class SoundInterface { this.currentMusic.stop(); } this.currentMusic = music; - if (music && this.pageIsVisible && !this.musicMuted) { + if (music && this.pageIsVisible) { logger.log("Starting", this.currentMusic.key); - music.play(); + music.play(this.musicVolume); } } } diff --git a/src/js/platform/wrapper.js b/src/js/platform/wrapper.js index 9fee5b3a..9c35a8e4 100644 --- a/src/js/platform/wrapper.js +++ b/src/js/platform/wrapper.js @@ -66,7 +66,7 @@ export class PlatformWrapperInterface { * @returns {number} */ getMinimumZoom() { - return 0.2 * this.getScreenScale(); + return 0.1 * this.getScreenScale(); } /** @@ -74,7 +74,7 @@ export class PlatformWrapperInterface { * @returns {number} */ getMaximumZoom() { - return 4 * this.getScreenScale(); + return 3.5 * this.getScreenScale(); } getScreenScale() { diff --git a/src/js/profile/application_settings.js b/src/js/profile/application_settings.js index 708c4d7b..084a6fe7 100644 --- a/src/js/profile/application_settings.js +++ b/src/js/profile/application_settings.js @@ -3,7 +3,7 @@ import { Application } from "../application"; /* typehints:end */ import { ReadWriteProxy } from "../core/read_write_proxy"; -import { BoolSetting, EnumSetting, BaseSetting } from "./setting_types"; +import { BoolSetting, EnumSetting, RangeSetting, BaseSetting } from "./setting_types"; import { createLogger } from "../core/logging"; import { ExplainedResult } from "../core/explained_result"; import { THEMES, THEME, applyGameTheme } from "../game/theme"; @@ -13,8 +13,15 @@ import { LANGUAGES } from "../languages"; const logger = createLogger("application_settings"); -const categoryGame = "game"; -const categoryApp = "app"; +/** + * @enum {string} + */ +export const enumCategories = { + general: "general", + userInterface: "userInterface", + performance: "performance", + advanced: "advanced", +}; export const uiScales = [ { @@ -116,13 +123,24 @@ export const autosaveIntervals = [ }, ]; +const refreshRateOptions = ["30", "60", "120", "180", "240"]; + +if (G_IS_DEV) { + refreshRateOptions.unshift("10"); + refreshRateOptions.unshift("5"); + refreshRateOptions.push("1000"); + refreshRateOptions.push("2000"); + refreshRateOptions.push("5000"); + refreshRateOptions.push("10000"); +} + /** @type {Array} */ export const allApplicationSettings = [ new EnumSetting("language", { options: Object.keys(LANGUAGES), valueGetter: key => key, textGetter: key => LANGUAGES[key].name, - category: categoryApp, + category: enumCategories.general, restartRequired: true, changeCb: (app, id) => null, magicValue: "auto-detect", @@ -132,7 +150,7 @@ export const allApplicationSettings = [ options: uiScales.sort((a, b) => a.size - b.size), valueGetter: scale => scale.id, textGetter: scale => T.settings.labels.uiScale.scales[scale.id], - category: categoryApp, + category: enumCategories.userInterface, restartRequired: false, changeCb: /** @@ -141,9 +159,26 @@ export const allApplicationSettings = [ (app, id) => app.updateAfterUiScaleChanged(), }), + new RangeSetting( + "soundVolume", + enumCategories.general, + /** + * @param {Application} app + */ + (app, value) => app.sound.setSoundVolume(value) + ), + new RangeSetting( + "musicVolume", + enumCategories.general, + /** + * @param {Application} app + */ + (app, value) => app.sound.setMusicVolume(value) + ), + new BoolSetting( "fullscreen", - categoryApp, + enumCategories.general, /** * @param {Application} app */ @@ -155,40 +190,22 @@ export const allApplicationSettings = [ !IS_DEMO ), - new BoolSetting( - "soundsMuted", - categoryApp, - /** - * @param {Application} app - */ - (app, value) => app.sound.setSoundsMuted(value) - ), - new BoolSetting( - "musicMuted", - categoryApp, - /** - * @param {Application} app - */ - (app, value) => app.sound.setMusicMuted(value) - ), - new BoolSetting( "enableColorBlindHelper", - categoryApp, + enumCategories.general, /** * @param {Application} app */ (app, value) => null ), - // GAME - new BoolSetting("offerHints", categoryGame, (app, value) => {}), + new BoolSetting("offerHints", enumCategories.userInterface, (app, value) => {}), new EnumSetting("theme", { options: Object.keys(THEMES), valueGetter: theme => theme, textGetter: theme => T.settings.labels.theme.themes[theme], - category: categoryGame, + category: enumCategories.userInterface, restartRequired: false, changeCb: /** @@ -205,7 +222,7 @@ export const allApplicationSettings = [ options: autosaveIntervals, valueGetter: interval => interval.id, textGetter: interval => T.settings.labels.autosaveInterval.intervals[interval.id], - category: categoryGame, + category: enumCategories.advanced, restartRequired: false, changeCb: /** @@ -214,21 +231,11 @@ export const allApplicationSettings = [ (app, id) => null, }), - new EnumSetting("refreshRate", { - options: ["60", "100", "120", "144", "165", "250", G_IS_DEV ? "10" : "500"], - valueGetter: rate => rate, - textGetter: rate => rate + " Hz", - category: categoryGame, - restartRequired: false, - changeCb: (app, id) => {}, - enabled: !IS_DEMO, - }), - new EnumSetting("scrollWheelSensitivity", { options: scrollWheelSensitivities.sort((a, b) => a.scale - b.scale), valueGetter: scale => scale.id, textGetter: scale => T.settings.labels.scrollWheelSensitivity.sensitivity[scale.id], - category: categoryGame, + category: enumCategories.advanced, restartRequired: false, changeCb: /** @@ -241,17 +248,34 @@ export const allApplicationSettings = [ options: movementSpeeds.sort((a, b) => a.multiplier - b.multiplier), valueGetter: multiplier => multiplier.id, textGetter: multiplier => T.settings.labels.movementSpeed.speeds[multiplier.id], - category: categoryGame, + category: enumCategories.advanced, restartRequired: false, changeCb: (app, id) => {}, }), - new BoolSetting("alwaysMultiplace", categoryGame, (app, value) => {}), - new BoolSetting("enableTunnelSmartplace", categoryGame, (app, value) => {}), - new BoolSetting("vignette", categoryGame, (app, value) => {}), - new BoolSetting("compactBuildingInfo", categoryGame, (app, value) => {}), - new BoolSetting("disableCutDeleteWarnings", categoryGame, (app, value) => {}), - new BoolSetting("rotationByBuilding", categoryGame, (app, value) => {}), + new BoolSetting("alwaysMultiplace", enumCategories.advanced, (app, value) => {}), + new BoolSetting("clearCursorOnDeleteWhilePlacing", enumCategories.advanced, (app, value) => {}), + new BoolSetting("enableTunnelSmartplace", enumCategories.advanced, (app, value) => {}), + new BoolSetting("vignette", enumCategories.userInterface, (app, value) => {}), + new BoolSetting("compactBuildingInfo", enumCategories.userInterface, (app, value) => {}), + new BoolSetting("disableCutDeleteWarnings", enumCategories.advanced, (app, value) => {}), + new BoolSetting("rotationByBuilding", enumCategories.advanced, (app, value) => {}), + new BoolSetting("displayChunkBorders", enumCategories.advanced, (app, value) => {}), + new BoolSetting("pickMinerOnPatch", enumCategories.advanced, (app, value) => {}), + + new EnumSetting("refreshRate", { + options: refreshRateOptions, + valueGetter: rate => rate, + textGetter: rate => rate + " Hz", + category: enumCategories.performance, + restartRequired: false, + changeCb: (app, id) => {}, + enabled: !IS_DEMO, + }), + + new BoolSetting("lowQualityMapResources", enumCategories.performance, (app, value) => {}), + new BoolSetting("disableTileGrid", enumCategories.performance, (app, value) => {}), + new BoolSetting("lowQualityTextures", enumCategories.performance, (app, value) => {}), ]; export function getApplicationSettingById(id) { @@ -263,8 +287,9 @@ class SettingsStorage { this.uiScale = "regular"; this.fullscreen = G_IS_STANDALONE; - this.soundsMuted = false; - this.musicMuted = false; + this.soundVolume = 1.0; + this.musicVolume = 1.0; + this.theme = "light"; this.refreshRate = "60"; this.scrollWheelSensitivity = "regular"; @@ -279,9 +304,16 @@ class SettingsStorage { this.compactBuildingInfo = false; this.disableCutDeleteWarnings = false; this.rotationByBuilding = true; + this.clearCursorOnDeleteWhilePlacing = true; + this.displayChunkBorders = false; + this.pickMinerOnPatch = true; this.enableColorBlindHelper = false; + this.lowQualityMapResources = false; + this.disableTileGrid = false; + this.lowQualityTextures = false; + /** * @type {Object.} */ @@ -407,7 +439,7 @@ export class ApplicationSettings extends ReadWriteProxy { /** * @param {string} key - * @param {string|boolean} value + * @param {string|boolean|number} value */ updateSetting(key, value) { for (let i = 0; i < allApplicationSettings.length; ++i) { @@ -467,7 +499,17 @@ export class ApplicationSettings extends ReadWriteProxy { const setting = allApplicationSettings[i]; const storedValue = settings[setting.id]; if (!setting.validate(storedValue)) { - return ExplainedResult.bad("Bad setting value for " + setting.id + ": " + storedValue); + return ExplainedResult.bad( + "Bad setting value for " + + setting.id + + ": " + + storedValue + + " @ settings version " + + data.version + + " (latest is " + + this.getCurrentVersion() + + ")" + ); } } return ExplainedResult.good(); @@ -481,7 +523,7 @@ export class ApplicationSettings extends ReadWriteProxy { } getCurrentVersion() { - return 18; + return 26; } /** @param {{settings: SettingsStorage, version: number}} data */ @@ -559,6 +601,51 @@ export class ApplicationSettings extends ReadWriteProxy { data.version = 18; } + if (data.version < 19) { + data.settings.lowQualityMapResources = false; + data.version = 19; + } + + if (data.version < 20) { + data.settings.disableTileGrid = false; + data.version = 20; + } + + if (data.version < 21) { + data.settings.lowQualityTextures = false; + data.version = 21; + } + + if (data.version < 22) { + data.settings.clearCursorOnDeleteWhilePlacing = true; + data.version = 22; + } + + if (data.version < 23) { + data.settings.displayChunkBorders = false; + data.version = 23; + } + + if (data.version < 24) { + data.settings.refreshRate = "60"; + } + + if (data.version < 25) { + data.settings.musicVolume = 0.5; + data.settings.soundVolume = 0.5; + + // @ts-ignore + delete data.settings.musicMuted; + // @ts-ignore + delete data.settings.soundsMuted; + data.version = 25; + } + + if (data.version < 26) { + data.settings.pickMinerOnPatch = true; + data.version = 26; + } + return ExplainedResult.good(); } } diff --git a/src/js/profile/setting_types.js b/src/js/profile/setting_types.js index 1255f961..7d07ca99 100644 --- a/src/js/profile/setting_types.js +++ b/src/js/profile/setting_types.js @@ -40,7 +40,7 @@ export class BaseSetting { /** * @param {Application} app - * @param {Element} element + * @param {HTMLElement} element * @param {any} dialogs */ bind(app, element, dialogs) { @@ -188,7 +188,7 @@ export class BoolSetting extends BaseSetting { return `
${this.enabled ? "" : `${T.demo.settingNotAvailable}`} - +
@@ -220,3 +220,103 @@ export class BoolSetting extends BaseSetting { return typeof value === "boolean"; } } + +export class RangeSetting extends BaseSetting { + constructor( + id, + category, + changeCb = null, + enabled = true, + defaultValue = 1.0, + minValue = 0, + maxValue = 1.0, + stepSize = 0.0001 + ) { + super(id, category, changeCb, enabled); + + this.defaultValue = defaultValue; + this.minValue = minValue; + this.maxValue = maxValue; + this.stepSize = stepSize; + } + + getHtml() { + return ` +
+ ${this.enabled ? "" : `${T.demo.settingNotAvailable}`} + +
+ +
+ + +
+
+
+ ${T.settings.labels[this.id].description} +
+
`; + } + + bind(app, element, dialogs) { + this.app = app; + this.element = element; + this.dialogs = dialogs; + + this.getRangeInputElement().addEventListener("input", () => { + this.updateLabels(); + }); + + this.getRangeInputElement().addEventListener("change", () => { + this.modify(); + }); + } + + syncValueToElement() { + const value = this.app.settings.getSetting(this.id); + this.setElementValue(value); + } + + /** + * Sets the elements value to the given value + * @param {number} value + */ + setElementValue(value) { + const rangeInput = this.getRangeInputElement(); + const rangeLabel = this.element.querySelector("label"); + rangeInput.value = String(value); + rangeLabel.innerHTML = T.settings.rangeSliderPercentage.replace( + "", + String(Math.round(value * 100.0)) + ); + } + + updateLabels() { + const value = Number(this.getRangeInputElement().value); + this.setElementValue(value); + } + + /** + * @returns {HTMLInputElement} + */ + getRangeInputElement() { + return this.element.querySelector("input.rangeInput"); + } + + modify() { + const rangeInput = this.getRangeInputElement(); + const newValue = Math.round(Number(rangeInput.value) * 100.0) / 100.0; + this.app.settings.updateSetting(this.id, newValue); + this.syncValueToElement(); + console.log("SET", newValue); + if (this.changeCb) { + this.changeCb(this.app, newValue); + } + } + + validate(value) { + return typeof value === "number" && value >= this.minValue && value <= this.maxValue; + } +} diff --git a/src/js/savegame/savegame.js b/src/js/savegame/savegame.js index 1db813d7..2a7102a9 100644 --- a/src/js/savegame/savegame.js +++ b/src/js/savegame/savegame.js @@ -1,8 +1,3 @@ -/* typehints:start */ -import { Application } from "../application"; -import { GameRoot } from "../game/root"; -/* typehints:end */ - import { ReadWriteProxy } from "../core/read_write_proxy"; import { ExplainedResult } from "../core/explained_result"; import { SavegameSerializer } from "./savegame_serializer"; @@ -18,20 +13,29 @@ import { SavegameInterface_V1005 } from "./schemas/1005"; const logger = createLogger("savegame"); +/** + * @typedef {import("../application").Application} Application + * @typedef {import("../game/root").GameRoot} GameRoot + * @typedef {import("./savegame_typedefs").SavegameData} SavegameData + * @typedef {import("./savegame_typedefs").SavegameMetadata} SavegameMetadata + * @typedef {import("./savegame_typedefs").SavegameStats} SavegameStats + * @typedef {import("./savegame_typedefs").SerializedGame} SerializedGame + */ + export class Savegame extends ReadWriteProxy { /** * * @param {Application} app * @param {object} param0 * @param {string} param0.internalId - * @param {import("./savegame_manager").SavegameMetadata} param0.metaDataRef Handle to the meta data + * @param {SavegameMetadata} param0.metaDataRef Handle to the meta data */ constructor(app, { internalId, metaDataRef }) { super(app, "savegame-" + internalId + ".bin"); this.internalId = internalId; this.metaDataRef = metaDataRef; - /** @type {import("./savegame_typedefs").SavegameData} */ + /** @type {SavegameData} */ this.currentData = this.getDefaultData(); assert( @@ -65,7 +69,7 @@ export class Savegame extends ReadWriteProxy { /** * Returns the savegames default data - * @returns {import("./savegame_typedefs").SavegameData} + * @returns {SavegameData} */ getDefaultData() { return { @@ -78,7 +82,7 @@ export class Savegame extends ReadWriteProxy { /** * Migrates the savegames data - * @param {import("./savegame_typedefs").SavegameData} data + * @param {SavegameData} data */ migrate(data) { if (data.version < 1000) { @@ -115,7 +119,7 @@ export class Savegame extends ReadWriteProxy { /** * Verifies the savegames data - * @param {import("./savegame_typedefs").SavegameData} data + * @param {SavegameData} data */ verify(data) { if (!data.dump) { @@ -140,7 +144,7 @@ export class Savegame extends ReadWriteProxy { } /** * Returns the statistics of the savegame - * @returns {import("./savegame_typedefs").SavegameStats} + * @returns {SavegameStats} */ getStatistics() { return this.currentData.stats; @@ -163,7 +167,7 @@ export class Savegame extends ReadWriteProxy { /** * Returns the current game dump - * @returns {import("./savegame_typedefs").SerializedGame} + * @returns {SerializedGame} */ getCurrentDump() { return this.currentData.dump; diff --git a/src/js/savegame/savegame_compressor.js b/src/js/savegame/savegame_compressor.js index 4962171e..bc14baf7 100644 --- a/src/js/savegame/savegame_compressor.js +++ b/src/js/savegame/savegame_compressor.js @@ -44,16 +44,18 @@ function decompressInt(s) { } // Sanity -for (let i = 0; i < 10000; ++i) { - if (decompressInt(compressInt(i)) !== i) { - throw new Error( - "Bad compression for: " + - i + - " compressed: " + - compressInt(i) + - " decompressed: " + - decompressInt(compressInt(i)) - ); +if (G_IS_DEV) { + for (let i = 0; i < 10000; ++i) { + if (decompressInt(compressInt(i)) !== i) { + throw new Error( + "Bad compression for: " + + i + + " compressed: " + + compressInt(i) + + " decompressed: " + + decompressInt(compressInt(i)) + ); + } } } @@ -88,9 +90,6 @@ function compressObjectInternal(obj, keys = [], values = []) { } export function compressObject(obj) { - if (G_IS_DEV) { - return obj; - } const keys = []; const values = []; const data = compressObjectInternal(obj, keys, values); diff --git a/src/js/savegame/savegame_manager.js b/src/js/savegame/savegame_manager.js index e3052806..52f9dc14 100644 --- a/src/js/savegame/savegame_manager.js +++ b/src/js/savegame/savegame_manager.js @@ -1,228 +1,225 @@ -import { ExplainedResult } from "../core/explained_result"; -import { createLogger } from "../core/logging"; -import { ReadWriteProxy } from "../core/read_write_proxy"; -import { globalConfig } from "../core/config"; -import { Savegame } from "./savegame"; -const logger = createLogger("savegame_manager"); - -const Rusha = require("rusha"); - -/** @enum {string} */ -export const enumLocalSavegameStatus = { - offline: "offline", - synced: "synced", -}; - -/** - * @typedef {{ - * lastUpdate: number, - * version: number, - * internalId: string, - * level: number - * }} SavegameMetadata - * - * @typedef {{ - * version: number, - * savegames: Array - * }} SavegamesData - */ - -export class SavegameManager extends ReadWriteProxy { - constructor(app) { - super(app, "savegames.bin"); - - /** @type {SavegamesData} */ - this.currentData = this.getDefaultData(); - } - - // RW Proxy Impl - /** - * @returns {SavegamesData} - */ - getDefaultData() { - return { - version: this.getCurrentVersion(), - savegames: [], - }; - } - - getCurrentVersion() { - return 1001; - } - - /** - * @returns {SavegamesData} - */ - getCurrentData() { - return super.getCurrentData(); - } - - verify(data) { - // TODO / FIXME!!!! - return ExplainedResult.good(); - } - - /** - * - * @param {SavegamesData} data - */ - migrate(data) { - if (data.version < 1001) { - data.savegames.forEach(savegame => { - savegame.level = 0; - }); - data.version = 1001; - } - - return ExplainedResult.good(); - } - - // End rw proxy - - /** - * @returns {Array} - */ - getSavegamesMetaData() { - return this.currentData.savegames; - } - - /** - * - * @param {string} internalId - * @returns {Savegame} - */ - getSavegameById(internalId) { - const metadata = this.getGameMetaDataByInternalId(internalId); - if (!metadata) { - return null; - } - return new Savegame(this.app, { internalId, metaDataRef: metadata }); - } - - /** - * Deletes a savegame - * @param {SavegameMetadata} game - */ - deleteSavegame(game) { - const handle = new Savegame(this.app, { - internalId: game.internalId, - metaDataRef: game, - }); - - return handle.deleteAsync().then(() => { - for (let i = 0; i < this.currentData.savegames.length; ++i) { - const potentialGame = this.currentData.savegames[i]; - if (potentialGame.internalId === handle.internalId) { - this.currentData.savegames.splice(i, 1); - break; - } - } - - return this.writeAsync(); - }); - } - - /** - * Returns a given games metadata by id - * @param {string} id - * @returns {SavegameMetadata} - */ - getGameMetaDataByInternalId(id) { - for (let i = 0; i < this.currentData.savegames.length; ++i) { - const data = this.currentData.savegames[i]; - if (data.internalId === id) { - return data; - } - } - logger.error("Savegame internal id not found:", id); - return null; - } - - /** - * Creates a new savegame - * @returns {Savegame} - */ - createNewSavegame() { - const id = this.generateInternalId(); - - const metaData = /** @type {SavegameMetadata} */ ({ - lastUpdate: Date.now(), - version: Savegame.getCurrentVersion(), - internalId: id, - }); - - this.currentData.savegames.push(metaData); - this.sortSavegames(); - - return new Savegame(this.app, { - internalId: id, - metaDataRef: metaData, - }); - } - - importSavegame(data) { - const savegame = this.createNewSavegame(); - const migrationResult = savegame.migrate(data); - if (migrationResult.isBad()) { - return Promise.reject("Failed to migrate: " + migrationResult.reason); - } - - savegame.currentData = data; - const verification = savegame.verify(data); - if (verification.isBad()) { - return Promise.reject("Verification failed: " + verification.result); - } - - return savegame.writeSavegameAndMetadata().then(() => this.sortSavegames()); - } - - /** - * Sorts all savegames by their creation time descending - * @returns {Promise} - */ - sortSavegames() { - this.currentData.savegames.sort((a, b) => b.lastUpdate - a.lastUpdate); - let promiseChain = Promise.resolve(); - while (this.currentData.savegames.length > 30) { - const toRemove = this.currentData.savegames.pop(); - - // Try to remove the savegame since its no longer available - const game = new Savegame(this.app, { - internalId: toRemove.internalId, - metaDataRef: toRemove, - }); - promiseChain = promiseChain - .then(() => game.deleteAsync()) - .then( - () => {}, - err => { - logger.error(this, "Failed to remove old savegame:", toRemove, ":", err); - } - ); - } - - return promiseChain; - } - - /** - * Helper method to generate a new internal savegame id - */ - generateInternalId() { - return Rusha.createHash() - .update(Date.now() + "/" + Math.random()) - .digest("hex"); - } - - // End - - initialize() { - // First read, then directly write to ensure we have the latest data - // @ts-ignore - return this.readAsync().then(() => { - if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) { - return Promise.resolve(); - } - return this.sortSavegames().then(() => this.writeAsync()); - }); - } -} +import { ExplainedResult } from "../core/explained_result"; +import { createLogger } from "../core/logging"; +import { ReadWriteProxy } from "../core/read_write_proxy"; +import { globalConfig } from "../core/config"; +import { Savegame } from "./savegame"; +const logger = createLogger("savegame_manager"); + +const Rusha = require("rusha"); + +/** + * @typedef {import("./savegame_typedefs").SavegamesData} SavegamesData + * @typedef {import("./savegame_typedefs").SavegameMetadata} SavegameMetadata + */ + +/** @enum {string} */ +export const enumLocalSavegameStatus = { + offline: "offline", + synced: "synced", +}; + +export class SavegameManager extends ReadWriteProxy { + constructor(app) { + super(app, "savegames.bin"); + + this.currentData = this.getDefaultData(); + } + + // RW Proxy Impl + /** + * @returns {SavegamesData} + */ + getDefaultData() { + return { + version: this.getCurrentVersion(), + savegames: [], + }; + } + + getCurrentVersion() { + return 1002; + } + + /** + * @returns {SavegamesData} + */ + getCurrentData() { + return super.getCurrentData(); + } + + verify(data) { + // TODO / FIXME!!!! + return ExplainedResult.good(); + } + + /** + * + * @param {SavegamesData} data + */ + migrate(data) { + if (data.version < 1001) { + data.savegames.forEach(savegame => { + savegame.level = 0; + }); + data.version = 1001; + } + + if (data.version < 1002) { + data.savegames.forEach(savegame => { + savegame.name = null; + }); + data.version = 1002; + } + + return ExplainedResult.good(); + } + + // End rw proxy + + /** + * @returns {Array} + */ + getSavegamesMetaData() { + return this.currentData.savegames; + } + + /** + * + * @param {string} internalId + * @returns {Savegame} + */ + getSavegameById(internalId) { + const metadata = this.getGameMetaDataByInternalId(internalId); + if (!metadata) { + return null; + } + return new Savegame(this.app, { internalId, metaDataRef: metadata }); + } + + /** + * Deletes a savegame + * @param {SavegameMetadata} game + */ + deleteSavegame(game) { + const handle = new Savegame(this.app, { + internalId: game.internalId, + metaDataRef: game, + }); + + return handle.deleteAsync().then(() => { + for (let i = 0; i < this.currentData.savegames.length; ++i) { + const potentialGame = this.currentData.savegames[i]; + if (potentialGame.internalId === handle.internalId) { + this.currentData.savegames.splice(i, 1); + break; + } + } + + return this.writeAsync(); + }); + } + + /** + * Returns a given games metadata by id + * @param {string} id + * @returns {SavegameMetadata} + */ + getGameMetaDataByInternalId(id) { + for (let i = 0; i < this.currentData.savegames.length; ++i) { + const data = this.currentData.savegames[i]; + if (data.internalId === id) { + return data; + } + } + logger.error("Savegame internal id not found:", id); + return null; + } + + /** + * Creates a new savegame + * @returns {Savegame} + */ + createNewSavegame() { + const id = this.generateInternalId(); + + const metaData = /** @type {SavegameMetadata} */ ({ + lastUpdate: Date.now(), + version: Savegame.getCurrentVersion(), + internalId: id, + }); + + this.currentData.savegames.push(metaData); + this.sortSavegames(); + + return new Savegame(this.app, { + internalId: id, + metaDataRef: metaData, + }); + } + + importSavegame(data) { + const savegame = this.createNewSavegame(); + const migrationResult = savegame.migrate(data); + if (migrationResult.isBad()) { + return Promise.reject("Failed to migrate: " + migrationResult.reason); + } + + savegame.currentData = data; + const verification = savegame.verify(data); + if (verification.isBad()) { + return Promise.reject("Verification failed: " + verification.result); + } + + return savegame.writeSavegameAndMetadata().then(() => this.sortSavegames()); + } + + /** + * Sorts all savegames by their creation time descending + * @returns {Promise} + */ + sortSavegames() { + this.currentData.savegames.sort((a, b) => b.lastUpdate - a.lastUpdate); + let promiseChain = Promise.resolve(); + while (this.currentData.savegames.length > 30) { + const toRemove = this.currentData.savegames.pop(); + + // Try to remove the savegame since its no longer available + const game = new Savegame(this.app, { + internalId: toRemove.internalId, + metaDataRef: toRemove, + }); + promiseChain = promiseChain + .then(() => game.deleteAsync()) + .then( + () => {}, + err => { + logger.error(this, "Failed to remove old savegame:", toRemove, ":", err); + } + ); + } + + return promiseChain; + } + + /** + * Helper method to generate a new internal savegame id + */ + generateInternalId() { + return Rusha.createHash() + .update(Date.now() + "/" + Math.random()) + .digest("hex"); + } + + // End + + initialize() { + // First read, then directly write to ensure we have the latest data + // @ts-ignore + return this.readAsync().then(() => { + if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) { + return Promise.resolve(); + } + return this.sortSavegames().then(() => this.writeAsync()); + }); + } +} diff --git a/src/js/savegame/savegame_serializer.js b/src/js/savegame/savegame_serializer.js index eff802a0..92db738b 100644 --- a/src/js/savegame/savegame_serializer.js +++ b/src/js/savegame/savegame_serializer.js @@ -1,18 +1,20 @@ -/* typehints:start */ -import { Component } from "../game/component"; -import { GameRoot } from "../game/root"; -/* typehints:end */ - import { ExplainedResult } from "../core/explained_result"; import { createLogger } from "../core/logging"; -// import { BuildingComponent } from "../components/impl/building"; import { gComponentRegistry } from "../core/global_registries"; import { SerializerInternal } from "./serializer_internal"; +/** + * @typedef {import("../game/component").Component} Component + * @typedef {import("../game/component").StaticComponent} StaticComponent + * @typedef {import("../game/entity").Entity} Entity + * @typedef {import("../game/root").GameRoot} GameRoot + * @typedef {import("../savegame/savegame_typedefs").SerializedGame} SerializedGame + */ + const logger = createLogger("savegame_serializer"); /** - * Allows to serialize a savegame + * Serializes a savegame */ export class SavegameSerializer { constructor() { @@ -26,7 +28,7 @@ export class SavegameSerializer { * @returns {object} */ generateDumpFromGameRoot(root, sanityChecks = true) { - // Now store generic savegame payload + /** @type {SerializedGame} */ const data = { camera: root.camera.serialize(), time: root.time.serialize(), @@ -35,11 +37,10 @@ export class SavegameSerializer { hubGoals: root.hubGoals.serialize(), pinnedShapes: root.hud.parts.pinnedShapes.serialize(), waypoints: root.hud.parts.waypoints.serialize(), + entities: this.internal.serializeEntityArray(root.entityMgr.entities), beltPaths: root.systemMgr.systems.belt.serializePaths(), }; - data.entities = this.internal.serializeEntityArray(root.entityMgr.entities); - if (!G_IS_RELEASE) { if (sanityChecks) { // Sanity check @@ -55,7 +56,7 @@ export class SavegameSerializer { /** * Verifies if there are logical errors in the savegame - * @param {object} savegame + * @param {SerializedGame} savegame * @returns {ExplainedResult} */ verifyLogicalErrors(savegame) { @@ -66,47 +67,44 @@ export class SavegameSerializer { const seenUids = []; // Check for duplicate UIDS - for (const entityListId in savegame.entities) { - for (let i = 0; i < savegame.entities[entityListId].length; ++i) { - const list = savegame.entities[entityListId][i]; - for (let k = 0; k < list.length; ++k) { - const entity = list[k]; - const uid = entity.uid; - if (!Number.isInteger(uid)) { - return ExplainedResult.bad("Entity has invalid uid: " + uid); - } - if (seenUids.indexOf(uid) >= 0) { - return ExplainedResult.bad("Duplicate uid " + uid); - } - seenUids.push(uid); + for (let i = 0; i < savegame.entities.length; ++i) { + /** @type {Entity} */ + const entity = savegame.entities[i]; - // Verify components - if (!entity.components) { - return ExplainedResult.bad( - "Entity is missing key 'components': " + JSON.stringify(entity) - ); - } - const components = entity.components; - for (const componentId in components) { - // Verify component data - const componentData = components[componentId]; - const componentClass = gComponentRegistry.findById(componentId); + const uid = entity.uid; + if (!Number.isInteger(uid)) { + return ExplainedResult.bad("Entity has invalid uid: " + uid); + } + if (seenUids.indexOf(uid) >= 0) { + return ExplainedResult.bad("Duplicate uid " + uid); + } + seenUids.push(uid); - // Check component id is known - if (!componentClass) { - return ExplainedResult.bad("Unknown component id: " + componentId); - } + // Verify components + if (!entity.components) { + return ExplainedResult.bad("Entity is missing key 'components': " + JSON.stringify(entity)); + } - // Check component data is ok - const componentVerifyError = /** @type {typeof Component} */ (componentClass).verify( - componentData - ); - if (componentVerifyError) { - return ExplainedResult.bad( - "Component " + componentId + " has invalid data: " + componentVerifyError - ); - } - } + const components = entity.components; + for (const componentId in components) { + const componentClass = gComponentRegistry.findById(componentId); + + // Check component id is known + if (!componentClass) { + return ExplainedResult.bad("Unknown component id: " + componentId); + } + + // Verify component data + const componentData = components[componentId]; + const componentVerifyError = /** @type {StaticComponent} */ (componentClass).verify( + componentData + ); + + // Check component data is ok + if (componentVerifyError) { + return ExplainedResult.bad( + "Component " + componentId + " has invalid data: " + componentVerifyError + ); } } } @@ -116,7 +114,7 @@ export class SavegameSerializer { /** * Tries to load the savegame from a given dump - * @param {import("./savegame_typedefs").SerializedGame} savegame + * @param {SerializedGame} savegame * @param {GameRoot} root * @returns {ExplainedResult} */ diff --git a/src/js/savegame/savegame_typedefs.js b/src/js/savegame/savegame_typedefs.js index 642865cd..0f94cd6a 100644 --- a/src/js/savegame/savegame_typedefs.js +++ b/src/js/savegame/savegame_typedefs.js @@ -1,33 +1,39 @@ -import { Entity } from "../game/entity"; - -/** - * @typedef {{ - * }} SavegameStats - */ - -/** - * - */ - -/** - * @typedef {{ - * camera: any, - * time: any, - * entityMgr: any, - * map: any, - * hubGoals: any, - * pinnedShapes: any, - * waypoints: any, - * entities: Array, - * beltPaths: Array - * }} SerializedGame - */ - -/** - * @typedef {{ - * version: number, - * dump: SerializedGame, - * stats: SavegameStats, - * lastUpdate: number, - * }} SavegameData - */ +/** + * @typedef {import("../game/entity").Entity} Entity + * + * @typedef {{}} SavegameStats + * + * @typedef {{ + * camera: any, + * time: any, + * entityMgr: any, + * map: any, + * hubGoals: any, + * pinnedShapes: any, + * waypoints: any, + * entities: Array, + * beltPaths: Array + * }} SerializedGame + * + * @typedef {{ + * version: number, + * dump: SerializedGame, + * stats: SavegameStats, + * lastUpdate: number, + * }} SavegameData + * + * @typedef {{ + * lastUpdate: number, + * version: number, + * internalId: string, + * level: number + * name: string|null + * }} SavegameMetadata + * + * @typedef {{ + * version: number, + * savegames: Array + * }} SavegamesData + */ + +export default {}; diff --git a/src/js/savegame/schemas/1001.js b/src/js/savegame/schemas/1001.js index 3af5eebe..af86b09d 100644 --- a/src/js/savegame/schemas/1001.js +++ b/src/js/savegame/schemas/1001.js @@ -1,6 +1,7 @@ import { SavegameInterface_V1000 } from "./1000.js"; import { createLogger } from "../../core/logging.js"; import { T } from "../../translations.js"; +import { TypeVector, TypeNumber, TypeString, TypeNullable } from "../serialization_data_types.js"; const schema = require("./1001.json"); @@ -43,6 +44,25 @@ export class SavegameInterface_V1001 extends SavegameInterface_V1000 { for (let i = 0; i < entities.length; ++i) { const entity = entities[i]; + /** + * @typedef {{ + * origin: TypeVector, + * tileSize: TypeVector, + * rotation: TypeNumber, + * originalRotation: TypeNumber, + * spriteKey?: string, + * blueprintSpriteKey: string, + * silhouetteColor: string + * }} OldStaticMapEntity + */ + + // Here we mock the old type of the StaticMapEntity before the change to using + // a building ID based system (see building_codes.js) to stop the linter from + // complaining that the type doesn't have the properties. + // The ignored error is the error that the types do not overlap. In the case + // of a v1000 save though, the data will match the mocked type above. + /** @type OldStaticMapEntity **/ + // @ts-ignore const staticComp = entity.components.StaticMapEntity; const beltComp = entity.components.Belt; if (staticComp) { diff --git a/src/js/savegame/schemas/1002.js b/src/js/savegame/schemas/1002.js index 92dadfc1..866bc1e8 100644 --- a/src/js/savegame/schemas/1002.js +++ b/src/js/savegame/schemas/1002.js @@ -29,7 +29,9 @@ export class SavegameInterface_V1002 extends SavegameInterface_V1001 { const entity = entities[i]; const beltComp = entity.components.Belt; const ejectorComp = entity.components.ItemEjector; + if (beltComp && ejectorComp) { + // @ts-ignore ejectorComp.instantEject = true; } } diff --git a/src/js/savegame/serialization.js b/src/js/savegame/serialization.js index aea2f944..9f998a0f 100644 --- a/src/js/savegame/serialization.js +++ b/src/js/savegame/serialization.js @@ -1,8 +1,11 @@ +import { createLogger } from "../core/logging"; import { BaseDataType, TypeArray, TypeBoolean, TypeClass, + TypeClassData, + TypeClassFromMetaclass, TypeClassId, TypeEntity, TypeEntityWeakref, @@ -17,12 +20,9 @@ import { TypePositiveInteger, TypePositiveNumber, TypeString, - TypeVector, - TypeClassFromMetaclass, - TypeClassData, TypeStructuredObject, + TypeVector, } from "./serialization_data_types"; -import { createLogger } from "../core/logging"; const logger = createLogger("serialization"); @@ -69,9 +69,10 @@ export const types = { /** * @param {FactoryTemplate<*>} registry + * @param {(GameRoot, any) => object=} resolver */ - obj(registry) { - return new TypeClass(registry); + obj(registry, resolver = null) { + return new TypeClass(registry, resolver); }, /** @@ -190,12 +191,18 @@ export class BasicSerializableObject { ); } - /** @returns {string|void} */ - deserialize(data) { + /** + * @param {any} data + * @param {import("./savegame_serializer").GameRoot} root + * @returns {string|void} + */ + deserialize(data, root = null) { return deserializeSchema( this, /** @type {typeof BasicSerializableObject} */ (this.constructor).getCachedSchema(), - data + data, + null, + root ); } @@ -253,9 +260,10 @@ export function serializeSchema(obj, schema, mergeWith = {}) { * @param {Schema} schema The schema to use * @param {object} data The serialized data * @param {string|void|null=} baseclassErrorResult Convenience, if this is a string error code, do nothing and return it + * @param {import("../game/root").GameRoot=} root Optional game root reference * @returns {string|void} String error code or nothing on success */ -export function deserializeSchema(obj, schema, data, baseclassErrorResult = null) { +export function deserializeSchema(obj, schema, data, baseclassErrorResult = null, root) { if (baseclassErrorResult) { return baseclassErrorResult; } @@ -275,7 +283,7 @@ export function deserializeSchema(obj, schema, data, baseclassErrorResult = null return "Non-nullable entry is null: " + key + " of class " + obj.constructor.name; } - const errorStatus = schema[key].deserializeWithVerify(data[key], obj, key, obj.root); + const errorStatus = schema[key].deserializeWithVerify(data[key], obj, key, obj.root || root); if (errorStatus) { logger.error( "Deserialization failed with error '" + errorStatus + "' on object", diff --git a/src/js/savegame/serialization_data_types.js b/src/js/savegame/serialization_data_types.js index 86b177c1..9fb53bb8 100644 --- a/src/js/savegame/serialization_data_types.js +++ b/src/js/savegame/serialization_data_types.js @@ -4,7 +4,7 @@ import { BasicSerializableObject } from "./serialization"; /* typehints:end */ import { Vector } from "../core/vector"; -import { round4Digits, schemaObject, accessNestedPropertyReverse } from "../core/utils"; +import { round4Digits } from "../core/utils"; export const globalJsonSchemaDefs = {}; /** @@ -28,6 +28,19 @@ export function schemaToJsonSchema(schema) { return jsonSchema; } +/** + * Helper function to create a json schema object + * @param {any} properties + */ +function schemaObject(properties) { + return { + type: "object", + required: Object.keys(properties).slice(), + additionalProperties: false, + properties, + }; +} + /** * Base serialization data type */ @@ -75,23 +88,6 @@ export class BaseDataType { return { $ref: "#/definitions/" + key, }; - - // return this.getAsJsonSchemaUncached(); - // if (!globalJsonSchemaDefs[key]) { - // // schema.$id = key; - // globalJsonSchemaDefs[key] = { - // $id: key, - // definitions: { - // ["d-" + key]: schema - // } - // }; - // } - - // return { - // $ref: key + "#/definitions/d-" + key - // } - - // // return this.getAsJsonSchemaUncached(); } /** @@ -460,7 +456,7 @@ export class TypeEnum extends BaseDataType { */ constructor(enumeration = {}) { super(); - this.availableValues = Object.keys(enumeration); + this.availableValues = Object.values(enumeration); } serialize(value) { @@ -599,10 +595,12 @@ export class TypeClass extends BaseDataType { /** * * @param {FactoryTemplate<*>} registry + * @param {(GameRoot, object) => object} customResolver */ - constructor(registry) { + constructor(registry, customResolver = null) { super(); this.registry = registry; + this.customResolver = customResolver; } serialize(value) { @@ -644,14 +642,23 @@ export class TypeClass extends BaseDataType { * @returns {string|void} String error code or null on success */ deserialize(value, targetObject, targetKey, root) { - const instanceClass = this.registry.findById(value.$); - if (!instanceClass || !instanceClass.prototype) { - return "Invalid class id (runtime-err): " + value.$ + "->" + instanceClass; - } - const instance = Object.create(instanceClass.prototype); - const errorState = instance.deserialize(value.data); - if (errorState) { - return errorState; + let instance; + + if (this.customResolver) { + instance = this.customResolver(root, value); + if (!instance) { + return "Failed to call custom resolver"; + } + } else { + const instanceClass = this.registry.findById(value.$); + if (!instanceClass || !instanceClass.prototype) { + return "Invalid class id (runtime-err): " + value.$ + "->" + instanceClass; + } + instance = Object.create(instanceClass.prototype); + const errorState = instance.deserialize(value.data); + if (errorState) { + return errorState; + } } targetObject[targetKey] = instance; } @@ -875,14 +882,17 @@ export class TypeArray extends BaseDataType { * @returns {string|void} String error code or null on success */ deserialize(value, targetObject, targetKey, root) { - const result = new Array(value.length); + let destination = targetObject[targetKey]; + if (!destination) { + targetObject[targetKey] = destination = new Array(value.length); + } + for (let i = 0; i < value.length; ++i) { - const errorStatus = this.innerType.deserializeWithVerify(value[i], result, i, root); + const errorStatus = this.innerType.deserializeWithVerify(value[i], destination, i, root); if (errorStatus) { return errorStatus; } } - targetObject[targetKey] = result; } getAsJsonSchemaUncached() { @@ -1230,15 +1240,18 @@ export class TypeStructuredObject extends BaseDataType { * @returns {string|void} String error code or null on success */ deserialize(value, targetObject, targetKey, root) { - let result = {}; + let target = targetObject[targetKey]; + if (!target) { + targetObject[targetKey] = target = {}; + } + for (const key in value) { const valueType = this.descriptor[key]; - const errorCode = valueType.deserializeWithVerify(value[key], result, key, root); + const errorCode = valueType.deserializeWithVerify(value[key], target, key, root); if (errorCode) { return errorCode; } } - targetObject[targetKey] = result; } getAsJsonSchemaUncached() { diff --git a/src/js/savegame/serializer_internal.js b/src/js/savegame/serializer_internal.js index 8df6f6e4..6e5dfbc2 100644 --- a/src/js/savegame/serializer_internal.js +++ b/src/js/savegame/serializer_internal.js @@ -1,74 +1,91 @@ -import { gComponentRegistry } from "../core/global_registries"; -import { Entity } from "../game/entity"; -import { enumLayer, GameRoot } from "../game/root"; - -// Internal serializer methods -export class SerializerInternal { - /** - * Serializes an array of entities - * @param {Array} array - */ - serializeEntityArray(array) { - const serialized = []; - for (let i = 0; i < array.length; ++i) { - const entity = array[i]; - if (!entity.queuedForDestroy && !entity.destroyed) { - serialized.push(entity.serialize()); - } - } - return serialized; - } - - /** - * - * @param {GameRoot} root - * @param {Array} array - * @returns {string|void} - */ - deserializeEntityArray(root, array) { - for (let i = 0; i < array.length; ++i) { - this.deserializeEntity(root, array[i]); - } - } - - /** - * - * @param {GameRoot} root - * @param {Entity} payload - */ - deserializeEntity(root, payload) { - const entity = new Entity(root); - this.deserializeComponents(entity, payload.components); - entity.layer = payload.layer; - - if (!enumLayer[payload.layer]) { - assert(false, "Invalid layer: " + payload.layer); - } - - root.entityMgr.registerEntity(entity, payload.uid); - - if (entity.components.StaticMapEntity) { - root.map.placeStaticEntity(entity); - } - } - - /////// COMPONENTS //// - - /** - * Deserializes components of an entity - * @param {Entity} entity - * @param {Object.} data - * @returns {string|void} - */ - deserializeComponents(entity, data) { - for (const componentId in data) { - const componentClass = gComponentRegistry.findById(componentId); - const componentHandle = new componentClass({}); - entity.addComponent(componentHandle); - const errorStatus = componentHandle.deserialize(data[componentId]); - if (errorStatus) { - return errorStatus; - } - } - } -} +import { createLogger } from "../core/logging"; +import { Vector } from "../core/vector"; +import { getBuildingDataFromCode } from "../game/building_codes"; +import { Entity } from "../game/entity"; +import { GameRoot } from "../game/root"; + +const logger = createLogger("serializer_internal"); + +// Internal serializer methods +export class SerializerInternal { + /** + * Serializes an array of entities + * @param {Array} array + */ + serializeEntityArray(array) { + const serialized = []; + for (let i = 0; i < array.length; ++i) { + const entity = array[i]; + if (!entity.queuedForDestroy && !entity.destroyed) { + serialized.push(entity.serialize()); + } + } + return serialized; + } + + /** + * + * @param {GameRoot} root + * @param {Array} array + * @returns {string|void} + */ + deserializeEntityArray(root, array) { + for (let i = 0; i < array.length; ++i) { + this.deserializeEntity(root, array[i]); + } + } + + /** + * + * @param {GameRoot} root + * @param {Entity} payload + */ + deserializeEntity(root, payload) { + const staticData = payload.components.StaticMapEntity; + assert(staticData, "entity has no static data"); + + const code = staticData.code; + const data = getBuildingDataFromCode(code); + + const metaBuilding = data.metaInstance; + + const entity = metaBuilding.createEntity({ + root, + origin: Vector.fromSerializedObject(staticData.origin), + rotation: staticData.rotation, + originalRotation: staticData.originalRotation, + rotationVariant: data.rotationVariant, + variant: data.variant, + }); + + entity.uid = payload.uid; + + this.deserializeComponents(root, entity, payload.components); + + root.entityMgr.registerEntity(entity, payload.uid); + root.map.placeStaticEntity(entity); + } + + /////// COMPONENTS //// + + /** + * Deserializes components of an entity + * @param {GameRoot} root + * @param {Entity} entity + * @param {Object.} data + * @returns {string|void} + */ + deserializeComponents(root, entity, data) { + for (const componentId in data) { + if (!entity.components[componentId]) { + logger.warn("Entity no longer has component:", componentId); + continue; + } + + const errorStatus = entity.components[componentId].deserialize(data[componentId], root); + if (errorStatus) { + return errorStatus; + } + } + } +} diff --git a/src/js/states/about.js b/src/js/states/about.js index 900adc5a..db06d8de 100644 --- a/src/js/states/about.js +++ b/src/js/states/about.js @@ -1,9 +1,7 @@ import { TextualGameState } from "../core/textual_game_state"; -import { SOUNDS } from "../platform/sound"; import { T } from "../translations"; -import { KEYMAPPINGS, getStringForKeyCode } from "../game/key_action_mapper"; -import { Dialog } from "../core/modal_dialog_elements"; import { THIRDPARTY_URLS } from "../core/config"; +import { cachebust } from "../core/cachebust"; export class AboutState extends TextualGameState { constructor() { @@ -15,9 +13,16 @@ export class AboutState extends TextualGameState { } getMainContentHTML() { - return T.about.body - .replace("", THIRDPARTY_URLS.github) - .replace("", THIRDPARTY_URLS.discord); + return ` +
+ shapez.io Logo +
+
+ ${T.about.body + .replace("", THIRDPARTY_URLS.github) + .replace("", THIRDPARTY_URLS.discord)} +
+ `; } onEnter() { diff --git a/src/js/states/ingame.js b/src/js/states/ingame.js index 33d7e15b..3eea38b7 100644 --- a/src/js/states/ingame.js +++ b/src/js/states/ingame.js @@ -381,17 +381,6 @@ export class InGameState extends GameState { } } - // // Check if we can show an ad - // // DISABLED - // if (this.stage === stages.s10_gameRunning && !this.core.root.hud.parts.processingOverlay.hasTasks()) { - // if (this.app.isRenderable() && this.app.adProvider.getCanShowVideoAd()) { - // this.saveThenGoToState("WatchAdState", { - // nextStateId: "RunningGameState", - // nextStatePayload: this.creationPayload, - // }); - // } - // } - if (this.stage === stages.s10_gameRunning) { this.core.tick(dt); } diff --git a/src/js/states/main_menu.js b/src/js/states/main_menu.js index cf7a05ac..bea209a8 100644 --- a/src/js/states/main_menu.js +++ b/src/js/states/main_menu.js @@ -1,530 +1,579 @@ -import { GameState } from "../core/game_state"; -import { cachebust } from "../core/cachebust"; -import { globalConfig, IS_DEBUG, IS_DEMO, THIRDPARTY_URLS } from "../core/config"; -import { - makeDiv, - makeButtonElement, - formatSecondsToTimeAgo, - generateFileDownload, - waitNextFrame, - isSupportedBrowser, - makeButton, - removeAllChildren, -} from "../core/utils"; -import { ReadWriteProxy } from "../core/read_write_proxy"; -import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs"; -import { T } from "../translations"; -import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper"; -import { getApplicationSettingById } from "../profile/application_settings"; -import { EnumSetting } from "../profile/setting_types"; - -export class MainMenuState extends GameState { - constructor() { - super("MainMenuState"); - } - - getInnerHTML() { - const bannerHtml = ` -

${T.demoBanners.title}

- -

${T.demoBanners.intro}

- - Get the shapez.io standalone! - `; - - return ` - -
- - - - ${ - G_IS_STANDALONE || G_IS_DEV - ? ` - - ` - : "" - } -
- - - - - - - -
- -
- ${IS_DEMO ? `
${bannerHtml}
` : ""} -
- -
- ${ - isSupportedBrowser() - ? "" - : `
${T.mainMenu.browserWarning}
` - } -
-
- - -
- - - `; - } - - requestImportSavegame() { - if ( - IS_DEMO && - this.app.savegameMgr.getSavegamesMetaData().length > 0 && - !this.app.platformWrapper.getHasUnlimitedSavegames() - ) { - this.app.analytics.trackUiClick("importgame_slot_limit_show"); - this.dialogs.showWarning(T.dialogs.oneSavegameLimit.title, T.dialogs.oneSavegameLimit.desc); - return; - } - - var input = document.createElement("input"); - input.type = "file"; - input.accept = ".bin"; - - input.onchange = e => { - const file = input.files[0]; - if (file) { - waitNextFrame().then(() => { - this.app.analytics.trackUiClick("import_savegame"); - const closeLoader = this.dialogs.showLoadingDialog(); - const reader = new FileReader(); - reader.addEventListener("load", event => { - // @ts-ignore - const contents = event.target.result; - let realContent; - - try { - realContent = ReadWriteProxy.deserializeObject(contents); - } catch (err) { - closeLoader(); - this.dialogs.showWarning( - T.dialogs.importSavegameError.title, - T.dialogs.importSavegameError.text + "

" + err - ); - return; - } - - this.app.savegameMgr.importSavegame(realContent).then( - () => { - closeLoader(); - this.dialogs.showWarning( - T.dialogs.importSavegameSuccess.title, - T.dialogs.importSavegameSuccess.text - ); - - this.renderMainMenu(); - this.renderSavegames(); - }, - err => { - closeLoader(); - this.dialogs.showWarning( - T.dialogs.importSavegameError.title, - T.dialogs.importSavegameError.text + ":

" + err - ); - } - ); - }); - reader.addEventListener("error", error => { - this.dialogs.showWarning( - T.dialogs.importSavegameError.title, - T.dialogs.importSavegameError.text + ":

" + error - ); - }); - reader.readAsText(file, "utf-8"); - }); - } - }; - input.click(); - } - - onBackButton() { - this.app.platformWrapper.exitApp(); - } - - onEnter(payload) { - this.dialogs = new HUDModalDialogs(null, this.app); - const dialogsElement = document.body.querySelector(".modalDialogParent"); - this.dialogs.initializeToElement(dialogsElement); - - if (payload.loadError) { - this.dialogs.showWarning( - T.dialogs.gameLoadFailure.title, - T.dialogs.gameLoadFailure.text + "

" + payload.loadError - ); - } - - const qs = this.htmlElement.querySelector.bind(this.htmlElement); - - if (G_IS_DEV && globalConfig.debug.fastGameEnter) { - const games = this.app.savegameMgr.getSavegamesMetaData(); - if (games.length > 0 && globalConfig.debug.resumeGameOnFastEnter) { - this.resumeGame(games[0]); - } else { - this.onPlayButtonClicked(); - } - } - - // Initialize video - this.videoElement = this.htmlElement.querySelector("video"); - this.videoElement.playbackRate = 0.9; - this.videoElement.addEventListener("canplay", () => { - if (this.videoElement) { - this.videoElement.classList.add("loaded"); - } - }); - - this.trackClicks(qs(".settingsButton"), this.onSettingsButtonClicked); - this.trackClicks(qs(".changelog"), this.onChangelogClicked); - this.trackClicks(qs(".redditLink"), this.onRedditClicked); - this.trackClicks(qs(".languageChoose"), this.onLanguageChooseClicked); - this.trackClicks(qs(".helpTranslate"), this.onTranslationHelpLinkClicked); - - const contestButton = qs(".participateContest"); - if (contestButton) { - this.trackClicks(contestButton, this.onContestClicked); - } - - if (G_IS_STANDALONE) { - this.trackClicks(qs(".exitAppButton"), this.onExitAppButtonClicked); - } - - this.renderMainMenu(); - this.renderSavegames(); - - const steamLink = this.htmlElement.querySelector(".steamLink"); - if (steamLink) { - this.trackClicks(steamLink, () => this.onSteamLinkClicked(), { preventClick: true }); - } - - const discordLink = this.htmlElement.querySelector(".discordLink"); - this.trackClicks( - discordLink, - () => this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.discord), - { preventClick: true } - ); - - const githubLink = this.htmlElement.querySelector(".githubLink"); - this.trackClicks( - githubLink, - () => this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.github), - { preventClick: true } - ); - - const producerLink = this.htmlElement.querySelector(".producerLink"); - this.trackClicks( - producerLink, - () => this.app.platformWrapper.openExternalLink("https://tobspr.com"), - { preventClick: true } - ); - } - - renderMainMenu() { - const buttonContainer = this.htmlElement.querySelector(".mainContainer .buttons"); - removeAllChildren(buttonContainer); - - // Import button - const importButtonElement = makeButtonElement( - ["importButton", "styledButton"], - T.mainMenu.importSavegame - ); - this.trackClicks(importButtonElement, this.requestImportSavegame); - - if (this.savedGames.length > 0) { - // Continue game - const continueButton = makeButton( - buttonContainer, - ["continueButton", "styledButton"], - T.mainMenu.continue - ); - this.trackClicks(continueButton, this.onContinueButtonClicked); - - const outerDiv = makeDiv(buttonContainer, null, ["outer"], null); - outerDiv.appendChild(importButtonElement); - const newGameButton = makeButton( - this.htmlElement.querySelector(".mainContainer .outer"), - ["newGameButton", "styledButton"], - T.mainMenu.newGame - ); - this.trackClicks(newGameButton, this.onPlayButtonClicked); - } else { - // New game - const playBtn = makeButton(buttonContainer, ["playButton", "styledButton"], T.mainMenu.play); - this.trackClicks(playBtn, this.onPlayButtonClicked); - buttonContainer.appendChild(importButtonElement); - } - } - - onSteamLinkClicked() { - this.app.analytics.trackUiClick("main_menu_steam_link_2"); - this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.standaloneStorePage); - return false; - } - - onExitAppButtonClicked() { - this.app.platformWrapper.exitApp(); - } - - onChangelogClicked() { - this.moveToState("ChangelogState"); - } - - onRedditClicked() { - this.app.analytics.trackUiClick("main_menu_reddit_link"); - this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.reddit); - } - - onContestClicked() { - this.app.analytics.trackUiClick("contest_click"); - - this.dialogs.showInfo( - T.mainMenu.contests.contest_01_03062020.title, - T.mainMenu.contests.contest_01_03062020.longDesc - ); - } - - onLanguageChooseClicked() { - this.app.analytics.trackUiClick("choose_language"); - const setting = /** @type {EnumSetting} */ (getApplicationSettingById("language")); - - const { optionSelected } = this.dialogs.showOptionChooser(T.settings.labels.language.title, { - active: this.app.settings.getLanguage(), - options: setting.options.map(option => ({ - value: setting.valueGetter(option), - text: setting.textGetter(option), - desc: setting.descGetter(option), - iconPrefix: setting.iconPrefix, - })), - }); - - optionSelected.add(value => { - this.app.settings.updateLanguage(value); - if (setting.restartRequired) { - if (this.app.platformWrapper.getSupportsRestart()) { - this.app.platformWrapper.performRestart(); - } else { - this.dialogs.showInfo(T.dialogs.restartRequired.title, T.dialogs.restartRequired.text, [ - "ok:good", - ]); - } - } - - if (setting.changeCb) { - setting.changeCb(this.app, value); - } - - // Update current icon - this.htmlElement.querySelector("button.languageChoose").setAttribute("data-languageIcon", value); - }, this); - } - - get savedGames() { - return this.app.savegameMgr.getSavegamesMetaData(); - } - - renderSavegames() { - const oldContainer = this.htmlElement.querySelector(".mainContainer .savegames"); - if (oldContainer) { - oldContainer.remove(); - } - const games = this.savedGames; - if (games.length > 0) { - const parent = makeDiv(this.htmlElement.querySelector(".mainContainer"), null, ["savegames"]); - - for (let i = 0; i < games.length; ++i) { - const elem = makeDiv(parent, null, ["savegame"]); - - makeDiv( - elem, - null, - ["playtime"], - formatSecondsToTimeAgo((new Date().getTime() - games[i].lastUpdate) / 1000.0) - ); - - makeDiv( - elem, - null, - ["level"], - games[i].level - ? T.mainMenu.savegameLevel.replace("", "" + games[i].level) - : T.mainMenu.savegameLevelUnknown - ); - - const deleteButton = document.createElement("button"); - deleteButton.classList.add("styledButton", "deleteGame"); - elem.appendChild(deleteButton); - - const downloadButton = document.createElement("button"); - downloadButton.classList.add("styledButton", "downloadGame"); - elem.appendChild(downloadButton); - - const resumeButton = document.createElement("button"); - resumeButton.classList.add("styledButton", "resumeGame"); - elem.appendChild(resumeButton); - - this.trackClicks(deleteButton, () => this.deleteGame(games[i])); - this.trackClicks(downloadButton, () => this.downloadGame(games[i])); - this.trackClicks(resumeButton, () => this.resumeGame(games[i])); - } - } - } - - /** - * @param {object} game - */ - resumeGame(game) { - this.app.analytics.trackUiClick("resume_game"); - - this.app.adProvider.showVideoAd().then(() => { - this.app.analytics.trackUiClick("resume_game_adcomplete"); - const savegame = this.app.savegameMgr.getSavegameById(game.internalId); - savegame - .readAsync() - .then(() => { - this.moveToState("InGameState", { - savegame, - }); - }) - .catch(err => { - this.dialogs.showWarning( - T.dialogs.gameLoadFailure.title, - T.dialogs.gameLoadFailure.text + "

" + err - ); - }); - }); - } - - /** - * @param {object} game - */ - deleteGame(game) { - this.app.analytics.trackUiClick("delete_game"); - - const signals = this.dialogs.showWarning( - T.dialogs.confirmSavegameDelete.title, - T.dialogs.confirmSavegameDelete.text, - ["delete:bad", "cancel:good"] - ); - - signals.delete.add(() => { - this.app.savegameMgr.deleteSavegame(game).then( - () => { - this.renderSavegames(); - if (this.savedGames.length <= 0) this.renderMainMenu(); - }, - err => { - this.dialogs.showWarning( - T.dialogs.savegameDeletionError.title, - T.dialogs.savegameDeletionError.text + "

" + err - ); - } - ); - }); - } - - /** - * @param {object} game - */ - downloadGame(game) { - this.app.analytics.trackUiClick("download_game"); - - const savegame = this.app.savegameMgr.getSavegameById(game.internalId); - savegame.readAsync().then(() => { - const data = ReadWriteProxy.serializeObject(savegame.currentData); - generateFileDownload(savegame.filename, data); - }); - } - - onSettingsButtonClicked() { - this.moveToState("SettingsState"); - } - - onTranslationHelpLinkClicked() { - this.app.analytics.trackUiClick("translation_help_link"); - this.app.platformWrapper.openExternalLink( - "https://github.com/tobspr/shapez.io/blob/master/translations" - ); - } - - onPlayButtonClicked() { - if ( - IS_DEMO && - this.app.savegameMgr.getSavegamesMetaData().length > 0 && - !this.app.platformWrapper.getHasUnlimitedSavegames() - ) { - this.app.analytics.trackUiClick("startgame_slot_limit_show"); - this.dialogs.showWarning(T.dialogs.oneSavegameLimit.title, T.dialogs.oneSavegameLimit.desc); - return; - } - - this.app.analytics.trackUiClick("startgame"); - this.app.adProvider.showVideoAd().then(() => { - const savegame = this.app.savegameMgr.createNewSavegame(); - - this.moveToState("InGameState", { - savegame, - }); - this.app.analytics.trackUiClick("startgame_adcomplete"); - }); - } - - onContinueButtonClicked() { - let latestLastUpdate = 0; - let latestInternalId; - this.app.savegameMgr.currentData.savegames.forEach(saveGame => { - if (saveGame.lastUpdate > latestLastUpdate) { - latestLastUpdate = saveGame.lastUpdate; - latestInternalId = saveGame.internalId; - } - }); - - const savegame = this.app.savegameMgr.getSavegameById(latestInternalId); - savegame.readAsync().then(() => { - this.moveToState("InGameState", { - savegame, - }); - }); - } - - onLeave() { - this.dialogs.cleanup(); - } -} +import { GameState } from "../core/game_state"; +import { cachebust } from "../core/cachebust"; +import { globalConfig, IS_DEMO, THIRDPARTY_URLS } from "../core/config"; +import { + makeDiv, + makeButtonElement, + formatSecondsToTimeAgo, + waitNextFrame, + isSupportedBrowser, + makeButton, + removeAllChildren, +} from "../core/utils"; +import { ReadWriteProxy } from "../core/read_write_proxy"; +import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs"; +import { T } from "../translations"; +import { getApplicationSettingById } from "../profile/application_settings"; +import { FormElementInput } from "../core/modal_dialog_forms"; +import { DialogWithForm } from "../core/modal_dialog_elements"; + +/** + * @typedef {import("../savegame/savegame_typedefs").SavegameMetadata} SavegameMetadata + * @typedef {import("../profile/setting_types").EnumSetting} EnumSetting + */ + +/** + * Generates a file download + * @param {string} filename + * @param {string} text + */ +function generateFileDownload(filename, text) { + var element = document.createElement("a"); + element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text)); + element.setAttribute("download", filename); + + element.style.display = "none"; + document.body.appendChild(element); + + element.click(); + document.body.removeChild(element); +} + +export class MainMenuState extends GameState { + constructor() { + super("MainMenuState"); + } + + getInnerHTML() { + const bannerHtml = ` +

${T.demoBanners.title}

+ +

${T.demoBanners.intro}

+ + Get the shapez.io standalone! + `; + + return ` + +
+ + + + ${ + G_IS_STANDALONE || G_IS_DEV + ? ` + + ` + : "" + } +
+ + + + + + + +
+ +
+ ${IS_DEMO ? `
${bannerHtml}
` : ""} +
+ +
+ ${ + isSupportedBrowser() + ? "" + : `
${T.mainMenu.browserWarning}
` + } +
+
+ + +
+ + + `; + } + + requestImportSavegame() { + if ( + IS_DEMO && + this.app.savegameMgr.getSavegamesMetaData().length > 0 && + !this.app.platformWrapper.getHasUnlimitedSavegames() + ) { + this.app.analytics.trackUiClick("importgame_slot_limit_show"); + this.dialogs.showWarning(T.dialogs.oneSavegameLimit.title, T.dialogs.oneSavegameLimit.desc); + return; + } + + var input = document.createElement("input"); + input.type = "file"; + input.accept = ".bin"; + + input.onchange = e => { + const file = input.files[0]; + if (file) { + waitNextFrame().then(() => { + this.app.analytics.trackUiClick("import_savegame"); + const closeLoader = this.dialogs.showLoadingDialog(); + const reader = new FileReader(); + reader.addEventListener("load", event => { + const contents = event.target.result; + let realContent; + + try { + realContent = ReadWriteProxy.deserializeObject(contents); + } catch (err) { + closeLoader(); + this.dialogs.showWarning( + T.dialogs.importSavegameError.title, + T.dialogs.importSavegameError.text + "

" + err + ); + return; + } + + this.app.savegameMgr.importSavegame(realContent).then( + () => { + closeLoader(); + this.dialogs.showWarning( + T.dialogs.importSavegameSuccess.title, + T.dialogs.importSavegameSuccess.text + ); + + this.renderMainMenu(); + this.renderSavegames(); + }, + err => { + closeLoader(); + this.dialogs.showWarning( + T.dialogs.importSavegameError.title, + T.dialogs.importSavegameError.text + ":

" + err + ); + } + ); + }); + reader.addEventListener("error", error => { + this.dialogs.showWarning( + T.dialogs.importSavegameError.title, + T.dialogs.importSavegameError.text + ":

" + error + ); + }); + reader.readAsText(file, "utf-8"); + }); + } + }; + input.click(); + } + + onBackButton() { + this.app.platformWrapper.exitApp(); + } + + onEnter(payload) { + this.dialogs = new HUDModalDialogs(null, this.app); + const dialogsElement = document.body.querySelector(".modalDialogParent"); + this.dialogs.initializeToElement(dialogsElement); + + if (payload.loadError) { + this.dialogs.showWarning( + T.dialogs.gameLoadFailure.title, + T.dialogs.gameLoadFailure.text + "

" + payload.loadError + ); + } + + const qs = this.htmlElement.querySelector.bind(this.htmlElement); + + if (G_IS_DEV && globalConfig.debug.fastGameEnter) { + const games = this.app.savegameMgr.getSavegamesMetaData(); + if (games.length > 0 && globalConfig.debug.resumeGameOnFastEnter) { + this.resumeGame(games[0]); + } else { + this.onPlayButtonClicked(); + } + } + + // Initialize video + this.videoElement = this.htmlElement.querySelector("video"); + this.videoElement.playbackRate = 0.9; + this.videoElement.addEventListener("canplay", () => { + if (this.videoElement) { + this.videoElement.classList.add("loaded"); + } + }); + + this.trackClicks(qs(".settingsButton"), this.onSettingsButtonClicked); + this.trackClicks(qs(".changelog"), this.onChangelogClicked); + this.trackClicks(qs(".redditLink"), this.onRedditClicked); + this.trackClicks(qs(".languageChoose"), this.onLanguageChooseClicked); + this.trackClicks(qs(".helpTranslate"), this.onTranslationHelpLinkClicked); + + if (G_IS_STANDALONE) { + this.trackClicks(qs(".exitAppButton"), this.onExitAppButtonClicked); + } + + this.renderMainMenu(); + this.renderSavegames(); + + const steamLink = this.htmlElement.querySelector(".steamLink"); + if (steamLink) { + this.trackClicks(steamLink, () => this.onSteamLinkClicked(), { preventClick: true }); + } + + const discordLink = this.htmlElement.querySelector(".discordLink"); + this.trackClicks( + discordLink, + () => this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.discord), + { preventClick: true } + ); + + const githubLink = this.htmlElement.querySelector(".githubLink"); + this.trackClicks( + githubLink, + () => this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.github), + { preventClick: true } + ); + + const producerLink = this.htmlElement.querySelector(".producerLink"); + this.trackClicks( + producerLink, + () => this.app.platformWrapper.openExternalLink("https://tobspr.com"), + { preventClick: true } + ); + } + + renderMainMenu() { + const buttonContainer = this.htmlElement.querySelector(".mainContainer .buttons"); + removeAllChildren(buttonContainer); + + // Import button + const importButtonElement = makeButtonElement( + ["importButton", "styledButton"], + T.mainMenu.importSavegame + ); + this.trackClicks(importButtonElement, this.requestImportSavegame); + + if (this.savedGames.length > 0) { + // Continue game + const continueButton = makeButton( + buttonContainer, + ["continueButton", "styledButton"], + T.mainMenu.continue + ); + this.trackClicks(continueButton, this.onContinueButtonClicked); + + const outerDiv = makeDiv(buttonContainer, null, ["outer"], null); + outerDiv.appendChild(importButtonElement); + const newGameButton = makeButton( + this.htmlElement.querySelector(".mainContainer .outer"), + ["newGameButton", "styledButton"], + T.mainMenu.newGame + ); + this.trackClicks(newGameButton, this.onPlayButtonClicked); + } else { + // New game + const playBtn = makeButton(buttonContainer, ["playButton", "styledButton"], T.mainMenu.play); + this.trackClicks(playBtn, this.onPlayButtonClicked); + buttonContainer.appendChild(importButtonElement); + } + } + + onSteamLinkClicked() { + this.app.analytics.trackUiClick("main_menu_steam_link_2"); + this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.standaloneStorePage); + return false; + } + + onExitAppButtonClicked() { + this.app.platformWrapper.exitApp(); + } + + onChangelogClicked() { + this.moveToState("ChangelogState"); + } + + onRedditClicked() { + this.app.analytics.trackUiClick("main_menu_reddit_link"); + this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.reddit); + } + + onLanguageChooseClicked() { + this.app.analytics.trackUiClick("choose_language"); + const setting = /** @type {EnumSetting} */ (getApplicationSettingById("language")); + + const { optionSelected } = this.dialogs.showOptionChooser(T.settings.labels.language.title, { + active: this.app.settings.getLanguage(), + options: setting.options.map(option => ({ + value: setting.valueGetter(option), + text: setting.textGetter(option), + desc: setting.descGetter(option), + iconPrefix: setting.iconPrefix, + })), + }); + + optionSelected.add(value => { + this.app.settings.updateLanguage(value); + if (setting.restartRequired) { + if (this.app.platformWrapper.getSupportsRestart()) { + this.app.platformWrapper.performRestart(); + } else { + this.dialogs.showInfo(T.dialogs.restartRequired.title, T.dialogs.restartRequired.text, [ + "ok:good", + ]); + } + } + + if (setting.changeCb) { + setting.changeCb(this.app, value); + } + + // Update current icon + this.htmlElement.querySelector("button.languageChoose").setAttribute("data-languageIcon", value); + }, this); + } + + get savedGames() { + return this.app.savegameMgr.getSavegamesMetaData(); + } + + renderSavegames() { + const oldContainer = this.htmlElement.querySelector(".mainContainer .savegames"); + if (oldContainer) { + oldContainer.remove(); + } + const games = this.savedGames; + if (games.length > 0) { + const parent = makeDiv(this.htmlElement.querySelector(".mainContainer"), null, ["savegames"]); + + for (let i = 0; i < games.length; ++i) { + const elem = makeDiv(parent, null, ["savegame"]); + + makeDiv( + elem, + null, + ["playtime"], + formatSecondsToTimeAgo((new Date().getTime() - games[i].lastUpdate) / 1000.0) + ); + + makeDiv( + elem, + null, + ["level"], + games[i].level + ? T.mainMenu.savegameLevel.replace("", "" + games[i].level) + : T.mainMenu.savegameLevelUnknown + ); + + const name = makeDiv( + elem, + null, + ["name"], + "" + (games[i].name ? games[i].name : T.mainMenu.savegameUnnamed) + "" + ); + + const deleteButton = document.createElement("button"); + deleteButton.classList.add("styledButton", "deleteGame"); + elem.appendChild(deleteButton); + + const downloadButton = document.createElement("button"); + downloadButton.classList.add("styledButton", "downloadGame"); + elem.appendChild(downloadButton); + + const renameButton = document.createElement("button"); + renameButton.classList.add("styledButton", "renameGame"); + name.appendChild(renameButton); + + const resumeButton = document.createElement("button"); + resumeButton.classList.add("styledButton", "resumeGame"); + elem.appendChild(resumeButton); + + this.trackClicks(deleteButton, () => this.deleteGame(games[i])); + this.trackClicks(downloadButton, () => this.downloadGame(games[i])); + this.trackClicks(resumeButton, () => this.resumeGame(games[i])); + this.trackClicks(renameButton, () => this.requestRenameSavegame(games[i])); + } + } + } + + /** + * @param {SavegameMetadata} game + */ + requestRenameSavegame(game) { + const regex = /^[a-zA-Z0-9_\- ]{1,20}$/; + + const nameInput = new FormElementInput({ + id: "nameInput", + label: null, + placeholder: "", + defaultValue: game.name || "", + validator: val => val.match(regex), + }); + const dialog = new DialogWithForm({ + app: this.app, + title: T.dialogs.renameSavegame.title, + desc: T.dialogs.renameSavegame.desc, + formElements: [nameInput], + buttons: ["cancel:bad:escape", "ok:good:enter"], + }); + this.dialogs.internalShowDialog(dialog); + + // When confirmed, save the name + dialog.buttonSignals.ok.add(() => { + game.name = nameInput.getValue(); + this.app.savegameMgr.writeAsync(); + this.renderSavegames(); + }); + } + + /** + * @param {SavegameMetadata} game + */ + resumeGame(game) { + this.app.analytics.trackUiClick("resume_game"); + + this.app.adProvider.showVideoAd().then(() => { + this.app.analytics.trackUiClick("resume_game_adcomplete"); + const savegame = this.app.savegameMgr.getSavegameById(game.internalId); + savegame + .readAsync() + .then(() => { + this.moveToState("InGameState", { + savegame, + }); + }) + .catch(err => { + this.dialogs.showWarning( + T.dialogs.gameLoadFailure.title, + T.dialogs.gameLoadFailure.text + "

" + err + ); + }); + }); + } + + /** + * @param {SavegameMetadata} game + */ + deleteGame(game) { + this.app.analytics.trackUiClick("delete_game"); + + const signals = this.dialogs.showWarning( + T.dialogs.confirmSavegameDelete.title, + T.dialogs.confirmSavegameDelete.text, + ["delete:bad", "cancel:good"] + ); + + signals.delete.add(() => { + this.app.savegameMgr.deleteSavegame(game).then( + () => { + this.renderSavegames(); + if (this.savedGames.length <= 0) this.renderMainMenu(); + }, + err => { + this.dialogs.showWarning( + T.dialogs.savegameDeletionError.title, + T.dialogs.savegameDeletionError.text + "

" + err + ); + } + ); + }); + } + + /** + * @param {SavegameMetadata} game + */ + downloadGame(game) { + this.app.analytics.trackUiClick("download_game"); + + const savegame = this.app.savegameMgr.getSavegameById(game.internalId); + savegame.readAsync().then(() => { + const data = ReadWriteProxy.serializeObject(savegame.currentData); + const filename = (game.name || "unnamed") + ".bin"; + generateFileDownload(filename, data); + }); + } + + onSettingsButtonClicked() { + this.moveToState("SettingsState"); + } + + onTranslationHelpLinkClicked() { + this.app.analytics.trackUiClick("translation_help_link"); + this.app.platformWrapper.openExternalLink( + "https://github.com/tobspr/shapez.io/blob/master/translations" + ); + } + + onPlayButtonClicked() { + if ( + IS_DEMO && + this.app.savegameMgr.getSavegamesMetaData().length > 0 && + !this.app.platformWrapper.getHasUnlimitedSavegames() + ) { + this.app.analytics.trackUiClick("startgame_slot_limit_show"); + this.dialogs.showWarning(T.dialogs.oneSavegameLimit.title, T.dialogs.oneSavegameLimit.desc); + return; + } + + this.app.analytics.trackUiClick("startgame"); + this.app.adProvider.showVideoAd().then(() => { + const savegame = this.app.savegameMgr.createNewSavegame(); + + this.moveToState("InGameState", { + savegame, + }); + this.app.analytics.trackUiClick("startgame_adcomplete"); + }); + } + + onContinueButtonClicked() { + let latestLastUpdate = 0; + let latestInternalId; + this.app.savegameMgr.currentData.savegames.forEach(saveGame => { + if (saveGame.lastUpdate > latestLastUpdate) { + latestLastUpdate = saveGame.lastUpdate; + latestInternalId = saveGame.internalId; + } + }); + + const savegame = this.app.savegameMgr.getSavegameById(latestInternalId); + savegame.readAsync().then(() => { + this.moveToState("InGameState", { + savegame, + }); + }); + } + + onLeave() { + this.dialogs.cleanup(); + } +} diff --git a/src/js/states/mobile_warning.js b/src/js/states/mobile_warning.js index de17578a..a48a69ed 100644 --- a/src/js/states/mobile_warning.js +++ b/src/js/states/mobile_warning.js @@ -17,7 +17,7 @@ export class MobileWarningState extends GameState { There is also no estimate when this will change, but feel to make a contribution! It's  open source!

-

If you want to play on your computer, you can also get the standalone on steam:

+

If you want to play on your computer, you can also get the standalone on Steam:

.desc"); + /** @type {HTMLElement} */ this.statusBar = this.htmlElement.querySelector(".loadingStatus > .bar > .inner"); + /** @type {HTMLElement} */ this.statusBarText = this.htmlElement.querySelector(".loadingStatus > .bar > .status"); + this.currentStatus = "booting"; this.currentIndex = 0; @@ -224,11 +228,7 @@ export class PreloadState extends GameState { this.statusBar.style.width = percentage + "%"; this.statusBarText.innerText = findNiceValue(percentage) + "%"; - if (G_IS_DEV) { - return Promise.resolve(); - } return Promise.resolve(); - // return waitNextFrame(); } showFailMessage(text) { @@ -251,12 +251,12 @@ export class PreloadState extends GameState { ${this.currentStatus} failed:
${text}
- + - +
Build ${G_BUILD_VERSION} @ ${G_BUILD_COMMIT_HASH} @@ -275,11 +275,6 @@ export class PreloadState extends GameState { if (confirm("Are you sure you want to reset the app? This will delete all your savegames")) { this.resetApp(); } - // const signals = this.dialogs.showWarning(T.preload.reset_app_warning.title, T.preload.reset_app_warning.desc, [ - // "delete:bad:timeout", - // "cancel:good", - // ]); - // signals.delete.add(this.resetApp, this); } resetApp() { diff --git a/src/js/states/settings.js b/src/js/states/settings.js index 4dce1fa3..5e22492a 100644 --- a/src/js/states/settings.js +++ b/src/js/states/settings.js @@ -1,6 +1,6 @@ import { TextualGameState } from "../core/textual_game_state"; import { formatSecondsToTimeAgo } from "../core/utils"; -import { allApplicationSettings } from "../profile/application_settings"; +import { allApplicationSettings, enumCategories } from "../profile/application_settings"; import { T } from "../translations"; export class SettingsState extends TextualGameState { @@ -15,50 +15,65 @@ export class SettingsState extends TextualGameState { getMainContentHTML() { return ` - ") + .join(""); } renderBuildText() { @@ -90,10 +105,33 @@ export class SettingsState extends TextualGameState { } this.initSettings(); + this.initCategoryButtons(); + + this.htmlElement.querySelector(".category").classList.add("active"); + this.htmlElement.querySelector(".categoryButton").classList.add("active"); + } + + setActiveCategory(category) { + const previousCategory = this.htmlElement.querySelector(".category.active"); + const previousCategoryButton = this.htmlElement.querySelector(".categoryButton.active"); + + if (previousCategory.getAttribute("data-category") == category) { + return; + } + + previousCategory.classList.remove("active"); + previousCategoryButton.classList.remove("active"); + + const newCategory = this.htmlElement.querySelector("[data-category='" + category + "']"); + const newCategoryButton = this.htmlElement.querySelector("[data-category-btn='" + category + "']"); + + newCategory.classList.add("active"); + newCategoryButton.classList.add("active"); } initSettings() { allApplicationSettings.forEach(setting => { + /** @type {HTMLElement} */ const element = this.htmlElement.querySelector("[data-setting='" + setting.id + "']"); setting.bind(this.app, element, this.dialogs); setting.syncValueToElement(); @@ -107,6 +145,20 @@ export class SettingsState extends TextualGameState { }); } + initCategoryButtons() { + Object.keys(enumCategories).forEach(key => { + const category = enumCategories[key]; + const button = this.htmlElement.querySelector("[data-category-btn='" + category + "']"); + this.trackClicks( + button, + () => { + this.setActiveCategory(category); + }, + { preventDefault: false } + ); + }); + } + onAboutClicked() { this.moveToStateAddGoBack("AboutState"); } diff --git a/src/js/tsconfig.json b/src/js/tsconfig.json index 5184bc42..8a151000 100644 --- a/src/js/tsconfig.json +++ b/src/js/tsconfig.json @@ -3,7 +3,7 @@ /* Basic Options */ "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, - // "lib": [], /* Specify library files to be included in the compilation. */ + "lib": ["DOM","ES2018"], /* Specify library files to be included in the compilation. */ "allowJs": true /* Allow javascript files to be compiled. */, "checkJs": true /* Report errors in .js files. */, // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ @@ -54,5 +54,6 @@ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ "resolveJsonModule": true - } + }, + "exclude": ["webworkers"] } diff --git a/src/js/webworkers/background_animation_frame_emittter.worker.js b/src/js/webworkers/background_animation_frame_emittter.worker.js index c927b2d3..3941e0dd 100644 --- a/src/js/webworkers/background_animation_frame_emittter.worker.js +++ b/src/js/webworkers/background_animation_frame_emittter.worker.js @@ -1,16 +1,16 @@ // We clamp high deltas so 30 fps is fairly ok -var bgFps = 30; -var desiredMsDelay = 1000 / bgFps; +const bgFps = 30; +const desiredMsDelay = 1000 / bgFps; -let lastTick = 0; +let lastTick = performance.now(); function tick() { - var now = performance.now(); - var delta = now - lastTick; + const now = performance.now(); + const delta = now - lastTick; lastTick = now; // @ts-ignore - postMessage({ delta }); + self.postMessage({ delta }); } setInterval(tick, desiredMsDelay); diff --git a/src/js/webworkers/compression.worker.js b/src/js/webworkers/compression.worker.js index 0bcb0ea6..1e567c05 100644 --- a/src/js/webworkers/compression.worker.js +++ b/src/js/webworkers/compression.worker.js @@ -1,6 +1,7 @@ -import { compressX64 } from "../core/lzstring"; import { globalConfig } from "../core/config"; -import { sha1 } from "../core/sensitive_utils.encrypt"; +import { compressX64 } from "../core/lzstring"; +import { computeCrc } from "../core/sensitive_utils.encrypt"; +import { compressObject } from "../savegame/savegame_compressor"; function accessNestedPropertyReverse(obj, keys) { let result = obj; @@ -12,25 +13,27 @@ function accessNestedPropertyReverse(obj, keys) { const salt = accessNestedPropertyReverse(globalConfig, ["file", "info"]); -onmessage = function (event) { +self.addEventListener("message", event => { + // @ts-ignore const { jobId, job, data } = event.data; const result = performJob(job, data); // @ts-ignore - postMessage({ - jobId, - result, - }); -}; + self.postMessage({ jobId, result }); +}); function performJob(job, data) { switch (job) { case "compressX64": { return compressX64(data); } - case "compressFile": { - const checksum = sha1(data.text + salt); - return data.compressionPrefix + compressX64(checksum + data.text); + + case "compressObject": { + const optimized = compressObject(data.obj); + const stringified = JSON.stringify(optimized); + + const checksum = computeCrc(stringified + salt); + return data.compressionPrefix + compressX64(checksum + stringified); } default: throw new Error("Webworker: Unknown job: " + job); diff --git a/src/js/webworkers/tsconfig.json b/src/js/webworkers/tsconfig.json new file mode 100644 index 00000000..dce06856 --- /dev/null +++ b/src/js/webworkers/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "lib": ["ES2018","WebWorker"] + }, + "exclude": [], + "extends": "../tsconfig", + "include": ["*.worker.js"] +} diff --git a/translations/README.md b/translations/README.md index 48400a48..7695f022 100644 --- a/translations/README.md +++ b/translations/README.md @@ -31,6 +31,8 @@ The base language is English and can be found [here](base-en.yaml). - [Catalan](base-cat.yaml) - [Slovenian](base-sl.yaml) - [Ukrainian](base-uk.yaml) +- [Indonesian](base-ind.yaml) +- [Serbian](base-sr.yaml) (If you want to translate into a new language, see below!) @@ -57,7 +59,7 @@ If you want to edit an existing translation (Fixing typos, Updating it to a newe ## Adding a new language -Please DM me on discord (tobspr#5407), so I can add the language template for you. +Please DM me on Discord (tobspr#5407), so I can add the language template for you. Please use the following template: diff --git a/translations/base-ar.yaml b/translations/base-ar.yaml index 0d31ee22..17d822d9 100644 --- a/translations/base-ar.yaml +++ b/translations/base-ar.yaml @@ -15,13 +15,17 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page - shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. + shortText: shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. + + # This is the text shown above the Discord link + discordLink: Official Discord - Chat with me! # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: @@ -31,15 +35,16 @@ steamPage: [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Upon delivering the requested shapes you'll progress within the game and unlock upgrades to speed up your factory. - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + As the demand for shapes increases, you'll have to scale up your factory to meet the demand - Don't forget about resources though, you'll have to expand across the [b]infinite map[/b]! - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Soon you'll have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with them to satisfy the demand. - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + This game features 18 progressive levels (Which should already keep you busy for hours!) but I'm constantly adding new content - There's a lot planned! + + Purchasing the game gives you access to the standalone version which has additional features, and you'll also receive access to newly developed features. [b]Standalone Advantages[/b] @@ -55,7 +60,7 @@ steamPage: [b]Future Updates[/b] - I am updating the game very often and trying to push an update at least every week! + I am updating the game often and trying to push an update at least once every week! [list] [*] Different maps and challenges (e.g. maps with obstacles) @@ -82,8 +87,6 @@ steamPage: [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] [/list] - discordLink: Official Discord - Chat with me! - global: loading: Loading error: Error @@ -91,6 +94,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -135,11 +141,15 @@ demoBanners: mainMenu: play: Play + continue: Continue + newGame: New Game changelog: Changelog + subreddit: Reddit importSavegame: Import openSourceHint: This game is open source! discordLink: Official Discord Server helpTranslate: Help translate! + madeBy: Made by # This is shown when using firefox and other browsers which are not supported. browserWarning: >- @@ -148,12 +158,6 @@ mainMenu: savegameLevel: Level savegameLevelUnknown: Unknown Level - - continue: Continue - newGame: New Game - madeBy: Made by - subreddit: Reddit - dialogs: buttons: ok: OK @@ -163,7 +167,7 @@ dialogs: restart: Restart reset: Reset getStandalone: Get Standalone - deleteGame: I know what I do + deleteGame: I know what I am doing viewUpdate: View Update showUpgrades: Show Upgrades showKeybindings: Show Keybindings @@ -212,11 +216,11 @@ dialogs: featureRestriction: title: Demo Version - desc: You tried to access a feature () which is not available in the demo. Consider to get the standalone for the full experience! + desc: You tried to access a feature () which is not available in the demo. Consider getting the standalone version for the full experience! oneSavegameLimit: title: Limited savegames - desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone! + desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone version! updateSummary: title: New update! @@ -234,6 +238,16 @@ dialogs: desc: >- You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? + massCutConfirm: + title: Confirm cut + desc: >- + You are cutting a lot of buildings ( to be exact)! Are you sure you want to do this? + + massCutInsufficientConfirm: + title: Confirm cut + desc: >- + You can not afford to paste this area! Are you sure you want to cut it? + blueprintsNotUnlocked: title: Not unlocked yet desc: >- @@ -250,26 +264,15 @@ dialogs: createMarker: title: New Marker - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) titleEdit: Edit Marker + desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) markerDemoLimit: desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! - massCutConfirm: - title: Confirm cut - desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you - want to do this? exportScreenshotWarning: title: Export screenshot - desc: >- - You requested to export your base as a screenshot. Please note that this can - be quite slow for a big base and even crash your game! - - massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + desc: You requested to export your base as a screenshot. Please note that this can be quite slow for a big base and even crash your game! ingame: # This is shown in the top left corner and displays useful keybindings in @@ -281,20 +284,32 @@ ingame: rotateBuilding: Rotate building placeMultiple: Place multiple reverseOrientation: Reverse orientation - disableAutoOrientation: Disable auto orientation + disableAutoOrientation: Disable auto-orientation toggleHud: Toggle HUD placeBuilding: Place building - createMarker: Create Marker - delete: Destroy + createMarker: Create marker + delete: Delete pasteLastBlueprint: Paste last blueprint lockBeltDirection: Enable belt planner plannerSwitchSide: Flip planner side cutSelection: Cut copySelection: Copy - clearSelection: Clear Selection + clearSelection: Clear selection pipette: Pipette switchLayers: Switch layers + # Names of the colors, used for the color blind mode + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + black: Black + uncolored: Gray + # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) buildingPlacement: @@ -389,6 +404,12 @@ ingame: description: Left-click a marker to jump to it, right-click to delete it.

Press to create a marker from the current view, or right-click to create a marker at the selected location. creationSuccessNotification: Marker has been created. + # Shape viewer + shapeViewer: + title: Layers + empty: Empty + copyKey: Copy Key + # Interactive tutorial interactiveTutorial: title: Tutorial @@ -400,21 +421,6 @@ ingame: 1_3_expand: >- This is NOT an idle game! Build more extractors and belts to finish the goal quicker.

Tip: Hold SHIFT to place multiple extractors, and use R to rotate them. - colors: - red: Red - green: Green - blue: Blue - yellow: Yellow - purple: Purple - cyan: Cyan - white: White - uncolored: No color - black: Black - shapeViewer: - title: Layers - empty: Empty - copyKey: Copy Key - # All shop upgrades shopUpgrades: belt: @@ -442,7 +448,13 @@ buildings: name: &belt Conveyor Belt description: Transports items, hold and drag to place multiple. - miner: # Internal name for the Extractor + wire: + default: + name: &wire Energy Wire + description: Allows you to transport energy. + + # Internal name for the Extractor + miner: default: name: &miner Extractor description: Place over a shape or color to extract it. @@ -451,16 +463,18 @@ buildings: name: Extractor (Chain) description: Place over a shape or color to extract it. Can be chained. - underground_belt: # Internal name for the Tunnel + # Internal name for the Tunnel + underground_belt: default: name: &underground_belt Tunnel - description: Allows to tunnel resources under buildings and belts. + description: Allows you to tunnel resources under buildings and belts. tier2: name: Tunnel Tier II - description: Allows to tunnel resources under buildings and belts. + description: Allows you to tunnel resources under buildings and belts. - splitter: # Internal name for the Balancer + # Internal name for the Balancer + splitter: default: name: &splitter Balancer description: Multifunctional - Evenly distributes all inputs onto all outputs. @@ -476,18 +490,26 @@ buildings: cutter: default: name: &cutter Cutter - description: Cuts shapes from top to bottom and outputs both halfs. If you use only one part, be sure to destroy the other part or it will stall! + description: Cuts shapes from top to bottom and outputs both halves. If you use only one part, be sure to destroy the other part or it will stall! quad: name: Cutter (Quad) description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other parts or it will stall! + advanced_processor: + default: + name: &advanced_processor Color Inverter + description: Accepts a color or shape and inverts it. + rotater: default: name: &rotater Rotate description: Rotates shapes clockwise by 90 degrees. ccw: name: Rotate (CCW) - description: Rotates shapes counter clockwise by 90 degrees. + description: Rotates shapes counter-clockwise by 90 degrees. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -503,15 +525,17 @@ buildings: default: name: &painter Painter description: &painter_desc Colors the whole shape on the left input with the color from the top input. + + mirrored: + name: *painter + description: *painter_desc + double: name: Painter (Double) description: Colors the shapes on the left inputs with the color from the top input. quad: name: Painter (Quad) - description: Allows to color each quadrant of the shape with a different color. - mirrored: - name: *painter - description: *painter_desc + description: Allows you to color each quadrant of the shape with a different color. trash: default: @@ -521,24 +545,22 @@ buildings: storage: name: Storage description: Stores excess items, up to a given capacity. Can be used as an overflow gate. - wire: - default: - name: Energy Wire - description: Allows you to transport energy. - advanced_processor: - default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + energy_generator: deliver: Deliver + + # This will be shown before the amount, so for example 'For 123 Energy' toGenerateEnergy: For + default: - name: Energy Generator + name: &energy_generator Energy Generator description: Generates energy by consuming shapes. + wire_crossings: default: - name: Wire Splitter + name: &wire_crossings Wire Splitter description: Splits a energy wire into two. + merger: name: Wire Merger description: Merges two energy wires into one. @@ -556,7 +578,7 @@ storyRewards: reward_painter: title: Painting desc: >- - The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, there is a color blind mode in the settings! + The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, there is a colorblind mode in the settings! reward_mixer: title: Color Mixing @@ -576,7 +598,7 @@ storyRewards: reward_rotater_ccw: title: CCW Rotating - desc: You have unlocked a variant of the rotater - It allows to rotate counter clockwise! To build it, select the rotater and press 'T' to cycle its variants! + desc: You have unlocked a variant of the rotater - It allows you to rotate shapes counter-clockwise! To build it, select the rotater and press 'T' to cycle through its variants! reward_miner_chainable: title: Chaining Extractor @@ -589,7 +611,7 @@ storyRewards: reward_splitter_compact: title: Compact Balancer desc: >- - You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one! + You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one belt! reward_cutter_quad: title: Quad Cutting @@ -601,11 +623,11 @@ storyRewards: reward_painter_quad: title: Quad Painting - desc: You have unlocked a variant of the painter - It allows to paint each part of the shape individually! + desc: You have unlocked a variant of the painter - It allows you to paint each part of the shape individually! reward_storage: title: Storage Buffer - desc: You have unlocked a variant of the trash - It allows to store items up to a given capacity! + desc: You have unlocked a variant of the trash - It allows you to store items up to a given capacity! reward_freeplay: title: Freeplay @@ -629,8 +651,9 @@ storyRewards: settings: title: Settings categories: - game: Game - app: Application + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: Development @@ -642,7 +665,7 @@ settings: uiScale: title: Interface scale description: >- - Changes the size of the user interface. The interface will still scale based on your device resolution, but this setting controls the amount of scale. + Changes the size of the user interface. The interface will still scale based on your device's resolution, but this setting controls the amount of scaling. scales: super_small: Super small small: Small @@ -650,6 +673,19 @@ settings: large: Large huge: Huge + autosaveInterval: + title: Autosave Interval + description: >- + Controls how often the game saves automatically. You can also disable it entirely here. + + intervals: + one_minute: 1 Minute + two_minutes: 2 Minutes + five_minutes: 5 Minutes + ten_minutes: 10 Minutes + twenty_minutes: 20 Minutes + disabled: Disabled + scrollWheelSensitivity: title: Zoom sensitivity description: >- @@ -661,10 +697,27 @@ settings: fast: Fast super_fast: Super fast + movementSpeed: + title: Movement speed + description: >- + Changes how fast the view moves when using the keyboard. + speeds: + super_slow: Super slow + slow: Slow + regular: Regular + fast: Fast + super_fast: Super Fast + extremely_fast: Extremely Fast + language: title: Language description: >- - Change the language. All translations are user contributed and might be incomplete! + Change the language. All translations are user-contributed and might be incomplete! + + enableColorBlindHelper: + title: Color Blind Mode + description: >- + Enables various tools which allow you to play the game if you are color blind. fullscreen: title: Fullscreen @@ -702,63 +755,32 @@ settings: offerHints: title: Hints & Tutorials description: >- - Whether to offer hints and tutorials while playing. Also hides certain UI elements onto a given level to make it easier to get into the game. + Whether to offer hints and tutorials while playing. Also hides certain UI elements up to a given level to make it easier to get into the game. - movementSpeed: - title: Movement speed - description: Changes how fast the view moves when using the keyboard. - speeds: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super Fast - extremely_fast: Extremely Fast enableTunnelSmartplace: title: Smart Tunnels description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. - This also enables to drag tunnels and excess tunnels will get removed. + When enabled, placing tunnels will automatically remove unnecessary belts. This also enables you to drag tunnels and excess tunnels will get removed. + vignette: title: Vignette description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. + Enables the vignette, which darkens the screen corners and makes text easier to read. - autosaveInterval: - title: Autosave Interval + rotationByBuilding: + title: Rotation by building type description: >- - Controls how often the game saves automatically. You can also disable it - entirely here. - intervals: - one_minute: 1 Minute - two_minutes: 2 Minutes - five_minutes: 5 Minutes - ten_minutes: 10 Minutes - twenty_minutes: 20 Minutes - disabled: Disabled + Each building type remembers the rotation you last set it to individually. This may be more comfortable if you frequently switch between placing different building types. compactBuildingInfo: title: Compact Building Infos description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a - description and image is shown. + Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. disableCutDeleteWarnings: title: Disable Cut/Delete Warnings description: >- - Disable the warning dialogs brought up when cutting/deleting more than 100 - entities. - - enableColorBlindHelper: - title: Color Blind Mode - description: Enables various tools which allow to play the game if you are color blind. - rotationByBuilding: - title: Rotation by building type - description: >- - Each building type remembers the rotation you last set it to individually. - This may be more comfortable if you frequently switch between placing - different building types. + Disables the warning dialogs brought up when cutting/deleting more than 100 entities. keybindings: title: Keybindings @@ -783,6 +805,7 @@ keybindings: mapMoveRight: Move Right mapMoveDown: Move Down mapMoveLeft: Move Left + mapMoveFaster: Move Faster centerMap: Center Map mapZoomIn: Zoom in @@ -791,66 +814,59 @@ keybindings: menuOpenShop: Upgrades menuOpenStats: Statistics + menuClose: Close Menu toggleHud: Toggle HUD toggleFPSInfo: Toggle FPS and Debug Info + switchLayers: Switch layers + exportScreenshot: Export whole Base as Image belt: *belt splitter: *splitter underground_belt: *underground_belt miner: *miner cutter: *cutter + advanced_processor: *advanced_processor rotater: *rotater stacker: *stacker mixer: *mixer + energy_generator: *energy_generator painter: *painter trash: *trash + wire: *wire + pipette: Pipette rotateWhilePlacing: Rotate rotateInverseModifier: >- Modifier: Rotate CCW instead cycleBuildingVariants: Cycle Variants - confirmMassDelete: Confirm Mass Delete + confirmMassDelete: Delete area + pasteLastBlueprint: Paste last blueprint cycleBuildings: Cycle Buildings + lockBeltDirection: Enable belt planner + switchDirectionLockSide: >- + Planner: Switch side massSelectStart: Hold and drag to start massSelectSelectMultiple: Select multiple areas massSelectCopy: Copy area + massSelectCut: Cut area placementDisableAutoOrientation: Disable automatic orientation placeMultiple: Stay in placement mode placeInverse: Invert automatic belt orientation - pasteLastBlueprint: Paste last blueprint - massSelectCut: Cut area - exportScreenshot: Export whole Base as Image - mapMoveFaster: Move Faster - lockBeltDirection: Enable belt planner - switchDirectionLockSide: "Planner: Switch side" - pipette: Pipette - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire about: title: About this Game body: >- - This game is open source and developed by Tobias Springer (this is me).

+ This game is open source and developed by Tobias Springer (this is me).

- If you want to contribute, check out shapez.io on github.

+ If you want to contribute, check out shapez.io on GitHub.

- This game wouldn't have been possible without the great discord community - around my games - You should really join the discord server!

+ This game wouldn't have been possible without the great Discord community around my games - You should really join the Discord server!

- The soundtrack was made by Peppsen - He's awesome.

+ The soundtrack was made by Peppsen - He's awesome.

- Finally, huge thanks to my best friend Niklas - Without our - factorio sessions this game would never have existed. + Finally, huge thanks to my best friend Niklas - Without our Factorio sessions, this game would never have existed. changelog: title: Changelog diff --git a/translations/base-cat.yaml b/translations/base-cat.yaml index da1e9085..b1870d77 100644 --- a/translations/base-cat.yaml +++ b/translations/base-cat.yaml @@ -15,14 +15,18 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io és un joc que té com a objectiu construir i automatitzar fàbriques per tal de produir figures cada cop més complexes en un mapa infinit. + # This is the text shown above the Discord link + discordLink: Discord Oficial (en Anglès) + # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: # - Do not translate the first line (This is the gif image at the start of the store) @@ -30,49 +34,50 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.io és un joc que té com a objectiu construir i automatitzar fàbriques per tal de produir figures cada cop més complexes en un mapa infinit. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Al lliurar les formes geomètriques sol·licitades, progressaràs i desbloquejaràs millores per accelerar la teva fàbrica. - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Com que la demanda de figures va augmentant, hauràs de augmentar proporcionalment la teva fàbrica per satisfer la demanda. Però no t'oblidis dels recursos, ja que t'hauràs d'expandre a través del [b]mapa infinit[/b]! - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Sovint, hauràs de començar a mesclar color i pintar les figures amb aquests; combina roig, verd i blau per produïr diferents colors i pintar les figures amb aquests per satisfer la demanda. - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + Aquest joc presenta 18 nivells progressius (Els quals ja haurien de mantenir-te ocupat durant hores!) però estic constantment afegint nou contingut. Tenim moltes coses planejades! - [b]Standalone Advantages[/b] + La compra del joc et dona accés a versió independent amb característiques adicionals, i també rebràs accés a les noves característiques que es desenvolupin. + + [b]Ventatges de la Versió Independent[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Mode Oscur + [*] Punts d'interès il·limitats + [*] Guardar partides il·limitades + [*] Configuracions Adicionals + [*] Pròximament: Cables i Energia! Objectiu (aproximadament) per finals de Juliol del 2020. + [*] Pròximament: Més Nivells + [*] Em permet seguir desenvolupant shapez.io ❤️ [/list] - [b]Future Updates[/b] + [b]Futures Actualitzacions[/b] - I am updating the game very often and trying to push an update at least every week! + Actualitzo el joc sovint i intent treure una actualització nova per setmana! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Mapes i reptes diferents (p.e. mapes amb obstacles) + [*] Trencaclosques (Entrega la figura amb una àrea/conjunt d'edificis delimitats) + [*] Un "Mode Història" on els edificis tenen un cost + [*] Generador de mapes configurable (Configura el tamany/densitat de les formes/recursos, llavors i més) + [*] Formes geomètriques adicionals + [*] Millores de rendiment (El joc ja funciona força bé!) + [*] Moltes coses més! [/list] - [b]This game is open source![/b] + [b]Aquest joc és de codi obert![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Qualsevol pot contribuir, estic involucrat activament en la comunitat i intento revisar tots els suggeriments i tenir en compte els comentaris sempre que sigui possible. + Assegureu-vos de consultar el meu tauler de trello per obtenir el full de ruta complet! - [b]Links[/b] + [b]Enllaços[/b] [list] [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] @@ -82,8 +87,6 @@ steamPage: [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] [/list] - discordLink: Official Discord - Chat with me! - global: loading: Carregant error: Error @@ -91,6 +94,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -151,8 +157,6 @@ mainMenu: savegameLevel: Nivell savegameLevelUnknown: Nivell desconegut - - dialogs: buttons: ok: OK @@ -170,7 +174,7 @@ dialogs: importSavegameError: title: Error en importar text: >- - Failed to import your savegame: + Ha ocurrit un error intentant importar la teva partida: importSavegameSuccess: title: Importar @@ -180,7 +184,7 @@ dialogs: gameLoadFailure: title: No es pot carregar la partida guardada text: >- - Failed to load your savegame: + Ha ocurrit un error al intentar carregar la teva partida: confirmSavegameDelete: title: Eliminar @@ -190,7 +194,7 @@ dialogs: savegameDeletionError: title: Error en eliminar text: >- - Failed to delete the savegame: + Ha ocurrit un error al intentar eliminar la teva partida: restartRequired: title: Reiniciar @@ -236,7 +240,12 @@ dialogs: massCutConfirm: title: Tallar edificis desc: >- - Estàs esborrant molts edificis de cop ( per ser exactes)! Estàs segur que vols seguir? + Estàs tallant molts edificis de cop ( per ser exactes)! Estàs segur que vols seguir? + + massCutInsufficientConfirm: + title: Confirmar tallar + desc: >- + No pots aferrar a aquesta zona! Estàs segur de que vols tallarla? blueprintsNotUnlocked: title: Encara no s'ha desbloquejat @@ -262,11 +271,8 @@ dialogs: desc: En la Demo només pots crear dos marcadors, aconsegueix la versió completa per gaudir de l'experiència completa! exportScreenshotWarning: - title: Export screenshot + title: Exportar Captura de Pantalla desc: Has demanat exportar la teva/teua base com una captura de pantalla. Tin en conte que aquest procés pot ser molt lent i inclús crashear el teu joc! - massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -301,19 +307,20 @@ ingame: purple: Morat cyan: Cian white: Blanc + black: Negre uncolored: Sense color - black: Black # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) buildingPlacement: # Buildings can have different variants which are unlocked at later levels, # and this is the hint shown when there are multiple variants available. - cycleBuildingVariants: Pulsa per a ciclar entre variants. + cycleBuildingVariants: Prem per a ciclar entre variants. # Shows the hotkey in the ui, e.g. "Hotkey: Q" hotkeyLabel: >- Hotkey: + infoTexts: speed: Velocitat range: Distància @@ -410,8 +417,10 @@ ingame: 1_1_extractor: Col·loca un extractor damunt d'una figura circular per extraure-la! 1_2_conveyor: >- Connecta l'extractor a la cinta transportadora cap al teu nexe!

Pista: Pots clicar i arrossegar la cinta transportadora amb el teu ratolí! + 1_3_expand: >- Aquest NO és un joc d'espera! Contrueix més extractors i cintes per a completar l'objectiu més ràpidament.

Pista: Manté pressionat SHIFT per a col·locar més extractors, i utilitza R per a rotar-los. + # All shop upgrades shopUpgrades: belt: @@ -444,7 +453,8 @@ buildings: name: &wire Cable description: Permet transportar energia. - miner: # Internal name for the Extractor + # Internal name for the Extractor + miner: default: name: &miner Extractor description: Posa-ho damunt d'una font de figures o colors per extraure'ls. @@ -453,7 +463,8 @@ buildings: name: Extractor (Cadena) description: Posa-ho damunt d'una font de figures o colors per extraure'ls. Pot ser encadenat! - underground_belt: # Internal name for the Tunnel + # Internal name for the Tunnel + underground_belt: default: name: &underground_belt Túnel description: Permet transportar recursos per sota d'edificis i cintes. @@ -462,7 +473,8 @@ buildings: name: Túnel de Nivell II description: Permet transportar recursos per sota d'edificis i cintes. - splitter: # Internal name for the Balancer + # Internal name for the Balancer + splitter: default: name: &splitter Distribuïdor description: Multifuncional - Distribueix les entrades i sortides equitativament. @@ -495,6 +507,9 @@ buildings: ccw: name: Rotador (Antihorari) description: Rota formes en sentit antihorari 90 graus. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -540,10 +555,12 @@ buildings: default: name: &energy_generator Generador d'energia description: Genera energia consumint figures. Cada generador requereix una figura diferent. + wire_crossings: default: - name: Wire Splitter + name: &wire_crossings Wire Splitter description: Splits a energy wire into two. + merger: name: Wire Merger description: Merges two energy wires into one. @@ -595,6 +612,7 @@ storyRewards: title: Distribuïdor compacte desc: >- Has desbloquejat una variant compacta del distribuïdor - Acepta dues entrades i les fusiona en una sola! + reward_cutter_quad: title: Cisalla quàdruple desc: Has desbloquejat una variant de la cisalla - Et permet tallar figures en quatre parts en lloc de sols en dos! @@ -633,8 +651,9 @@ storyRewards: settings: title: Opcions categories: - game: Joc - app: Aplicació + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: Desenvolupament @@ -658,6 +677,7 @@ settings: title: Interval de guardat automàtic description: >- Controla el temps entre guardats automàtics que fa el joc, pots deshabilitar-ho des d'aquí + intervals: one_minute: 1 Minut two_minutes: 2 Minuts @@ -667,124 +687,139 @@ settings: disabled: Desactivat scrollWheelSensitivity: - title: Zoom sensitivity + title: Sensitivitat del Zoom description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + Canvia la sensitivitat del zoom (Roda del ratolí o del trackpad). sensitivity: - super_slow: Super slow - slow: Slow + super_slow: Molt lent + slow: Lent regular: Regular - fast: Fast - super_fast: Super fast + fast: Ràpid + super_fast: Molt Ràpid movementSpeed: - title: Movement speed + title: Velocitat de Moviment description: >- - Changes how fast the view moves when using the keyboard. + Canvia la rapidesa amb la que la vista es mou mentres empres el teclat. speeds: - super_slow: Super slow - slow: Slow + super_slow: Molt lent + slow: Lent regular: Regular - fast: Fast - super_fast: Super Fast - extremely_fast: Extremely Fast + fast: Rápid + super_fast: Molt Ràpid + extremely_fast: Extremadament Ràpid language: - title: Language + title: Idioma description: >- - Change the language. All translations are user contributed and might be incomplete! + Canvia l'idioma. Totes les traduccions són contribucions d'usuaris i poden estar incompletes! + enableColorBlindHelper: - title: Color Blind Mode + title: Mode per Daltònics description: >- - Enables various tools which allow to play the game if you are color blind. + Habilita diverses eines que et permeten jugar si ets Daltònic. + fullscreen: - title: Fullscreen + title: Pantalla Completa description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. + Es recomana jugar en Pantalla Completa per aconseguir la millor experiència. Només disponible a la versió completa del joc. + soundsMuted: - title: Mute Sounds + title: Silencia els sons description: >- - If enabled, mutes all sound effects. + Si està activat, silencia tots els sons. + musicMuted: - title: Mute Music + title: Silencia la música description: >- - If enabled, mutes all music. + Si està activat, silencia la música. + theme: - title: Game theme + title: Tema del joc (Visual) description: >- - Choose the game theme (light / dark). + Tria el tema visual (clar / oscur). themes: - dark: Dark - light: Light + dark: Oscur + light: Clar refreshRate: - title: Simulation Target + title: Objectiu de Simulació description: >- - If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. + Si tens un monitor de 144hz, canvia la tarifa de refresc aquí per que el joc es mostri de forma correcta a tarifes de refresc altes. Pot decrementar els FPS si el teu ordenador és massa lent. + alwaysMultiplace: - title: Multiplace + title: Col·locació Múltiple description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. + Si s'activa, tots els edificis es mantindràn seleccionats després de col·locarlos fins que ho cancel·lis. Això és equivalent a mantenir SHIFT permanentment. + offerHints: - title: Hints & Tutorials + title: Pistes i Tutorials description: >- - Whether to offer hints and tutorials while playing. Also hides certain UI elements onto a given level to make it easier to get into the game. + Si s'activa, es mostraràn pistes i tutorials mentres es juga. També amaga certs elements visuals fins a un nivell per que sigui més fàcil aprendre a jugar. + enableTunnelSmartplace: - title: Smart Tunnels + title: Túnels Intel·ligents description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. This also enables to drag tunnels and excess tunnels will get removed. + Si s'activa, al col·locar túnels s'eliminaràn les cintes transportadores innecessaris. També et permet arrastrar túnels i els túnels sobrants s'eliminaràn. + vignette: - title: Vignette + title: Vinyeta description: >- - Enables the vignette which darkens the screen corners and makes text easier to read. + Activa la vinyeta, que obscureix els cantons de la pantalla i facilita la lectura de texte. + rotationByBuilding: - title: Rotation by building type + title: Rotació segons el tipus d'edifici. description: >- - Each building type remembers the rotation you last set it to individually. This may be more comfortable if you frequently switch between placing different building types. + Cada tipus d'edifici recorda la rotació que vau definir per última vegada de manera individual. Això pot ser més còmode si canvies freqüentment entre edificis. + compactBuildingInfo: - title: Compact Building Infos + title: Informació sobre Edificis Compactes description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. + Escurça els quadres d’informació dels edificis només mostrant les seves velocitats. En cas contrari, es mostra una descripció i una imatge. + disableCutDeleteWarnings: - title: Disable Cut/Delete Warnings + title: Desactiva els diàlegs de Talla/Borra description: >- - Disable the warning dialogs brought up when cutting/deleting more than 100 entities. + Desactiva els diàlegs d'advertència que es mostren en tallar / suprimir més de 100 entitats. + keybindings: - title: Keybindings + title: Combinacions de tecles hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - resetKeybindings: Reset Keybindings + Tip: Assegura't d'emprar CTRL, SHIFT i ALT! Et permeten col·locar objectes de formes diferents. + + resetKeybindings: Resetejar les Combinacions de tecles categoryLabels: - general: Application - ingame: Game - navigation: Navigating - placement: Placement - massSelect: Mass Select - buildings: Building Shortcuts - placementModifiers: Placement Modifiers + general: Aplicació + ingame: Joc + navigation: Navegació + placement: Col·locació + massSelect: Sel·lecció Massiva + buildings: Dreceres d'Edificis + placementModifiers: Modificadors de col·locació mappings: - confirm: Confirm - back: Back - mapMoveUp: Move Up - mapMoveRight: Move Right - mapMoveDown: Move Down - mapMoveLeft: Move Left - mapMoveFaster: Move Faster - centerMap: Center Map + confirm: Confirmar + back: Enrere + mapMoveUp: Moure Amunt + mapMoveRight: Moure Dreta + mapMoveDown: Moure Avall + mapMoveLeft: Moure Esquerra + mapMoveFaster: Moure més Ràpid + centerMap: Centrar Mapa - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker + mapZoomIn: Apropar + mapZoomOut: Allunyar + createMarker: Crea un Marcador - menuOpenShop: Upgrades - menuOpenStats: Statistics + menuOpenShop: Millores + menuOpenStats: Estadístiques + menuClose: Tancar Menú - toggleHud: Toggle HUD - toggleFPSInfo: Toggle FPS and Debug Info - switchLayers: Switch layers - exportScreenshot: Export whole Base as Image + toggleHud: Commutar HUD + toggleFPSInfo: Commutar FPS i Informació de Depuració + switchLayers: Canviar capes + exportScreenshot: Exportar la Base com a Imatge belt: *belt splitter: *splitter underground_belt: *underground_belt @@ -799,44 +834,49 @@ keybindings: trash: *trash wire: *wire - pipette: Pipette - rotateWhilePlacing: Rotate + pipette: Pipeta + rotateWhilePlacing: Rotar rotateInverseModifier: >- - Modifier: Rotate CCW instead - cycleBuildingVariants: Cycle Variants - confirmMassDelete: Delete area - pasteLastBlueprint: Paste last blueprint - cycleBuildings: Cycle Buildings - lockBeltDirection: Enable belt planner + Modifier: Rotar en sentit antihorari + cycleBuildingVariants: Rotar les Variants + confirmMassDelete: Eliminar àrea + pasteLastBlueprint: Afferar el darrer pla + cycleBuildings: Rotar els Buildings + lockBeltDirection: Habilitar el planificador de cintes transportadores switchDirectionLockSide: >- - Planner: Switch side - massSelectStart: Hold and drag to start - massSelectSelectMultiple: Select multiple areas - massSelectCopy: Copy area - massSelectCut: Cut area + Planner: Canviar costat - placementDisableAutoOrientation: Disable automatic orientation - placeMultiple: Stay in placement mode - placeInverse: Invert automatic belt orientation - menuClose: Close Menu + massSelectStart: Manteniu premut i arrossegueu per començar + massSelectSelectMultiple: Seleccionar múltiples àrees + massSelectCopy: Copiar àrea + massSelectCut: Tallar àrea + + placementDisableAutoOrientation: Desactivar orientació automàtica + placeMultiple: Mantenir-se en mode de col·locació + placeInverse: Invertir orientació automàtica de les cintes transportadores about: - title: About this Game + title: Sobre aquest Joc body: >- - This game is open source and developed by Tobias Springer (this is me).

- If you want to contribute, check out shapez.io on github.

- This game wouldn't have been possible without the great discord community around my games - You should really join the discord server!

- The soundtrack was made by Peppsen - He's awesome.

- Finally, huge thanks to my best friend Niklas - Without our factorio sessions this game would never have existed. + Aquest joc és de codi obert i desenvolupat per Tobias Springer (sóc jo).

+ + Si vols contribuir, visita shapez.io a GitHub.

+ + Aquest joc no hauria estat possible sense la gran comunitat de Discord al voltant dels meus jocs. Recoman unir-se al servidor de Discord!

+ + Banda sonora creada perPeppsen - És increïble.

+ + Finalment, gràcies al meu millor amic Niklas. Sense les nostres sessions de Factorio, aquest joc mai hauria existit. + changelog: - title: Changelog + title: Registre de Canvis demo: features: - restoringGames: Restoring savegames - importingGames: Importing savegames - oneGameLimit: Limited to one savegame - customizeKeybindings: Customizing Keybindings - exportingBase: Exporting whole Base as Image + restoringGames: Restaurar partides guardats + importingGames: Importar partides guardats + oneGameLimit: Limitat a una partida guardada. + customizeKeybindings: Personalitzar teclats + exportingBase: Exportar la base com a Imatge - settingNotAvailable: Not available in the demo. + settingNotAvailable: No disponible en la versió de demostració. diff --git a/translations/base-cz.yaml b/translations/base-cz.yaml index 14c8d192..2ee35618 100644 --- a/translations/base-cz.yaml +++ b/translations/base-cz.yaml @@ -1,5 +1,6 @@ # Czech translation +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io je hra o stavbě továren pro automatizaci výroby a kombinování čím dál složitějších tvarů na nekonečné mapě. @@ -72,6 +73,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: " " + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -129,7 +133,6 @@ mainMenu: savegameLevel: Úroveň savegameLevelUnknown: Neznámá úroveň - continue: Pokračovat newGame: Nová hra madeBy: Vytvořil @@ -231,8 +234,8 @@ dialogs: createMarker: title: Nová značka - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) - titleEdit: Edit Marker + desc: Pojmenuj jí nějak výstižně, též ji můžeš doplnit zkratkou pro tvar (Kterou si můžete vytvořit zde) + titleEdit: Upravit značku markerDemoLimit: desc: V ukázce můžete vytvořit pouze dvě značky. Získejte plnou verzi pro neomezený počet značek! @@ -249,8 +252,8 @@ dialogs: může zejména u větších základen dlouho trvat, nebo dokonce shodit hru! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + title: Potvrdit vyjmutí + desc: Nemůžeš si dovolit vložení této oblasti! Skutečně ji chceš vyjmout? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -469,6 +472,9 @@ buildings: ccw: name: Rotor (opačný) description: Otáčí tvary o 90 stupňů proti směru hodinových ručiček + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -504,25 +510,25 @@ buildings: description: Skladuje věci navíc až do naplnění kapacity. Může být použit na skladování surovin navíc. wire: default: - name: Energy Wire - description: Allows you to transport energy. + name: Kabel + description: Dovoluje přenos energie. advanced_processor: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + name: Invertor barev + description: Přijme barvu či tvar a převrátí jej. energy_generator: - deliver: Deliver - toGenerateEnergy: For + deliver: Dodej + toGenerateEnergy: Pro default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: Generátor energie + description: Vyrábí energii zpracováním tvarů. wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Dělič kabelů + description: Rozdělí kabel na dva. merger: - name: Wire Merger - description: Merges two energy wires into one. + name: Slučovač kabelů + description: Spojí dva kabely do jednoho. storyRewards: # Those are the rewards gained from completing the store @@ -537,7 +543,7 @@ storyRewards: reward_painter: title: Barvení desc: >- - The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, there is a color blind mode in the settings! + Barvič byl právě odemčen - Vytěžte nějaká ložiska barev (podobně jako těžíte tvary) a spojte je s tvarem v barviči pro jeho obarvení!

PS: Pokud jste barvoslepý, v nastavení naleznete režim pro barvoslepé! reward_mixer: title: Míchání barev @@ -581,7 +587,7 @@ storyRewards: desc: Odemknuli jste variantu barviče - Funguje stejně jako normální, ale nabarví dva tvary naráz pomocí jedné barvy! reward_painter_quad: - title: Quad Painting + title: Čtyřstranné barvení desc: Odemknuli jste variantu painter - Umožní vám nabarvit každou čtvrtinu tvaru jinou barvou! reward_storage: @@ -610,8 +616,9 @@ storyRewards: settings: title: Nastavení categories: - game: Hra - app: Aplikace + general: Obecné + userInterface: Uživatelské rozhraní + advanced: Rozšířené versionBadges: dev: Vývojová verze @@ -821,9 +828,9 @@ about: Pokud se chceš na hře podílet, podívej se na shapez.io na githubu.

- Tato hra by nebyla ani možná bez skvělé discord komunity + Tato hra by nebyla ani možná bez skvělé Discord komunity okolo Tobiasových her - Vážně by ses měl přijít mrknout na discord server!

+ target="_blank">Discord server!

Soundtrack udělal Peppsen - Je úžasnej.

diff --git a/translations/base-da.yaml b/translations/base-da.yaml index f5ff3fcd..abfe89a6 100644 --- a/translations/base-da.yaml +++ b/translations/base-da.yaml @@ -15,13 +15,17 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page - shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. + shortText: shapez.io handler om at bygge fabrikker på en grænseløs spilleflade for automatisk at skabe og kombinere figurer, der i stigende grad bliver mere komplicerede. + + # This is the text shown above the Discord link + discordLink: Officiel Discord - Snak lidt med mig! # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: @@ -30,776 +34,783 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.io handler om at bygge fabrikker over en grænseløs spilleflade for automatisk at skabe og kombinere figurer, der i stigende grad bliver mere komplicerede. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Når efterspurgte figurer bliver afleveret, vil du gøre fremskridt i spillet og modtage opgraderinger, der gør din fabrik hurtigere. - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Som efterspørgslen på figurer stiger, må du opskalere din fabrik for at holde trit - Glem dog ikke resurserne, du vil blive nødt til at udvide over hele den [b]uendelige flade[/b]! - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Der går ikke lang tid før du må mikse farver og male dine figurer med dem - Kombiner rød, grøn og blå farveresurser for at producere forskellige farver og mal derefter figurer med dem for at møde efterspørgslen. - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + Dette spil indeholder 18 fremadskridende Niveauers (Som allerede burde holde dig beskæftiget i timevis!) men jeg tilføjer hele tiden nyt - Der er en hel masse planlagt! - [b]Standalone Advantages[/b] + Hvis du køber spillet, får du adgang til den selvstændige version, der har endnu flere ting, og du får også adgang til nyudviklet indhold. + + [b]Fordele for køb[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Mørk Tilstand + [*] Uendelige Markører + [*] Uendelige Gem + [*] Yderligere Indstillinger + [*] Kommer snart: Ledninger & Energi! Går efter at udgive (omkring) enden af juli 2020. + [*] Kommer snart: Niveauer + [*] Støtter mig i yderligere at udvikle shapez.io ❤️ [/list] - [b]Future Updates[/b] + [b]Fremtidige Opdateringer[/b] - I am updating the game very often and trying to push an update at least every week! + Jeg opdaterer spillet meget ofte og prøver at få frigivet en opdatering mindst hver uge! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Forskellige spilleflader og udfordringer (f.eks. flader med forhindringer) + [*] Hjernevridere (Aflever den efterspurgte figur med et afgrænset areal / mængde bygninger) + [*] En 'story mode' hvor bygninger har en pris + [*] En spillefladeskaber med forskellige indstillinger (Konfigurer resurse/figur størrelse/tæthed, seed m.m.) + [*] Flere typer af figurer + [*] Forbedringer til hvor godt spillet kører (Det kører allerede rimelig godt!) + [*] Og meget mere! [/list] - [b]This game is open source![/b] + [b]Dette spil er open source![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Enhver kan kontribuere, jeg er aktivt involveret i fælleskabet og prøver at gennemgå alle forslag og tage feedback i betragtning når det er muligt. + Husk at tjekke mit trello board for den fulde køreplan! - [b]Links[/b] + [b]Link[/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Officiel Discord[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Køreplan[/url] [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://github.com/tobspr/shapez.io]Kildekode (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Hjælp med at oversætte[/url] [/list] - discordLink: Official Discord - Chat with me! - global: - loading: Loading - error: Error + loading: Indlæser + error: Fejl # How big numbers are rendered, e.g. "10,000" - thousandsDivider: "," + thousandsDivider: "." + + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "," # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k - millions: M - billions: B - trillions: T + millions: mio + billions: mia + trillions: bio # Shown for infinitely big numbers - infinite: inf + infinite: uendelig time: # Used for formatting past time dates - oneSecondAgo: one second ago - xSecondsAgo: seconds ago - oneMinuteAgo: one minute ago - xMinutesAgo: minutes ago - oneHourAgo: one hour ago - xHoursAgo: hours ago - oneDayAgo: one day ago - xDaysAgo: days ago + oneSecondAgo: et sekund siden + xSecondsAgo: sekunder siden + oneMinuteAgo: et minut siden + xMinutesAgo: minutter siden + oneHourAgo: en time siden + xHoursAgo: timer siden + oneDayAgo: en dag siden + xDaysAgo: dage siden # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s - hoursAndMinutesShort: h m + hoursAndMinutesShort: t m - xMinutes: minutes + xMinutes: minutter keys: tab: TAB control: CTRL alt: ALT escape: ESC - shift: SHIFT - space: SPACE + shift: SKIFT + space: MELLEMRUM demoBanners: # This is the "advertisement" shown in the main menu and other various places title: Demo Version intro: >- - Get the standalone to unlock all features! + Køb spillet for at få den fulde oplevelse! mainMenu: - play: Play - continue: Continue - newGame: New Game + play: Spil + continue: Fortsæt + newGame: Nyt Spil changelog: Changelog subreddit: Reddit - importSavegame: Import - openSourceHint: This game is open source! - discordLink: Official Discord Server - helpTranslate: Help translate! - madeBy: Made by + importSavegame: Importér + openSourceHint: Dette spil er open source! + discordLink: Officiel Discord Server + helpTranslate: Hjælp med at oversætte! + madeBy: Lavet af # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - Sorry, but the game is known to run slow on your browser! Get the standalone version or download chrome for the full experience. - - savegameLevel: Level - savegameLevelUnknown: Unknown Level - + Undskyld, men spillet er kendt for at køre langsomt på denne browser! Køb spillet eller download chrome for den fulde oplevelse. + savegameLevel: Niveau + savegameLevelUnknown: Ukendt Niveau dialogs: buttons: ok: OK - delete: Delete - cancel: Cancel - later: Later - restart: Restart - reset: Reset - getStandalone: Get Standalone - deleteGame: I know what I do - viewUpdate: View Update - showUpgrades: Show Upgrades - showKeybindings: Show Keybindings + delete: Slet + cancel: Fortryd + later: Senere + restart: Genstart + reset: Nulstil + getStandalone: Køb spillet + deleteGame: Jeg ved hvad jeg laver + viewUpdate: Se Opdatering + showUpgrades: Vis Opgraderinger + showKeybindings: Vis Keybindings importSavegameError: - title: Import Error + title: Import Fejl text: >- - Failed to import your savegame: + Importering af gemt spil fejlede: importSavegameSuccess: - title: Savegame Imported + title: Gemt spil Importeret text: >- - Your savegame has been successfully imported. + Dit gemte spil blev importet. gameLoadFailure: - title: Game is broken + title: Spillet er i stykker text: >- - Failed to load your savegame: + Det lykkedes ikke at åbne dit gemte spil: confirmSavegameDelete: - title: Confirm deletion + title: Bekræft sletning text: >- - Are you sure you want to delete the game? + Er du sikker på du vil slette dit gemte spil? savegameDeletionError: - title: Failed to delete + title: Sletning fejlede text: >- - Failed to delete the savegame: + Det lykkedes ikke at slette dit gemte spil: restartRequired: - title: Restart required + title: Genstart er nødvendig text: >- - You need to restart the game to apply the settings. + Du er nødt til at genstarte spillet for at anvende indstillingerne. editKeybinding: - title: Change Keybinding - desc: Press the key or mouse button you want to assign, or escape to cancel. + title: Ændr Keybinding + desc: Tryk på knappen du vil bruge, eller escape for at fortryde. resetKeybindingsConfirmation: - title: Reset keybindings - desc: This will reset all keybindings to their default values. Please confirm. + title: Nulstil keybindings + desc: Dette vil nulstille alle keybindings til deres standarder. Bekræft venligst. keybindingsResetOk: - title: Keybindings reset - desc: The keybindings have been reset to their respective defaults! + title: Keybindings nulstillet + desc: Keybindings er nulstillet til deres standarder! featureRestriction: - title: Demo Version - desc: You tried to access a feature () which is not available in the demo. Consider to get the standalone for the full experience! + title: Demoversion + desc: Du prøvede at bruge en funktion () der ikke er tilgængelig i demoen. Overvej at købe spillet for den fulde oplevelse! oneSavegameLimit: - title: Limited savegames - desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone! + title: Begrænset mængde gemte spil + desc: Du kan kun have et gemt spil ad gangen in demoversionen. Vær sød at slette det nuværende gemte spil eller at købe spillet! updateSummary: - title: New update! + title: Ny opdatering! desc: >- - Here are the changes since you last played: + Dette har ændret sig siden sidst du spillede: upgradesIntroduction: - title: Unlock Upgrades + title: Få Opgraderinger desc: >- - All shapes you produce can be used to unlock upgrades - Don't destroy your old factories! - The upgrades tab can be found on the top right corner of the screen. + Alle figurer du producerer kan blive brugt til at få opgraderinger - Ødelæg ikke dine gamle fabrikker! + Opgraderingeringsvinduet kan findes i det øverste højre hjørne af skærmen. massDeleteConfirm: - title: Confirm delete + title: Bekræft sletning desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? + Du er ved at slette mange bygninger ( helt præcist)! Er du sikker på at det er det du vil gøre? massCutConfirm: - title: Confirm cut + title: Bekræft klip desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you want to do this? + Du er ved at klippe mange bygninger ( helt præcist)! Er du sikker på at det er det du vil gøre? blueprintsNotUnlocked: - title: Not unlocked yet + title: Ikke tilgængeligt endnu desc: >- - Complete level 12 to unlock Blueprints! + Gennemfør Niveau 12 for at bruge arbejdstegninger! keybindingsIntroduction: - title: Useful keybindings + title: Brugbare keybindings desc: >- - This game has a lot of keybindings which make it easier to build big factories. - Here are a few, but be sure to check out the keybindings!

- CTRL + Drag: Select an area.
- SHIFT: Hold to place multiple of one building.
- ALT: Invert orientation of placed belts.
+ Dette spil har mange keybindings, som gør det lettere at bygge store fabrikker. + Her er et par, men husk at tjekke keybindings!

+ CTRL + Træk: Vælg et område.
+ SHIFT: Hold for at placere flere af en bygning.
+ ALT: Vend retningen af placerede transportbånd.
createMarker: - title: New Marker - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) - titleEdit: Edit Marker + title: Ny Markør + desc: Giv det et betydningsfuldt navn. du kan også inkludere en kort kode der repræsenterer en figur (Som du kan lave her) + titleEdit: Rediger Markør markerDemoLimit: - desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! + desc: Du kan kun lave to markører i demoen. Køb spillet for uendelige markører! exportScreenshotWarning: - title: Export screenshot - desc: You requested to export your base as a screenshot. Please note that this can be quite slow for a big base and even crash your game! + title: Eksporter skærmbillede + desc: Du bad om at eksportere din fabrik som et skærmbillede. Bemærk at dette kan være rimelig langsomt for en stor base og kan endda lukke dit spil! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + title: Bekræft klip + desc: Du har ikke råd til at sætte dette område ind igen! Er du sikker på at du vil klippe det? ingame: # This is shown in the top left corner and displays useful keybindings in # every situation keybindingsOverlay: - moveMap: Move - selectBuildings: Select area - stopPlacement: Stop placement - rotateBuilding: Rotate building - placeMultiple: Place multiple - reverseOrientation: Reverse orientation - disableAutoOrientation: Disable auto orientation - toggleHud: Toggle HUD - placeBuilding: Place building - createMarker: Create Marker - delete: Delete - pasteLastBlueprint: Paste last blueprint - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side - cutSelection: Cut - copySelection: Copy - clearSelection: Clear Selection + moveMap: Bevæg dig + selectBuildings: Marker område + stopPlacement: Stop placering + rotateBuilding: Roter bygning + placeMultiple: Placer flere + reverseOrientation: Omvend retning + disableAutoOrientation: Slå automatisk retning fra + toggleHud: Slå HUD til/fra + placeBuilding: Placer bygning + createMarker: Lav Markør + delete: Slet + pasteLastBlueprint: Sæt sidste arbejdstegning ind + lockBeltDirection: Aktiver bælteplanlægger + plannerSwitchSide: Vend planlægsningsside + cutSelection: Klip + copySelection: Kopier + clearSelection: Ryd Selektion pipette: Pipette - switchLayers: Switch Layers + switchLayers: Skift Lag # Names of the colors, used for the color blind mode colors: - red: Red - green: Green - blue: Blue - yellow: Yellow - purple: Purple + red: Rød + green: Grøn + blue: Blå + yellow: Gul + purple: Lilla cyan: Cyan - white: White - uncolored: No color - black: Black + white: Hvid + uncolored: Ingen farve + black: Sort # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) buildingPlacement: # Buildings can have different variants which are unlocked at later levels, # and this is the hint shown when there are multiple variants available. - cycleBuildingVariants: Press to cycle variants. + cycleBuildingVariants: Tryk for at vælge type. # Shows the hotkey in the ui, e.g. "Hotkey: Q" hotkeyLabel: >- Hotkey: infoTexts: - speed: Speed - range: Range - storage: Storage - oneItemPerSecond: 1 item / second - itemsPerSecond: items / s + speed: Fart + range: Rækkevidde + storage: Opbevaring + oneItemPerSecond: 1 genstand / sekund + itemsPerSecond: genstande / s itemsPerSecondDouble: (x2) - tiles: tiles + tiles: flader # The notification when completing a level levelCompleteNotification: # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: Level - completed: Completed - unlockText: Unlocked ! - buttonNextLevel: Next Level + levelTitle: Niveau + completed: Klaret + unlockText: er nu tilgængelig! + buttonNextLevel: Næste Niveau # Notifications on the lower right notifications: - newUpgrade: A new upgrade is available! - gameSaved: Your game has been saved. + newUpgrade: En ny opgradering er tilgængelig! + gameSaved: Dit spil er gemt. # The "Upgrades" window shop: - title: Upgrades - buttonUnlock: Upgrade + title: Opgraderinger + buttonUnlock: Opgrader # Gets replaced to e.g. "Tier IX" - tier: Tier + tier: Trin # The roman number for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXIMUM LEVEL (Speed x) + maximumLevel: HØJESTE NIVEAU (Speed x) # The "Statistics" window statistics: - title: Statistics + title: Statistikker dataSources: stored: - title: Stored - description: Displaying amount of stored shapes in your central building. + title: Opbevaret + description: Viser mængden af opbevarede figurer i din centrale bygning. produced: - title: Produced - description: Displaying all shapes your whole factory produces, including intermediate products. + title: Produceret + description: Viser alle de figurer hele din fabrik producerer, inklusiv produkter brugt til videre produktion. delivered: - title: Delivered - description: Displaying shapes which are delivered to your central building. - noShapesProduced: No shapes have been produced so far. + title: Afleveret + description: Viser figurer som er afleveret til din centrale bygning. + noShapesProduced: Ingen figurer er blevet produceret indtil videre. # Displays the shapes per minute, e.g. '523 / m' shapesPerMinute: / m # Settings menu, when you press "ESC" settingsMenu: - playtime: Playtime + playtime: Spilletid - buildingsPlaced: Buildings - beltsPlaced: Belts + buildingsPlaced: Bygninger + beltsPlaced: Bælter buttons: - continue: Continue - settings: Settings - menu: Return to menu + continue: Fortsæt + settings: Indstillinger + menu: Hovedmenu # Bottom left tutorial hints tutorialHints: - title: Need help? - showHint: Show hint - hideHint: Close + title: Har du brug for hjælp? + showHint: Vis hint + hideHint: Luk # When placing a blueprint blueprintPlacer: - cost: Cost + cost: Pris # Map markers waypoints: - waypoints: Markers + waypoints: Markører hub: HUB - description: Left-click a marker to jump to it, right-click to delete it.

Press to create a marker from the current view, or right-click to create a marker at the selected location. - creationSuccessNotification: Marker has been created. + description: Venstreklik en markør for at hoppe til den, højreklik for at slette den.

Tryk for at lave en markør på det nuværende sted, eller højreklik for at lave en markør på det valgte sted. + creationSuccessNotification: Markør er sat. # Shape viewer shapeViewer: - title: Layers - empty: Empty - copyKey: Copy Key + title: Lag + empty: Tom + copyKey: Kopier Kode # Interactive tutorial interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! + 1_1_extractor: Sæt en udvinder på toppen af encirkelfigur for at begynde produktion af den! 1_2_conveyor: >- - Connect the extractor with a conveyor belt to your hub!

Tip: Click and drag the belt with your mouse! + Forbind udvinderen til din hub med et transportbælte!

Tip: Tryk og træk bæltet med din mus! 1_3_expand: >- - This is NOT an idle game! Build more extractors and belts to finish the goal quicker.

Tip: Hold SHIFT to place multiple extractors, and use R to rotate them. + Dette er IKKE et idle game! Byg flere udvindere og bælter for at færdiggøre målet hurtigere.

Tip: Hold SKIFT for at sætte flere udvindere, og tryk R for at rotere dem. # All shop upgrades shopUpgrades: belt: - name: Belts, Distributor & Tunnels - description: Speed x → x + name: Bælter, Fordelere & Tuneller + description: Fart x → x miner: - name: Extraction - description: Speed x → x + name: Udvinding + description: Fart x → x processors: - name: Cutting, Rotating & Stacking - description: Speed x → x + name: Klipning, Rotering & Stabling + description: Fart x → x painting: - name: Mixing & Painting - description: Speed x → x + name: Blanding & Maling + description: Fart x → x # Buildings and their name / description buildings: hub: - deliver: Deliver - toUnlock: to unlock - levelShortcut: LVL + deliver: Aflever + toUnlock: for at få adgang til + levelShortcut: NIV belt: default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. + name: &belt Transportbælte + description: Transporterer figurer, hold og træk for at sætte flere. - miner: # Internal name for the Extractor + # Internal name for the Extractor + miner: default: - name: &miner Extractor - description: Place over a shape or color to extract it. + name: &miner Udvinder + description: Placer over en figur eller farve for at udvinde den. chainable: - name: Extractor (Chain) - description: Place over a shape or color to extract it. Can be chained. + name: Udvinder (Kæde) + description: Placer over en figur eller farve for at udvinde den. Kan kædes. - underground_belt: # Internal name for the Tunnel + # Internal name for the Tunnel + underground_belt: default: name: &underground_belt Tunnel - description: Allows to tunnel resources under buildings and belts. + description: Laver tunneller under bygninger og bælter. tier2: - name: Tunnel Tier II - description: Allows to tunnel resources under buildings and belts. + name: Tunnel Trin II + description: Laver tunneller under bygninger og bælter. - splitter: # Internal name for the Balancer + # Internal name for the Balancer + splitter: default: - name: &splitter Balancer - description: Multifunctional - Evenly distributes all inputs onto all outputs. + name: &splitter Fordeler + description: Flere funktioner - Fordeler alle modtagne varer jævnt. compact: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: Sammenlægger (kompakt) + description: Lægger to bælter sammen til et. compact-inverse: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: Sammenlægger (kompakt) + description: Lægger to bælter sammen til et. cutter: default: - name: &cutter Cutter - description: Cuts shapes from top to bottom and outputs both halfs. If you use only one part, be sure to destroy the other part or it will stall! + name: &cutter Klipper + description: Klipper figurer fra top til bund og udsender begge halvdele. Hvis du kun bruger den ene halvdel så husk at ødelægge den anden del, ellers går maskinen i stå! quad: - name: Cutter (Quad) - description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other parts or it will stall! + name: Klipper (firdeler) + description: Klipper figurer om til fire dele. Hvis du kun bruger nogle af dem så husk at ødelægge de andre dele, ellers går maskinen i stå! rotater: default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. + name: &rotater Drejer + description: Drejer figurer 90 grader med uret. ccw: - name: Rotate (CCW) - description: Rotates shapes counter clockwise by 90 degrees. + name: Drejer (mod uret) + description: Drejer figurer 90 grader mod uret. + fl: + name: Drejer (180) + description: Drejer figurer 180 grader. stacker: default: - name: &stacker Stacker - description: Stacks both items. If they can not be merged, the right item is placed above the left item. + name: &stacker Stabler + description: Stabler begge figurer. Hvis de ikke kan sammensmeltes, så sættes den højre figur oven på den venstre. mixer: default: - name: &mixer Color Mixer - description: Mixes two colors using additive blending. + name: &mixer Farveblander + description: Blander to farver med additiv blanding. painter: default: - name: &painter Painter - description: &painter_desc Colors the whole shape on the left input with the color from the top input. + name: &painter Maler + description: &painter_desc Farver hele figuren fra venstre side med farven fra toppen. mirrored: name: *painter description: *painter_desc double: - name: Painter (Double) - description: Colors the shapes on the left inputs with the color from the top input. + name: Maler (Dobbelt) + description: Farver figurerne fra venstre side med farven fra toppen. quad: - name: Painter (Quad) - description: Allows to color each quadrant of the shape with a different color. + name: Maler (Quad) + description: Lader dig farve hver fjerdel af figuren med forskellige farver. trash: default: - name: &trash Trash - description: Accepts inputs from all sides and destroys them. Forever. + name: &trash Skraldespand + description: Tillader input fra alle sider og ødelægger dem. For evigt. storage: - name: Storage - description: Stores excess items, up to a given capacity. Can be used as an overflow gate. + name: Opbevaring + description: Opbevarer ekstra figurer, til en given kapicitet. Kan bruges til at håndtere overproduktion. energy_generator: - deliver: Deliver - toGenerateEnergy: For energy + deliver: Aflever + toGenerateEnergy: For energi default: - name: &energy_generator Energy Generator - description: Generates energy by consuming shapes. Each energy generator requires a different shapes. + name: &energy_generator Energigenerator + description: Genererer energi ved at optage figurer. Hver energigenerator kræver forskellige figurer. wire: default: - name: Energy Wire - description: Allows you to transport energy. + name: Energiledning + description: Lader dig transportere energi. advanced_processor: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + name: Farveomvender + description: Tager imod en farve, og giver den modsatte. wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Ledningsspalter + description: Spalter en energiledning i to. merger: - name: Wire Merger - description: Merges two energy wires into one. + name: Ledningssammenlægger + description: Lægger to energiledninger sammen til en. storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: - title: Cutting Shapes - desc: You just unlocked the cutter - it cuts shapes half from top to bottom regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will stall - For this purpose I gave you a trash, which destroys everything you put into it! + title: Klippe Figurer + desc: Du har lige fået adgang til klipperen - den klipper figurer i to fra top til bund uanset hvordan den vender!

Sørg for at ødelægge alt du ikke har brug for, ellers går den i stå - Til dette har jeg givet dig skraldespanden, som ødelægger alt du putter i den! reward_rotater: - title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. + title: Rotation + desc: Drejeren er nu tilgængelig! Den drejer figurer 90 grader med uret. reward_painter: - title: Painting + title: Maling desc: >- - The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, there is a color blind mode in the settings! + Maleren er nu tilgængelig - Få noget farve med udvinderen (som du også gør med figurer) og kombiner det med en farve i maleren for at farve dem!

PS: Hvis du er farveblind, så er der en farveblindstilstand i indstillingerne! reward_mixer: - title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! + title: Farveblanding + desc: Farveblanderen er nu tilgængelig - Kombiner to farver ved brug af (strong>additiv blanding med denne bygning! reward_stacker: - title: Combiner - desc: You can now combine shapes with the combiner! Both inputs are combined, and if they can be put next to each other, they will be fused. If not, the right input is stacked on top of the left input! + title: Stabler + desc: Du kan du stable figurer med stableren! Begge inputs stables. Hvis de kan sættes ved siden af hinanden, sammensmeltes de. Hvis ikke, bliver det højre input stablet ovenpå det venstre! reward_splitter: - title: Splitter/Merger - desc: The multifunctional balancer has been unlocked - It can be used to build bigger factories by splitting and merging items onto multiple belts!

+ title: Fordeler/Sammenlægger + desc: Den flerfunktionelle Fordeler er nu tilgængelig - Den kan bruges til at bygge større fabrikker ved at fordele og sammenlægge varer på flere bælter!

reward_tunnel: title: Tunnel - desc: The tunnel has been unlocked - You can now tunnel items through belts and buildings with it! + desc: Tunnellen er nu tilgængelig - Du kan nu lave tuneller under bælter og bygninger! reward_rotater_ccw: - title: CCW Rotating - desc: You have unlocked a variant of the rotater - It allows to rotate counter clockwise! To build it, select the rotater and press 'T' to cycle its variants! + title: Rotation mod uret + desc: Du har fået adgang til en variant af drejeren - Den lader dig dreje ting mod uret! For at bygge den skal du vælge drejeren og trykke 'T'! reward_miner_chainable: - title: Chaining Extractor - desc: You have unlocked the chaining extractor! It can forward its resources to other extractors so you can more efficiently extract resources! + title: Kædeudvinder + desc: Kædeudvinder er nu tilgængelig! Den kan videregive sine resurser til andre udvindere, så du kan udvinde resurser mere effektivt! reward_underground_belt_tier_2: - title: Tunnel Tier II - desc: You have unlocked a new variant of the tunnel - It has a bigger range, and you can also mix-n-match those tunnels now! + title: Tunnel Trin II + desc: Du har fået adgang til en variant af tunnellen - Den har en større rækkevidde, og du kan også bruge begge typer tunneller på den samme strækning! reward_splitter_compact: - title: Compact Balancer + title: Kompakt Fordeler desc: >- - You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one! + Du har fået adgang til en kompakt variant af fordeleren - Den tager to inputs og lægger dem sammen til en! reward_cutter_quad: - title: Quad Cutting - desc: You have unlocked a variant of the cutter - It allows you to cut shapes in four parts instead of just two! + title: Quad Klipining + desc: Du har fået adgang til en variant af klipperen - Den lader dig klippe figurer i fire dele i stedet for kun to! reward_painter_double: - title: Double Painting - desc: You have unlocked a variant of the painter - It works as the regular painter but processes two shapes at once consuming just one color instead of two! + title: Dobbelt Maling + desc: Du har fået adgang til en variant af maleren - Den virker som en normal maler, men maler to figurer samtidig og bruger kun en farve i stedet for to. reward_painter_quad: - title: Quad Painting - desc: You have unlocked a variant of the painter - It allows to paint each part of the shape individually! + title: Quad Maling + desc: Du har fået adgang til en variant af maleren - Den lader dig male alle dele af en figur hver for sig! reward_storage: - title: Storage Buffer - desc: You have unlocked a variant of the trash - It allows to store items up to a given capacity! + title: Opbevaringsbuffer + desc: Du har fået adgang til en variant af skraldespanden - Den lader dig opbevare varer til en hvis kapacitet! reward_freeplay: - title: Freeplay - desc: You did it! You unlocked the free-play mode! This means that shapes are now randomly generated! (No worries, more content is planned for the standalone!) + title: Frit spil + desc: Du klarede det! Du har fået adgang til frit spil! Dette betyder at figurer nu er tilfældigt genereret! (Vær ikke bekymret, mere indhold er planlagt for den betalte version!) reward_blueprints: - title: Blueprints - desc: You can now copy and paste parts of your factory! Select an area (Hold CTRL, then drag with your mouse), and press 'C' to copy it.

Pasting it is not free, you need to produce blueprint shapes to afford it! (Those you just delivered). + title: Arbejdstegninger + desc: Du kan nu kopiere og indsætte dele af din fabrik! Vælg et område (Hold CTRL, og træk med musen), og tryk 'C' for at kopiere det.

At sætte det ind er ikke gratis. Du skal producere arbejdstegning figurer for at have råd til det! (Dem du lige har leveret). # Special reward, which is shown when there is no reward actually no_reward: - title: Next level + title: Næste niveau desc: >- - This level gave you no reward, but the next one will!

PS: Better don't destroy your existing factory - You need all those shapes later again to unlock upgrades! + Dette niveau gav dig ingen belønninger, men det vil det næste!

PS: Du må hellere lade være med at ødelægge din fabrik - Du får brug for alle de figurer senere igen for at få opgraderinger! no_reward_freeplay: - title: Next level + title: Næste niveau desc: >- - Congratulations! By the way, more content is planned for the standalone! + Tillykke! Forresten er mere indhold planlagt for den betalte version! settings: - title: Settings + title: Indstillinger categories: - game: Game - app: Application + general: Generelt + userInterface: Brugerflade + advanced: Avanceret versionBadges: - dev: Development - staging: Staging - prod: Production - buildDate: Built + dev: Udvikling + staging: Iscenesættelse + prod: Produktion + buildDate: Bygget labels: uiScale: - title: Interface scale + title: Grænseflade størrelse description: >- - Changes the size of the user interface. The interface will still scale based on your device resolution, but this setting controls the amount of scale. + Ændrer størrelsen på brugerfladen. Den vil stadig skalere baseret på opløsningen af din skærm, men denne indstilling bestemmer hvor meget den skalerer. scales: - super_small: Super small - small: Small - regular: Regular - large: Large - huge: Huge + super_small: Meget lille + small: Lille + regular: Normal + large: Store + huge: Kæmpe autosaveInterval: - title: Autosave Interval + title: Autogem Interval description: >- - Controls how often the game saves automatically. You can also disable it entirely here. + Ændrer hvor ofte spillet gemmer automatisk. Du kan også slå det helt fra her. intervals: - one_minute: 1 Minute - two_minutes: 2 Minutes - five_minutes: 5 Minutes - ten_minutes: 10 Minutes - twenty_minutes: 20 Minutes - disabled: Disabled + one_minute: 1 Minut + two_minutes: 2 Minutter + five_minutes: 5 Minutter + ten_minutes: 10 Minutter + twenty_minutes: 20 Minutter + disabled: Slået fra scrollWheelSensitivity: - title: Zoom sensitivity + title: Zoom følsomhed description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + Ændrer hvor følsomt zoomet er (Enten musehjulet eller trackpad). sensitivity: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super fast + super_slow: Meget langsom + slow: Langsom + regular: Normal + fast: Hurtig + super_fast: Meget hurtig movementSpeed: - title: Movement speed + title: Bevægelseshastighed description: >- - Changes how fast the view moves when using the keyboard. + Ændrer hvor hurtigt du kan bevæge dit overblik når du bruger tastaturet. speeds: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super Fast - extremely_fast: Extremely Fast + super_slow: Meget langsom + slow: Langsom + regular: Normal + fast: Hurtig + super_fast: Meget hurtig + extremely_fast: Ekstremt hurtig language: - title: Language + title: Sprog description: >- - Change the language. All translations are user contributed and might be incomplete! + Ændrer sproget. All oversættelser er lavet af fælleskabet og kan være ufuldstændige! enableColorBlindHelper: - title: Color Blind Mode + title: Farveblindstilstand description: >- - Enables various tools which allow to play the game if you are color blind. + Aktiverer forskellige redskaber der lader dig spille, selv hvis du er farveblind. fullscreen: - title: Fullscreen + title: Fuld skærm description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. + Det er foreslået at spille i fuld skærm for den bedste oplevelse. Kun tilgængelig i den betalte version. soundsMuted: - title: Mute Sounds + title: Slå lydeffekterne fra description: >- - If enabled, mutes all sound effects. + Aktiver for at slå alle lydeffekter fra. musicMuted: - title: Mute Music + title: Slå musik fra description: >- - If enabled, mutes all music. + Aktiver for at slå al musik fra. theme: - title: Game theme + title: Tema description: >- - Choose the game theme (light / dark). + Vælg tema (lys / mørk). themes: - dark: Dark - light: Light + dark: Mørk + light: Lys refreshRate: - title: Simulation Target + title: Simulationsmål description: >- - If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. + Hvis du har en 144hz skærm, så ændr opdateringshastigheden her så spillet vil simulere den højere opdateringshastighed korrekt. Dette kan faktisk sænke din FPS hvis din computer er for langsom. alwaysMultiplace: - title: Multiplace + title: Multiplacér description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. + Aktiver for at alle bygninger fortsætter med at være valgt efter placering, indtil du vælger dem fra. Dette svarer til altid at holde SKIFT nede. offerHints: - title: Hints & Tutorials + title: Hints & Vejledning description: >- - Whether to offer hints and tutorials while playing. Also hides certain UI elements onto a given level to make it easier to get into the game. + Om spillet skal tilbyde hints og vejledning imens du spiller. Skjuler også visse dele af brugerfladen indtil et givent niveau for at gøre det nemmere at lære spillet at kende. enableTunnelSmartplace: - title: Smart Tunnels + title: Smarte Tunneller description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. This also enables to drag tunnels and excess tunnels will get removed. + Aktiver for at placering af tunneller automatisk fjerner unødige bælter. Dette gør igså at du kan trække tunneller så overskydende tunneller fjernes. vignette: title: Vignette description: >- - Enables the vignette which darkens the screen corners and makes text easier to read. + Aktiverer vignette hvilket mørkner kanterne af skærmen og gør teksten nemmere at læse. rotationByBuilding: - title: Rotation by building type + title: Rotation baseret på bygningstype description: >- - Each building type remembers the rotation you last set it to individually. This may be more comfortable if you frequently switch between placing different building types. + Hver bygningstype husker den rotation du sidst satte den til. Dette kan være komfortabelt hvis du ofte skifter mellem at placere forskellige bygninger. compactBuildingInfo: - title: Compact Building Infos + title: Kompakt Bygningsinfo description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. + Forkorter infobokse til bygninger ved kun at vise deres forhold. Ellers er en beskrivelse og et billede også vist. disableCutDeleteWarnings: - title: Disable Cut/Delete Warnings + title: Slå klip/slet advarsler fra description: >- - Disable the warning dialogs brought up when cutting/deleting more than 100 entities. + Slå advarselsboksene, der dukker op når mere end 100 ting slettes, fra. keybindings: title: Keybindings hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. + Tip: Husk at bruge CTRL, SKIFT og ALT! De byder på forskellige placeringsmuligheder. - resetKeybindings: Reset Keybindings + resetKeybindings: Nulstil Keybindings categoryLabels: - general: Application - ingame: Game - navigation: Navigating - placement: Placement - massSelect: Mass Select - buildings: Building Shortcuts - placementModifiers: Placement Modifiers + general: Applikation + ingame: Spil + navigation: Navigation + placement: Placering + massSelect: Massemarkering + buildings: Bygningsgenveje + placementModifiers: Placeringsmodifikationer mappings: - confirm: Confirm - back: Back - mapMoveUp: Move Up - mapMoveRight: Move Right - mapMoveDown: Move Down - mapMoveLeft: Move Left - mapMoveFaster: Move Faster - centerMap: Center Map + confirm: Bekræft + back: Tilbage + mapMoveUp: Bevæg dig op + mapMoveRight: Bevæg dig til højre + mapMoveDown: Bevæg dig ned + mapMoveLeft: Bevæg dig til venstre + mapMoveFaster: Bevæg dig hurtigere + centerMap: Centrer kortet - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker + mapZoomIn: Zoom ind + mapZoomOut: Zoom ud + createMarker: Lav Markør - menuOpenShop: Upgrades - menuOpenStats: Statistics + menuOpenShop: Opgraderinger + menuOpenStats: Statistikker - toggleHud: Toggle HUD - toggleFPSInfo: Toggle FPS and Debug Info - switchLayers: Switch layers - exportScreenshot: Export whole Base as Image + toggleHud: Slå HUD til/fra + toggleFPSInfo: Slå FPS og Debug Info til/fra + switchLayers: Skift lag + exportScreenshot: Eksporter hele basen som et billede belt: *belt splitter: *splitter underground_belt: *underground_belt @@ -813,51 +824,51 @@ keybindings: trash: *trash pipette: Pipette - rotateWhilePlacing: Rotate + rotateWhilePlacing: Roter rotateInverseModifier: >- - Modifier: Rotate CCW instead - cycleBuildingVariants: Cycle Variants - confirmMassDelete: Delete area - pasteLastBlueprint: Paste last blueprint - cycleBuildings: Cycle Buildings - lockBeltDirection: Enable belt planner + Modifier: Roter mod uret i stedet + cycleBuildingVariants: Gennemgå Varianter + confirmMassDelete: Slet område + pasteLastBlueprint: Sæt sidste arbejdstegning ind + cycleBuildings: Gennemgå bygninger + lockBeltDirection: Slå bælteplanlægger til switchDirectionLockSide: >- - Planner: Switch side + Planner: Skift side - massSelectStart: Hold and drag to start - massSelectSelectMultiple: Select multiple areas - massSelectCopy: Copy area - massSelectCut: Cut area + massSelectStart: Hold og træk for at starte + massSelectSelectMultiple: Vælg flere områder + massSelectCopy: Kopier område + massSelectCut: Klip område - placementDisableAutoOrientation: Disable automatic orientation - placeMultiple: Stay in placement mode - placeInverse: Invert automatic belt orientation - menuClose: Close Menu - advanced_processor: Color Inverter - wire: Energy Wire + placementDisableAutoOrientation: Slå automatisk rotation fra + placeMultiple: Bliv i placeringstilstand + placeInverse: Spejlvend automatisk bælteorientering + menuClose: Luk Menu + advanced_processor: Farveomvender + wire: Energiledning about: - title: About this Game + title: Om dette spil body: >- - This game is open source and developed by Tobias Springer (this is me).

+ Dette spil er open source og er udviklet af Tobias Springer (det er mig).

- If you want to contribute, check out shapez.io on github.

+ Hvis du vil kontribuere, tjek shapez.io på github.

- This game wouldn't have been possible without the great discord community around my games - You should really join the discord server!

+ Dette spil ville ikke have været muligt uden det fremragende Discord-fælleskab omkring mine spil - Du burde virkelig deltage på Discordserveren!

- The soundtrack was made by Peppsen - He's awesome.

+ Lydsporet er lavet af Peppsen - Han er fantastisk.

- Finally, huge thanks to my best friend Niklas - Without our factorio sessions this game would never have existed. + Endelig, tusind tak til min bedste ven Niklas - Uden vi havde spillet factorio sammen ville dette spil aldrig have eksisteret. changelog: title: Changelog demo: features: - restoringGames: Restoring savegames - importingGames: Importing savegames - oneGameLimit: Limited to one savegame - customizeKeybindings: Customizing Keybindings - exportingBase: Exporting whole Base as Image + restoringGames: Genopretter gem + importingGames: Importerer gem + oneGameLimit: Afgrænset til et gem + customizeKeybindings: Tilpasser Keybindings + exportingBase: Eksportere hele basen som et billede - settingNotAvailable: Not available in the demo. + settingNotAvailable: Ikke tilgængelig i demoen. diff --git a/translations/base-de.yaml b/translations/base-de.yaml index fe745046..84c8a57e 100644 --- a/translations/base-de.yaml +++ b/translations/base-de.yaml @@ -15,15 +15,16 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: In shapez.io nutzt du die vorhandenen Ressourcen, um mit deinen Maschinen durch Kombination immer komplexere Formen zu erschaffen. - # This is the text shown above the discord link + # This is the text shown above the Discord link discordLink: Offizieller Discord - Hier kannst du mit mir schreiben! # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. @@ -33,57 +34,59 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + In shapez.io musst du Maschinen geschickt verbinden, damit Formen automatisiert erstellt, bearbeitet und kombiniert werden. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Liefere die gewünschten, stetig komplexer werdenden Formen an dein Hauptgebäude, um im Spiel voranzukommen. Schalte mit ihnen außerdem Upgrades frei, die deine Maschinen und somit auch deine Fabriken beschleunigen! - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Da die Nachfrage sowohl in der Komplexität, als auch der Menge steigt, wirst du deine Fabriken erweitern müssen. Vergiss nicht, dass du die dafür benötigten Ressourcen beschaffen musst und expandiere auf der [b]unendlichen Karte[/b]! - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Bald wirst du Farben mischen und deine Formen damit bemalen lassen. Staple dann deine fertigen Formen aufeinander und lasse so die wildesten Kreationen entstehen. - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + Nutze dein gesammeltes Wissen über die Maschinen und lasse deine Fabriken die gewünschten Formen der 18 verschiedenen Level abliefern. Schalte mit jedem Level neue Arbeitsschritte oder Gebäude frei. Das sollte dich schon für Stunden beschäftigt halten! Danach werden im Freispielmodus zufällige Formen generiert, die du ebenfalls abliefern kannst. Ich füge regelmäßig neue Funktionen hinzu und davon sind eine ganze Menge geplant! - [b]Standalone Advantages[/b] + Wenn du das Spiel erwirbst, erhälst du Zugriff auf die zusätzlichen Features der Standalone-Version. Das bedeutet, du kannst unter anderem die neuesten Updates zuerst spielen! + + [b]Vorteile der Standalone[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Dark-Mode + [*] Unbegrenzte Anzahl an Wegpunkten + [*] Unbegrenzte Anzahl an Speicherständen + [*] Zusätzliche Einstellungen + [*] Es kommen: Kabel & Energie! Voraussichtlich gegen Ende Juli 2020 + [*] Es kommen: Mehr Levels + [*] Unterstütze die Entwicklung von shapez.io ❤️ [/list] - [b]Future Updates[/b] + [b]Geplante Funktionen[/b] - I am updating the game very often and trying to push an update at least every week! + Ich bin aktiv mit der Entwicklung beschäftigt und versuche jede Woche ein Update oder den aktuellen Stand der Entwicklung zu veröffentlichen. [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Verschiedene Karten und Herausforderungen (z.B. Karten mit Hindernissen) + [*] Puzzle (Liefere die geforderte Form mit begrenztem Platz/limitierten Gebäuden) + [*] Eine Kampagne mit Gebäudekosten + [*] Konfigurierbarer Kartengenerator (Ändere die Grösse/Anzahl/Dichte der Ressourcenflecken, den Seed und viel mehr) + [*] Mehr Formentypen + [*] Performanceverbesserungen (Das Spiel läuft bereits sehr gut!) + [*] Und vieles mehr! [/list] - [b]This game is open source![/b] + [b]Das Spiel ist Open Source![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Jeder kann dazu beitragen! Ich bin aktiv in die Community involviert, versuche alle Vorschläge zu lesen und beziehe so viel Feedback wie möglich mit in die Entwicklung ein. + Die komplette Roadmap gibt es auf dem Trello-Board zum Nachlesen. [b]Links[/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Offizieller Discord[/url] [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://github.com/tobspr/shapez.io]Quelltext (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Hilf beim Übersetzen[/url] [/list] + global: loading: Laden error: Fehler @@ -91,6 +94,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "." + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "," + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -99,7 +105,7 @@ global: trillions: T # Shown for infinitely big numbers - infinite: unend + infinite: ∞ time: # Used for formatting past time dates @@ -135,25 +141,23 @@ demoBanners: mainMenu: play: Spielen - changelog: Änderungshistorie + changelog: Änderungsprotokoll + continue: Fortsetzen + newGame: Neues Spiel + subreddit: Reddit importSavegame: Importieren openSourceHint: Dieses Spiel ist Open Source! discordLink: Offizieller Discord Server + helpTranslate: Hilf beim Übersetzen! + madeBy: Ein Spiel von # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - Sorry, aber das Spiel wird in deinem Browser langsam laufen! Erwerbe die Standalone-Version oder downloade Chrome für die beste Erfahrung! + Sorry, aber das Spiel wird in deinem Browser langsam laufen! Kaufe die Standalone-Version oder verwende Chrome für die beste Erfahrung! savegameLevel: Level savegameLevelUnknown: Unbekanntes Level - - helpTranslate: Hilf beim Übersetzen! - continue: Fortsetzen - newGame: Neues Spiel - madeBy: Ein Spiel von - subreddit: Reddit - dialogs: buttons: ok: OK @@ -163,7 +167,7 @@ dialogs: restart: Neustart reset: Zurücksetzen getStandalone: Standalone Ansehen - deleteGame: Ich weiß, was ich tue + deleteGame: Ich weiß, was ich tue! viewUpdate: Update anzeigen showUpgrades: Upgrades anzeigen showKeybindings: Kürzel anzeigen @@ -196,15 +200,15 @@ dialogs: restartRequired: title: Neustart benötigt text: >- - Du muss das Spiel neu starten, um die Einstellungen anzuwenden. + Du musst das Spiel neu starten, um die Einstellungen anzuwenden. editKeybinding: title: Tastenbelegung ändern - desc: Drücke die (Maus-)Taste, die du vergeben willst, oder ESC um abzubrechen. + desc: Drücke die (Maus-)Taste, die du belegen möchtest, oder ESC um abzubrechen. resetKeybindingsConfirmation: title: Tastenbelegung zurücksetzen - desc: Das wird alle deine Tastenbelegungen auf den Standard zurücksetzen. Bist du dir sicher? + desc: Dies wird alle deine Tastenbelegungen auf den Standard zurücksetzen. Bist du dir sicher? keybindingsResetOk: title: Tastenbelegung zurückgesetzt @@ -221,23 +225,32 @@ dialogs: updateSummary: title: Neues Update! desc: >- - Hier sind die Änderungen, seit dem du das letzte Mal gespielt hast: + Hier sind die Änderungen, seitdem du das letzte Mal gespielt hast: upgradesIntroduction: title: Upgrades Freischalten desc: >- Viele deiner Formen können noch benutzt werden, um Upgrades freizuschalten - Zerstöre deine alten Fabriken nicht! - Den Upgrade-Tab kannst du oben rechts im Bildschirm finden. + Den Upgrade-Tab findest du oben rechts im Bildschirm. massDeleteConfirm: title: Löschen bestätigen desc: >- Du löscht sehr viele Gebäude ( um genau zu sein)! Bist du dir sicher? + massCutConfirm: + title: Ausschneiden bestätigen + desc: >- + Du schneidest sehr viele Gebäude aus ( um genau zu sein)! Bist du dir sicher? + + massCutInsufficientConfirm: + title: Ausschneiden bestätigen + desc: Du kannst dir das Einfügen nicht leisten! Bist du sicher, dass du trotzdem Ausschneiden möchtest? + blueprintsNotUnlocked: title: Noch nicht freigeschaltet desc: >- - Blueprints werden erst in Level 12 freigeschaltet! + Blaupausen werden erst in Level 12 freigeschaltet! keybindingsIntroduction: title: Nützliche Hotkeys @@ -251,23 +264,14 @@ dialogs: createMarker: title: Neuer Marker desc: Gib ihm einen griffigen Namen. Du kannst sogar die Abkürzung einer Form eingeben (Diese kann hier generiert werden). - titleEdit: Edit Marker + titleEdit: Marker bearbeiten markerDemoLimit: - desc: Du kannst nur 2 benutzerdefinierte Marker in der Demo benutzen. Hol dir die Standalone, um unendlich viele Marker zu erstellen! - massCutConfirm: - title: Ausschneiden bestätigen - desc: >- - Du schneidest sehr viele Gebäude aus ( um genau zu sein)! Bist du dir sicher? + desc: Du kannst nur 2 Marker in der Demo benutzen. Hol dir die Standalone, um unendlich viele Marker zu erstellen! exportScreenshotWarning: title: Bildschirmfoto exportieren - desc: >- - Hier kannst du ein Bildschirmfoto von deiner ganzen Fabrik erstellen. Für extrem große Fabriken kann das jedoch sehr lange dauern und ggf. zum Spielabsturz führen! - - massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + desc: Hier kannst du ein Bildschirmfoto von deiner ganzen Fabrik erstellen. Für extrem große Fabriken kann das jedoch sehr lange dauern und ggf. zum Spielabsturz führen! ingame: # This is shown in the top left corner and displays useful keybindings in @@ -291,7 +295,19 @@ ingame: copySelection: Kopieren clearSelection: Auswahl aufheben pipette: Pipette - switchLayers: Switch layers + switchLayers: Ebenen wechseln + + # Names of the colors, used for the color blind mode + colors: + red: Rot + green: Grün + blue: Blau + yellow: Gelb + purple: Magenta + cyan: Cyan + white: Weiß + black: Schwarz + uncolored: Farblos # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -346,14 +362,14 @@ ingame: dataSources: stored: title: Gelagert - description: Zeigt die Menge an Formen, die im zentralen Gebäude gelagert sind. + description: Zeigt die Menge an Formen, die im Hub gelagert sind. produced: title: Produziert description: Zeigt die Menge an Formen, die deine gesamte Fabrik produziert (inkl. Zwischenprodukte). delivered: title: Abgeliefert description: Zeigt die Menge an Formen, die im zentralen Gebäude abgeliefert werden. - noShapesProduced: Bisher wurden keine Formen produziert. + noShapesProduced: Es werden noch keine Formen produziert oder abgeliefert. # Displays the shapes per minute, e.g. '523 / m' shapesPerMinute: / m @@ -383,35 +399,26 @@ ingame: # Map markers waypoints: waypoints: Markierungen - hub: HUB - description: Linksklick auf einen Marker, um dort hinzugelangen, Rechtsklick, um ihn zu löschen.

Drücke um einen Marker aus deinem Blickwinkel, oder rechtsklicke, um einen Marker auf der ausgewählten Position zu erschaffen. + hub: Hub + description: Linksklick auf einen Marker, um dort hinzugelangen. Rechtsklick, um ihn zu löschen.

Drücke , um einen Marker aus deinem Blickwinkel, oder rechtsklicke, um einen Marker auf der ausgewählten Position zu erschaffen. creationSuccessNotification: Marker wurde erstellt. + # Shape viewer + shapeViewer: + title: Ebenen + empty: Leer + copyKey: Schlüssel kopieren + # Interactive tutorial interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Platziere einen Extrahierer auf der Kreisform um sie zu extrahieren! + 1_1_extractor: Platziere einen Extrahierer auf der Kreisform, um sie zu extrahieren! 1_2_conveyor: >- - Verbinde den Extrahierer mit einem Förderband und schließe ihn am zentralen Gebäude an!

Tipp: Drück und ziehe das Förderband mit der Maus! + Verbinde den Extrahierer mit einem Förderband und schließe ihn am Hub an!

Tipp: Drücke und ziehe das Förderband mit der Maus! 1_3_expand: >- - Dies ist KEIN Idle-Game! Baue mehr Extrahierer und Förderbänder, um das Ziel schneller zu erreichen.

Tipp: Halte UMSCH, um mehrere Gebäude zu platzieren und nutze R um sie zu rotieren. - - colors: - red: Rot - green: Grün - blue: Blau - yellow: Gelb - purple: Violett - cyan: Cyan - white: Weiß - uncolored: Farblos - black: Black - shapeViewer: - title: Ebenen - empty: Leer - copyKey: Copy Key + Dies ist KEIN Idle-Game! Baue mehr Extrahierer und Förderbänder, um das Ziel schneller zu erreichen.

Tipp: Halte UMSCH, um mehrere Gebäude zu platzieren und nutze R, um sie zu rotieren. # All shop upgrades shopUpgrades: @@ -430,21 +437,29 @@ shopUpgrades: # Buildings and their name / description buildings: + hub: + deliver: Liefere + toUnlock: >- + Für folgende Belohnung: + levelShortcut: LVL + belt: default: name: &belt Förderband - description: Transportiert Items. Halte und ziehe um mehrere zu platzieren. + description: Transportiert Items. Halte und ziehe, um mehrere zu platzieren. - miner: # Internal name for the Extractor + # Internal name for the Extractor + miner: default: name: &miner Extrahierer - description: Platziere ihn auf einer Form oder Farbe um sie zu extrahieren. + description: Platziere ihn auf einer Form oder Farbe, um sie zu extrahieren. chainable: name: Extrahierer (Kette) - description: Platziere ihn auf einer Form oder Farbe um sie zu extrahieren. Kann verkettet werden. + description: Platziere ihn auf einer Form oder Farbe, um sie zu extrahieren. Kann verkettet werden. - underground_belt: # Internal name for the Tunnel + # Internal name for the Tunnel + underground_belt: default: name: &underground_belt Tunnel description: Erlaubt dir, Formen und Farbe unter Gebäuden und Förderbändern durchzuleiten. @@ -453,18 +468,19 @@ buildings: name: Tunnel Stufe II description: Erlaubt dir, Formen und Farbe unter Gebäuden und Förderbändern durchzuleiten. Höhere Reichweite. - splitter: # Internal name for the Balancer + # Internal name for the Balancer + splitter: default: name: &splitter Verteiler - description: Multifunktional - Verteilt gleichmäßig vom Eingang auf den Ausgang. + description: Multifunktional - Verteilt gleichmäßig von den Eingängen auf die Ausgänge. compact: name: Kombinierer (Kompakt) - description: Vereint zwei Förderbänder zu einem. + description: Vereint zwei Eingänge zu einem Ausgang. compact-inverse: name: Kombinierer (Kompakt) - description: Vereint zwei Förderbänder zu einem. + description: Vereint zwei Eingänge zu einem Ausgang. cutter: default: @@ -476,12 +492,14 @@ buildings: rotater: default: - name: &rotater Rotierer + name: &rotater Rotierer (-90°) description: Rotiert Formen im Uhrzeigersinn um 90 Grad. - ccw: - name: Rotierer (CCW) + name: Rotierer (+90°) description: Rotiert Formen gegen den Uhrzeigersinn um 90 Grad. + fl: + name: Rotierer (180°) + description: Rotiert die Formen um 180 Grad. stacker: default: @@ -498,17 +516,18 @@ buildings: name: &painter Färber description: &painter_desc Färbt die ganze Form aus dem linken Eingang mit der Farbe aus dem oberen Eingang. - double: - name: Färber (2-Fach) - description: Färbt beide Formen aus dem linken Eingang mit der Farbe aus dem oberen Eingang. - - quad: - name: Färber (4-Fach) - description: Erlaubt jedes einzelne Viertel einer Form beliebig einzufärben. mirrored: name: *painter description: *painter_desc + double: + name: Färber (2-fach) + description: Färbt beide Formen aus dem linken Eingang mit der Farbe aus dem oberen Eingang. + + quad: + name: Färber (4-fach) + description: Erlaubt es, jedes einzelne Viertel einer Form beliebig einzufärben. + trash: default: name: &trash Mülleimer @@ -516,57 +535,52 @@ buildings: storage: name: Lager - description: Lagert den Überschuss bis zu einer gegebenen Kapazität. Kann als Überlauftor agieren. + description: Lagert Items bis zu einer gegebenen Kapazität und verwaltet den Überlauf. - hub: - deliver: Liefere - toUnlock: >- - Für folgende Belohnung: - levelShortcut: LVL wire: default: - name: Energy Wire - description: Allows you to transport energy. + name: Stromkabel + description: Erlaubt dir Strom zu transportieren. advanced_processor: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + name: Farbinvertierer + description: Invertiert die Farbe. Geht auch bei Formen. energy_generator: - deliver: Deliver - toGenerateEnergy: For + deliver: Liefere + toGenerateEnergy: für default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: Stromgenerator + description: Erzeugt Strom, indem er Formen verbraucht. wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Kabelverteiler + description: Teilt ein Stromkabel in zwei auf. merger: - name: Wire Merger - description: Merges two energy wires into one. + name: Kabelverbinder + description: Verbindet zwei Stromkabel zu einem. storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Formen zerschneiden - desc: Du hast den Schneider freigeschaltet! - Er zerschneidet Formen von oben nach unten, unabhängig von ihrer Orientierung!

Stelle sicher, dass du den Abfall loswirst, sonst verstopft die Maschine! - Dafür habe ich dir extra einen Mülleimer freigeschaltet. + desc: Du hast den Schneider freigeschaltet! Er zerschneidet Formen von oben nach unten, unabhängig von ihrer Orientierung.

Stelle sicher, dass du den Abfall loswirst, sonst verstopft die Maschine! Dafür habe ich dir extra einen Mülleimer freigeschaltet. reward_rotater: title: Rotieren - desc: Der Rotierer wurde freigeschaltet! Er rotiert Formen im Uhrzeigersinn um 90 Grad! + desc: Der Rotierer wurde freigeschaltet! Er rotiert Formen im Uhrzeigersinn um 90 Grad. reward_painter: title: Färben desc: >- - The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, there is a color blind mode in the settings! + Der Färber wurde freigeschaltet. Extrahiere ein paar Farben (genauso wie bei Formen) und färbe damit eine Form im Färber.

PS: Falls du Farbenblind bist, gibt es einen Modus für Farbenblinde in den Einstellungen! reward_mixer: title: Farben mischen - desc: Der Farbmischer wurde freigeschaltet! Kombiniere mit diesem Gebäude zwei Farben getreu der additiven Farbmischung! + desc: Der Farbmischer wurde freigeschaltet! Kombiniere mit diesem Gebäude zwei Farben getreu der additiven Farbmischung. reward_stacker: title: Stapler - desc: Mit dem Stapler kannst du nun Formen kombinieren! Passen sie nebeneinander, werden sie verschmolzen. Anderenfalls wird die rechte auf die linke Form gestapelt! + desc: Mit dem Stapler kannst du nun Formen kombinieren! Passen sie nebeneinander, werden sie verschmolzen. Anderenfalls wird die rechte auf die linke Form gestapelt. reward_splitter: title: Verteiler/Kombinierer @@ -574,11 +588,11 @@ storyRewards: reward_tunnel: title: Tunnel - desc: Der Tunnel wurde freigeschaltet! Du kannst Items nun unter Gebäuden oder Förderbändern hindurchleiten! + desc: Der Tunnel wurde freigeschaltet! Du kannst Items nun unter Gebäuden oder Förderbändern hindurchleiten. reward_rotater_ccw: title: Gegen UZS Rotieren - desc: Du hast eine zweite Variante des Rotierers freigeschaltet! Damit können Items gegen den Uhrzeigensinn gedreht werden. Wähle den Rotierer aus und drücke 'T', um auf verschiedene Varianten zuzugreifen! + desc: Du hast eine zweite Variante des Rotierers freigeschaltet! Damit können Items gegen den Uhrzeigensinn gedreht werden. Wähle den Rotierer aus und drücke 'T', um auf verschiedene Varianten zuzugreifen. reward_miner_chainable: title: Extrahierer (Kette) @@ -586,32 +600,32 @@ storyRewards: reward_underground_belt_tier_2: title: Tunnel Stufe II - desc: Du hast eine neue Variante des Tunnels freigeschaltet! Dieser hat eine höhere Reichweite und du kannst beide Tunnel miteinander mischen! + desc: Du hast eine neue Variante des Tunnels freigeschaltet! Dieser hat eine höhere Reichweite und du kannst beide Tunnel miteinander mischen. reward_splitter_compact: title: Kompakter Kombinierer desc: >- - Du hast eine kompakte Variante des Kombinierers freigeschaltet! Er hat zwei Eingänge und gibt zwei Förderbänder als eines aus! + Du hast eine kompakte Variante des Kombinierers freigeschaltet! Er hat zwei Eingänge und vereint diese zu einem Ausgang. reward_cutter_quad: title: Schneider (4-fach) - desc: Du hast eine neue Variante des Schneiders freigeschaltet! Damit kannst du Formen in alle vier Teile zerschneiden! + desc: Du hast eine neue Variante des Schneiders freigeschaltet! Damit kannst du Formen in alle vier Teile zerschneiden. reward_painter_double: title: Färber (2-fach) - desc: Du hast eine neue Variante des Färbers freigeschaltet! Hiermit kannst du zwei Formen auf einmal färben und verbrauchst nur eine Farbe! + desc: Du hast eine neue Variante des Färbers freigeschaltet! Hiermit kannst du zwei Formen auf einmal färben und verbrauchst nur eine Farbe. reward_painter_quad: title: Färber (4-fach) - desc: Du hast eine neue Variante des Färbers freigeschaltet! Er kann jedes Viertel einer Form einzeln färben, verbraucht aber auch jeweils eine Farbe! + desc: Du hast eine neue Variante des Färbers freigeschaltet! Er kann jedes Viertel einer Form einzeln färben, verbraucht aber auch jeweils eine Farbe. reward_storage: title: Zwischenlager - desc: Du hast eine neue Variante des Mülleimers freigeschaltet! Bis zu einer gewissen Kapazität können hier Items zwischengelagert werden! + desc: Du hast eine neue Variante des Mülleimers freigeschaltet! Bis zu einer gewissen Kapazität können hier Items zwischengelagert werden. reward_freeplay: - title: Freispiel - desc: Du hast es geschafft! Du hast den Freispielmodus freigeschaltet! Das heißt, dass abzuliefernde Formen jetzt zufällig generiert werden! (Keine Sorge, für die Standaloneversion ist noch mehr geplant!) + title: Freies Spiel + desc: Du hast es geschafft! Du bist im freien Spiel angekommen! Das heißt, dass abzuliefernde Formen jetzt zufällig generiert werden! (Keine Sorge, für die Standaloneversion ist noch mehr geplant!) reward_blueprints: title: Blaupause @@ -621,7 +635,7 @@ storyRewards: no_reward: title: Nächstes Level desc: >- - Dieses Level hat dir keine Belohnung gegeben, aber das nächste schon!

PS: Denk daran, deine alten Fabriken nicht zu zerstören - Du wirst sie später alle noch brauchen, um Upgrades freizuschalten! + Dieses Level hat dir keine Belohnung gegeben, aber dafür das Nächste schon!

PS: Denke daran, deine alten Fabriken nicht zu zerstören - Du wirst sie später alle noch brauchen, um Upgrades freizuschalten! no_reward_freeplay: title: Nächstes Level @@ -631,14 +645,15 @@ storyRewards: settings: title: Einstellungen categories: - game: Spiel - app: Applikation + general: Allgemein + userInterface: Benutzeroberfläche + advanced: Erweitert versionBadges: dev: Entwicklung staging: Beta prod: Produktion - buildDate: Gebaut + buildDate: Gebaut am labels: uiScale: @@ -652,10 +667,23 @@ settings: large: Groß huge: Riesig + autosaveInterval: + title: Intervall für automatisches Speichern + description: >- + Ändert das Intervall, in dem der Spielstand automatisch gespeichert wird. Die Funktion kann hier auch deaktiviert werden. + + intervals: + one_minute: 1 Minute + two_minutes: 2 Minuten + five_minutes: 5 Minuten + ten_minutes: 10 Minuten + twenty_minutes: 20 Minuten + disabled: Deaktiviert + scrollWheelSensitivity: title: Zoomempfindlichkeit description: >- - Ändert die Sensitivität des Zooms (Sowohl Mausrad, als auch Trackpad). + Ändert die Empfindlichkeit des Zooms (Sowohl Mausrad, als auch Trackpad). sensitivity: super_slow: Sehr langsam slow: Langsam @@ -663,6 +691,28 @@ settings: fast: Schnell super_fast: Sehr schnell + movementSpeed: + title: Bewegungsgeschwindigkeit + description: >- + Ändert die Geschwindigkeit, mit der der Bildschirm durch die Pfeiltasten bewegt wird. + speeds: + super_slow: Sehr langsam + slow: Langsam + regular: Normal + fast: Schnell + super_fast: Sehr schnell + extremely_fast: Extrem schnell + + language: + title: Sprache + description: >- + Ändere die Sprache. Alle Übersetzungen werden von Nutzern erstellt und sind möglicherweise unvollständig! + + enableColorBlindHelper: + title: Modus für Farbenblinde + description: >- + Aktiviert verschiedene Werkzeuge, die dir das Spielen trotz Farbenblindheit ermöglichen. + fullscreen: title: Vollbild description: >- @@ -678,98 +728,75 @@ settings: description: >- Bei Aktivierung wird die Musik stummgeschaltet. + soundVolume: + title: Geräuschlautstärke + description: >- + Regler für die Lautstärke von Geräuschen. + + musicVolume: + title: Musiklautstärke + description: >- + Regler für die Lautstärke der Musik. + theme: title: Farbmodus description: >- - Wähle zwischen dunklem und hellem Farbmodus. - + Wähle zwischen dem dunklen und dem hellen Farbmodus. themes: dark: Dunkel light: Hell + refreshRate: - title: Zielbildwiederholrate + title: Tickrate description: >- - Für z.B. einen 144-Hz-Monitor kann die Bildwiederholrate hier korrekt eingestellt werden. Bei einem zu langsamen Computer kann dies die Leistung beeinträchtigen. + Das Spiel passt die Tickrate automatisch so an, dass sie immer zwischen diesem Wert und der Hälfte bleibt. Zum Beispiel bei einer Tickrate von 60 Hz versucht das Spiel, diese zu halten. Bei Bedarf regelt der Computer diese bis zu einer Untergrenze von 30 Hz herunter. alwaysMultiplace: title: Mehrfachplatzierung description: >- - Bei Aktivierung wird das platzierte Gebäude nicht abgewählt. Das hat den gleichen Effekt wie beim Platzieren permanent UMSCH gedrückt zu halten. + Bei Aktivierung wird das platzierte Gebäude nicht abgewählt. Das hat den gleichen Effekt, wie beim Platzieren UMSCH gedrückt zu halten. offerHints: title: Hinweise & Tutorials description: >- Schaltet Hinweise und das Tutorial beim Spielen an und aus. Außerdem werden zu den Levels bestimmte Textfelder versteckt, die den Einstieg erleichtern sollen. - language: - title: Sprache - description: >- - Ändere die Sprache. Alle Übersetzungen werden von Nutzern erstellt und sind möglicherweise unvollständig! - - movementSpeed: - title: Bewegungsgeschwindigkeit - description: Ändert die Geschwindigkeit, mit der der Bildschirm durch die Pfeiltasten bewegt wird. - speeds: - super_slow: Sehr langsam - slow: Langsam - regular: Normal - fast: Schnell - super_fast: Sehr schnell - extremely_fast: Extrem schnell enableTunnelSmartplace: title: Intelligente Tunnel description: >- Aktiviert das automatische Entfernen von überflüssigen Förderbändern bei der Platzierung von Tunneln. Außerdem funktioniert das Ziehen von Tunneln und überschüssige werden ebenfalls entfernt. + vignette: title: Vignette description: >- - Aktiviert den Vignetteneffekt, der den Rand des Bildschirms zunehmend verdunkelt - und das Lesen der Textfelder vereinfacht. + Aktiviert den Vignetteneffekt, der den Rand des Bildschirms zunehmend verdunkelt und das Lesen der Textfelder vereinfacht. - autosaveInterval: - title: Intervall für automatisches Speichern + rotationByBuilding: + title: Rotation pro Gebäudetyp description: >- - Ändert das Intervall, in dem der Spielstand automatisch gespeichert wird. - Die Funktion kann hier auch deaktiviert werden. - intervals: - one_minute: 1 Minute - two_minutes: 2 Minuten - five_minutes: 5 Minuten - ten_minutes: 10 Minuten - twenty_minutes: 20 Minuten - disabled: Deaktiviert + Jeder Gebäudetyp merkt sich einzeln, in welche Richtung er zeigt. + Das fühlt sich möglicherweise besser an, wenn du häufig zwischen verschiedenen Gebäudetypen wechselst. compactBuildingInfo: title: Kompakte Gebäudeinformationen description: >- - Reduziert die Infoboxen der Gebäude auf ihre Arbeitsgeschwindigkeit. Anderenfalls wird ein - Bild mit Beschreibung angezeigt. + Reduziert die Infoboxen der Gebäude auf ihre Arbeitsgeschwindigkeit. Anderenfalls wird ein Bild mit Beschreibung angezeigt. disableCutDeleteWarnings: title: Deaktiviere Warnungsdialog beim Löschen description: >- Deaktiviert die Warnung, die beim Löschen und Ausschneiden von mehr als 100 Feldern angezeigt wird. - enableColorBlindHelper: - title: Modus für Farbenblinde - description: Aktiviert verschiedene Werkzeuge, die dir das Spielen trotz Farbenblindheit ermöglichen. - rotationByBuilding: - title: Rotation pro Gebäudetyp - description: >- - Jeder Gebäudetyp merkt sich einzeln, welche Rotation ausgewählt ist. - Das fühlt sich möglicherweise besser an, wenn du häufig zwischen verschiedenen - Gebäudetypen wechselst. - keybindings: title: Tastenbelegung hint: >- Tipp: Benutze STRG, UMSCH and ALT! Sie aktivieren verschiedene Platzierungsoptionen. - resetKeybindings: Tastenbelegung zurücksetzen. + resetKeybindings: Tastenbelegung zurücksetzen categoryLabels: - general: Applikation + general: Anwendung ingame: Spiel navigation: Navigation placement: Platzierung @@ -784,17 +811,23 @@ keybindings: mapMoveRight: Nach rechts bewegen mapMoveDown: Nach unten bewegen mapMoveLeft: Nach links bewegen + mapMoveFaster: Schneller bewegen centerMap: Karte zentrieren - mapZoomIn: Hineinzoomen - mapZoomOut: Herauszoomen + mapZoomIn: Reinzoomen + mapZoomOut: Rauszoomen createMarker: Markierung erstellen menuOpenShop: Upgrades menuOpenStats: Statistiken + menuClose: Menü schließen toggleHud: HUD an/aus toggleFPSInfo: FPS und Debug-Info an/aus + switchLayers: Ebenen wechseln + exportScreenshot: Ganze Fabrik als Foto exportieren + + # --- Do not translate the values in this section belt: *belt splitter: *splitter underground_belt: *underground_belt @@ -805,33 +838,31 @@ keybindings: mixer: *mixer painter: *painter trash: *trash + # --- + pipette: Pipette rotateWhilePlacing: Rotieren rotateInverseModifier: >- - Modifikator: stattdessen gegen UZS rotieren - cycleBuildingVariants: Variante wählen + Modifikator: stattdessen gegen den UZS rotieren + cycleBuildingVariants: Nächste Variante auswählen confirmMassDelete: Massenlöschung bestätigen - cycleBuildings: Gebäude rotieren + pasteLastBlueprint: Letzte Blaupause einfügen + cycleBuildings: Nächstes Gebäude auswählen + lockBeltDirection: Bandplaner aktivieren + switchDirectionLockSide: >- + Bandplaner: Seite wechseln massSelectStart: Halten und ziehen zum Beginnen massSelectSelectMultiple: Mehrere Areale markieren massSelectCopy: Areal kopieren + massSelectCut: Areal ausschneiden placementDisableAutoOrientation: Automatische Orientierung deaktivieren placeMultiple: Im Platziermodus bleiben placeInverse: Automatische Förderbandorientierung invertieren - pasteLastBlueprint: Letzte Blaupause einfügen - massSelectCut: Areal ausschneiden - exportScreenshot: Ganze Fabrik als Foto exportieren - mapMoveFaster: Schneller bewegen - lockBeltDirection: Bandplaner aktivieren - switchDirectionLockSide: "Planer: Seite wechseln" - pipette: Pipette - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire + advanced_processor: Farbinvertierer + energy_generator: Stromgenerator + wire: Stromkabel about: title: Über dieses Spiel @@ -849,9 +880,8 @@ about: Der Soundtrack wurde von Peppsen komponiert! Klasse Typ.

- Abschließend möchte ich meinem Kumpel Niklas danken! Ohne unsere - etlichen gemeinsamen Stunden in Factorio wäre dieses Projekt nie zustande gekommen. + Abschließend möchte ich meinem Kumpel Niklas danken! + Ohne unsere etlichen gemeinsamen Stunden in Factorio wäre dieses Projekt nie zustande gekommen. changelog: title: Änderungen diff --git a/translations/base-el.yaml b/translations/base-el.yaml index ac0baf89..a8c8b241 100644 --- a/translations/base-el.yaml +++ b/translations/base-el.yaml @@ -15,10 +15,11 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. @@ -91,6 +92,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -148,7 +152,6 @@ mainMenu: savegameLevel: Level savegameLevelUnknown: Unknown Level - continue: Continue newGame: New Game madeBy: Made by @@ -483,6 +486,9 @@ buildings: ccw: name: Rotate (CCW) description: Rotates shapes counter clockwise by 90 degrees. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -629,8 +635,9 @@ storyRewards: settings: title: Settings categories: - game: Game - app: Application + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: Development @@ -842,7 +849,7 @@ about: If you want to contribute, check out shapez.io on github.

- This game wouldn't have been possible without the great discord community + This game wouldn't have been possible without the great Discord community around my games - You should really join the discord server!

diff --git a/translations/base-en.yaml b/translations/base-en.yaml index 90421a8c..28fef7e2 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -1,5 +1,5 @@ # -# GAME TRANSLATIONS +# GAME TRANSLATIONS # # Contributing: # @@ -15,15 +15,16 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - # This is the text shown above the discord link + # This is the text shown above the Discord link discordLink: Official Discord - Chat with me! # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. @@ -34,15 +35,16 @@ steamPage: [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Upon delivering the requested shapes you'll progress within the game and unlock upgrades to speed up your factory. - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + As the demand for shapes increases, you'll have to scale up your factory to meet the demand - Don't forget about resources though, you'll have to expand across the [b]infinite map[/b]! - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Soon you'll have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with them to satisfy the demand. - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + This game features 18 progressive levels (Which should already keep you busy for hours!) but I'm constantly adding new content - There's a lot planned! + + Purchasing the game gives you access to the standalone version which has additional features, and you'll also receive access to newly developed features. [b]Standalone Advantages[/b] @@ -58,7 +60,7 @@ steamPage: [b]Future Updates[/b] - I am updating the game very often and trying to push an update at least every week! + I am updating the game often and trying to push an update at least once every week! [list] [*] Different maps and challenges (e.g. maps with obstacles) @@ -73,7 +75,7 @@ steamPage: [b]This game is open source![/b] Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Be sure to check out my trello board for the full roadmap! [b]Links[/b] @@ -92,6 +94,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -148,10 +153,11 @@ mainMenu: # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - Sorry, but the game is known to run slow on your browser! Get the standalone version or download chrome for the full experience. + Sorry, but the game is known to run slow on your browser! Get the standalone version or download Google Chrome for the full experience. savegameLevel: Level savegameLevelUnknown: Unknown Level + savegameUnnamed: Unnamed dialogs: buttons: @@ -269,6 +275,10 @@ dialogs: title: Export screenshot desc: You requested to export your base as a screenshot. Please note that this can be quite slow for a big base and even crash your game! + renameSavegame: + title: Rename Savegame + desc: You can rename your savegame here. + ingame: # This is shown in the top left corner and displays useful keybindings in # every situation @@ -299,7 +309,7 @@ ingame: green: Green blue: Blue yellow: Yellow - purple: Purple + purple: Magenta cyan: Cyan white: White black: Black @@ -367,8 +377,8 @@ ingame: description: Displaying shapes which are delivered to your central building. noShapesProduced: No shapes have been produced so far. - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m + # Displays the shapes per second, e.g. '523 / s' + shapesPerSecond: / s # Settings menu, when you press "ESC" settingsMenu: @@ -416,6 +426,12 @@ ingame: 1_3_expand: >- This is NOT an idle game! Build more extractors and belts to finish the goal quicker.

Tip: Hold SHIFT to place multiple extractors, and use R to rotate them. + # Connected miners + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limited to + # All shop upgrades shopUpgrades: belt: @@ -443,12 +459,8 @@ buildings: name: &belt Conveyor Belt description: Transports items, hold and drag to place multiple. - wire: - default: - name: &wire Energy Wire - description: Allows you to transport energy. - - miner: # Internal name for the Extractor + # Internal name for the Extractor + miner: default: name: &miner Extractor description: Place over a shape or color to extract it. @@ -457,7 +469,8 @@ buildings: name: Extractor (Chain) description: Place over a shape or color to extract it. Can be chained. - underground_belt: # Internal name for the Tunnel + # Internal name for the Tunnel + underground_belt: default: name: &underground_belt Tunnel description: Allows you to tunnel resources under buildings and belts. @@ -466,7 +479,8 @@ buildings: name: Tunnel Tier II description: Allows you to tunnel resources under buildings and belts. - splitter: # Internal name for the Balancer + # Internal name for the Balancer + splitter: default: name: &splitter Balancer description: Multifunctional - Evenly distributes all inputs onto all outputs. @@ -479,6 +493,14 @@ buildings: name: Merger (compact) description: Merges two conveyor belts into one. + compact-merge: + name: Splitter (compact) + description: Splits one conveyor belt into two. + + compact-merge-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + cutter: default: name: &cutter Cutter @@ -487,11 +509,6 @@ buildings: name: Cutter (Quad) description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other parts or it will stall! - advanced_processor: - default: - name: &advanced_processor Color Inverter - description: Accepts a color or shape and inverts it. - rotater: default: name: &rotater Rotate @@ -499,6 +516,9 @@ buildings: ccw: name: Rotate (CCW) description: Rotates shapes counter-clockwise by 90 degrees. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -522,6 +542,7 @@ buildings: double: name: Painter (Double) description: Colors the shapes on the left inputs with the color from the top input. + quad: name: Painter (Quad) description: Allows you to color each quadrant of the shape with a different color. @@ -535,30 +556,92 @@ buildings: name: Storage description: Stores excess items, up to a given capacity. Can be used as an overflow gate. - energy_generator: - deliver: Deliver - - # This will be shown before the amount, so for example 'For 123 Energy' - toGenerateEnergy: For - + wire: default: - name: &energy_generator Energy Generator - description: Generates energy by consuming shapes. + name: &wire Wire + description: &wire_desc Allows to connect logical components and can transfer items, colors or boolean signals. - wire_crossings: + wire_tunnel: default: - name: &wire_crossings Wire Splitter - description: Splits a energy wire into two. + name: &wire_tunnel Wire Tunnel + description: Allows to cross two wires without connecting them. - merger: - name: Wire Merger - description: Merges two energy wires into one. + coating: + name: Wire Insulation + description: Allows to pass through signals without connecting to other wires on the sides. + + constant_signal: + default: + name: &constant_signal Constant Signal + description: Emits a constant signal (shape, color or boolean). + + lever: + default: + name: &lever Switch + description: Can be toggled to emit 1 / 0 + + logic_gate: + default: + name: &logic_gate AND Gate + description: Emits a truthy boolean signal if both inputs are truthy. + not: + name: NOT + description: Inverts the given signal. + xor: + name: XOR + description: Emits a truthy signal if one of the inputs is truthy, but not both. + or: + name: OR + description: Emits a truthy signal if one of the inputs is truthy. + + transistor: + name: Gate + description: Only forwards the bottom input if the left input is true. + + filter: + default: + name: &filter Filter + # TEMP + description: Only allows through items which match exactly the provided shape / color. If you put in a boolean 1, it allows everything through, if you put in a 0 it will allow nothing through. + + display: + default: + name: &display Display + # TEMP + description: Can be connected on the wires layer to show a color or shape. When inputting a boolean item, the display will be white if the value is 1. + + reader: + default: + name: &reader Belt Reader + # TEMP + description: Allows to read the current item from a belt, as well as measuring the throughput. + + virtual_processor: + default: + name: &virtual_processor Virtual Cutter + description: Virtually cuts the shape input from top to bottom and returns both halfs. + + analyzer: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape and returns its shape and color + + rotater: + name: Virtual Rotater + description: Virtually rotates the shape by 90 degrees clockwise. + + unstacker: + name: Virtual Unstacker + description: Returns the topmost layer to the right, and the remaining ones on the left. + + shapecompare: + name: Compare + description: Returns true if both items are exactly equal. Can compare shapes, items and booleans. storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Cutting Shapes - desc: You just unlocked the cutter - it cuts shapes half from top to bottom regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will stall - For this purpose I gave you a trash, which destroys everything you put into it! + desc: You just unlocked the cutter - it cuts shapes in half from top to bottom regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will stall - For this purpose I have given you the trash can, which destroys everything you put into it! reward_rotater: title: Rotating @@ -630,7 +713,7 @@ storyRewards: no_reward: title: Next level desc: >- - This level gave you no reward, but the next one will!

PS: Better don't destroy your existing factory - You need all those shapes later again to unlock upgrades! + This level gave you no reward, but the next one will!

PS: Better not destroy your existing factory - You'll need all those shapes later to unlock upgrades! no_reward_freeplay: title: Next level @@ -640,8 +723,10 @@ storyRewards: settings: title: Settings categories: - game: Game - app: Application + general: General + userInterface: User Interface + advanced: Advanced + performance: Performance versionBadges: dev: Development @@ -649,6 +734,8 @@ settings: prod: Production buildDate: Built + rangeSliderPercentage: % + labels: uiScale: title: Interface scale @@ -722,6 +809,16 @@ settings: description: >- If enabled, mutes all music. + soundVolume: + title: Sound Volume + description: >- + Set the volume for sound effects + + musicVolume: + title: Music Volume + description: >- + Set the volume for music + theme: title: Game theme description: >- @@ -731,9 +828,9 @@ settings: light: Light refreshRate: - title: Simulation Target + title: Tick Rate description: >- - If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. + The game will automatically adjust the tickrate to be between this target tickrate and half of it. For example, with a tickrate of 60hz, the game will try to stay at 60hz, and if your computer can't handle it it will go down until it eventually reaches 30hz. alwaysMultiplace: title: Multiplace @@ -770,6 +867,37 @@ settings: description: >- Disables the warning dialogs brought up when cutting/deleting more than 100 entities. + lowQualityMapResources: + title: Low Quality Map Resources + description: >- + Simplifies the rendering of resources on the map when zoomed in to improve performance. + It even looks cleaner, so be sure to try it out! + + disableTileGrid: + title: Disable Grid + description: >- + Disabling the tile grid can help with the performance. This also makes the game look cleaner! + + clearCursorOnDeleteWhilePlacing: + title: Clear Cursor on Right Click + description: >- + Enabled by default, clears the cursor whenever you right click while you have a building selected for placement. If disabled, you can delete buildings by right-clicking while placing a building. + + lowQualityTextures: + title: Low quality textures (Ugly) + description: >- + Uses low quality textures to save performance. This will make the game look very ugly! + + displayChunkBorders: + title: Display Chunk Borders + description: >- + The game is divided into chunks of 16x16 tiles, if this setting is enabled the borders of each chunk are displayed. + + pickMinerOnPatch: + title: Pick miner on resource patch + description: >- + Enabled by default, selects the miner if you use the pipette when hovering a resource patch. + keybindings: title: Keybindings hint: >- @@ -808,19 +936,27 @@ keybindings: toggleFPSInfo: Toggle FPS and Debug Info switchLayers: Switch layers exportScreenshot: Export whole Base as Image + + # --- Do not translate the values in this section belt: *belt splitter: *splitter underground_belt: *underground_belt miner: *miner cutter: *cutter - advanced_processor: *advanced_processor rotater: *rotater stacker: *stacker mixer: *mixer - energy_generator: *energy_generator painter: *painter trash: *trash wire: *wire + constant_signal: *constant_signal + logic_gate: *logic_gate + lever: *lever + filter: *filter + wire_tunnel: *wire_tunnel + display: *display + reader: *reader + # --- pipette: Pipette rotateWhilePlacing: Rotate @@ -848,13 +984,13 @@ about: body: >- This game is open source and developed by Tobias Springer (this is me).

- If you want to contribute, check out shapez.io on github.

+ If you want to contribute, check out shapez.io on GitHub.

- This game wouldn't have been possible without the great discord community around my games - You should really join the discord server!

+ This game wouldn't have been possible without the great Discord community around my games - You should really join the Discord server!

The soundtrack was made by Peppsen - He's awesome.

- Finally, huge thanks to my best friend Niklas - Without our factorio sessions, this game would never have existed. + Finally, huge thanks to my best friend Niklas - Without our Factorio sessions, this game would never have existed. changelog: title: Changelog diff --git a/translations/base-es.yaml b/translations/base-es.yaml index 436bf750..765970d6 100644 --- a/translations/base-es.yaml +++ b/translations/base-es.yaml @@ -15,17 +15,18 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io es un juego sobre construir fábricas para automatizar la creación y combinación de figuras cada vez más complejas en un mapa infinito. - # This is the text shown above the discord link + # This is the text shown above the Discord link discordLink: Discord oficial - ¡Chatea conmigo! - + # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: # - Do not translate the first line (This is the gif image at the start of the store) @@ -33,7 +34,7 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io es un juego basado en la construcción de fábricas para automatizar la creación y combinación de figuras en un mapa que se expande infinitamente. + shapez.io es un juego basado en la construcción de fábricas para automatizar la creación y combinación de figuras en un mapa que se expande infinitamente. Entrega las figuras requeridas para progresar y desbloquear mejoras para aumentar la velocidad de tu fábrica. Al aumentar la demanda, necesitarás escalar tu fábrica para ajustarte a las necesidades - ¡No te olvides de los recursos, necesitarás expandirte en el [b]mapa infinito[/b]! @@ -44,7 +45,7 @@ steamPage: Comprando el juego tendrás acceso a la versión completa con contenido adicional, además del contenido en desarrollo. - [b]Standalone Advantages[/b] + [b]Ventajas del juego completo[/b] [list] [*] Modo oscuro @@ -73,7 +74,7 @@ steamPage: [b]¡Este juego es de código abierto![/b] Cualquiera puede contribuir, estoy activamente involucrado en la comunidad e intento leer todas las sugerencias y considerar todas las propuestas planteadas. - ¡Comprueba mi tablero de Trello para ver todo lo planificado! + ¡Comprueba mi tablero de Trello para ver todo lo planificado! [b]Enlaces[/b] @@ -92,6 +93,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "." + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "," + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -216,7 +220,7 @@ dialogs: oneSavegameLimit: title: Partidas guardadas limitadas desc: Solo puedes tener una partida guardada a la vez en la versión de prueba. ¡Por favor, elimina la ya existente u obtén el juego completo! - + updateSummary: title: ¡Nueva actualización! desc: >- @@ -499,6 +503,9 @@ buildings: ccw: name: Rotador (Inverso) description: Rota las figuras en sentido antihorario 90 grados. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -553,7 +560,7 @@ buildings: merger: name: Fusionador de cables description: Fusiona dos cables en uno - + storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: @@ -599,8 +606,7 @@ storyRewards: reward_splitter_compact: title: Balanceador compacto - desc: >- - Has desbloqueado una variante compacta del balanceador - ¡Acepta dos entradas y las junta en una salida! + desc: Has desbloqueado una variante compacta del balanceador - ¡Acepta dos entradas y las junta en una salida! reward_cutter_quad: title: Cortador cuádruple @@ -640,8 +646,9 @@ storyRewards: settings: title: Opciones categories: - game: Juego - app: Aplicación + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: Desarrollo @@ -867,4 +874,4 @@ demo: customizeKeybindings: Personalizando atajos de teclado exportingBase: Exportando la base completa como imagen - settingNotAvailable: No disponible en la versión de prueba. \ No newline at end of file + settingNotAvailable: No disponible en la versión de prueba. diff --git a/translations/base-fi.yaml b/translations/base-fi.yaml index 892ee7ae..5acc58cf 100644 --- a/translations/base-fi.yaml +++ b/translations/base-fi.yaml @@ -15,10 +15,11 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io on peli tehtaiden rakentamisesta, joiden avulla automatisoidaan yhä monimutkaisempien muotojen luonti and yhdisteleminen loputtomassa maailmassa. @@ -91,6 +92,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -152,8 +156,6 @@ mainMenu: savegameLevel: Taso savegameLevelUnknown: Tuntematon Taso - - dialogs: buttons: ok: OK @@ -498,6 +500,9 @@ buildings: ccw: name: Rotate (Vastapäivään) description: Kääntää muotoja 90 astetta vastapäivään. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -637,8 +642,9 @@ storyRewards: settings: title: Asetukset categories: - game: Peli - app: Sovellus + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: Kehitys @@ -847,7 +853,7 @@ about: Jos haluat osallistua, tarkista shapez.io githubissa.

- Tämä peli ei olisi ollut mahdollinen ilman suurta discord yhteisöä pelini ympärillä - Sinun kannattaisi liittyä discord palvelimelleni!

+ Tämä peli ei olisi ollut mahdollinen ilman suurta Discord yhteisöä pelini ympärillä - Sinun kannattaisi liittyä Discord palvelimelleni!

Ääniraidan on tehnyt Peppsen - Hän on mahtava.

diff --git a/translations/base-fr.yaml b/translations/base-fr.yaml index 181b5003..0504956a 100644 --- a/translations/base-fr.yaml +++ b/translations/base-fr.yaml @@ -15,10 +15,11 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io est un jeu qui consiste à construire des usines pour automatiser la création et la combinaison de formes de plus en plus complexes sur une carte infinie. @@ -30,66 +31,68 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.io est un jeu dans lequel vous devrez construire des usines pour automatiser la création et la combinaison de formes de plus en plus complexes sur une carte infinie. + Lors de la livraison des formes requises vous progresserez et débloquerez des améliorations pour accélerer votre usine. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Au vu de l'augmentation des demandes de formes, vous devrez agrandir votre usine pour répondre à la forte demande - Mais n'oubliez pas les ressources, vous drevrez vous étendre au milieu de cette [b]carte infinie[/b] ! - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Bientôt vous devrez mixer les couleurs et peindre vos formes avec - Combinez les ressources de couleurs rouge, verte et bleue pour produire différentes couleurs et peindre les formes avec pour satisfaire la demande. - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Ce jeu propose 18 niveaux progressifs (qui devraient déjà vous occuper quelques heures !) mais j'ajoute constamment de nouveau contenus - Il y en a beaucoup de prévus ! - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + Acheter le jeu vous donne accès à la version complète qui a des fonctionnalités additionnelles et vous recevrez aussi un accès à des fonctionnalités fraîchement développées. - [b]Standalone Advantages[/b] + [b]Avantages de la version complète (standalone)[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Mode sombre + [*] Balises infinies + [*] Parties infinies + [*] Plus d'options + [*] Prochainement: Câbles et énergie ! Prévu pour (environ) fin Juillet 2020. + [*] Prochainement: Plus de niveaux + [*] Aidez moi à continuer de développer shapez.io ❤️ [/list] - [b]Future Updates[/b] + [b]Mises à jour futures[/b] - I am updating the game very often and trying to push an update at least every week! + Je fais souvent des mises à jour et essaye d'en sortir une par semaine! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Différentes cartes et challenges (e.g. carte avec obstacles) + [*] Puzzles (Délivrer la forme requise avec une zone limitée/jeu de bâtiments) + [*] Un mode histoire où les bâtiments ont un coût + [*] Générateur de carte configurable (configuration des ressources/formes/taille/densitée, seed et plus) + [*] Plus de formes + [*] Amélioration des performances (Le jeu tourne déjà plutot bien !) + [*] Et bien plus ! [/list] - [b]This game is open source![/b] + [b]Ce jeu est open source ![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! - - [b]Links[/b] + Tout le monde peut contribuer, je suis très impliqué dans la communauté et j'essaye de répondre à toutes les suggestions et prendre en compte vos retours si possible. + Jetez un coup d'œil à mon Trello pour le suivi du projet et la planification du développement ! + [b]Liens[/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Discord officiel[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Trello[/url] [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://github.com/tobspr/shapez.io]Code source (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Aidez à traduire[/url] [/list] - discordLink: Official Discord - Chat with me! + discordLink: Discord officiel - Parlez avec moi! global: loading: Chargement error: Erreur # How big numbers are rendered, e.g. "10,000" - thousandsDivider: "." + thousandsDivider: " " + + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "," # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. cf wikipedia système international d'unité # For french: https://fr.wikipedia.org/wiki/Pr%C3%A9fixes_du_Syst%C3%A8me_international_d%27unit%C3%A9s @@ -125,7 +128,7 @@ global: control: CTRL alt: ALT escape: ESC - shift: SHIFT + shift: MAJ space: ESPACE demoBanners: @@ -144,12 +147,11 @@ mainMenu: # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - Désolé, mais ce jeu est connu pour tourner lentement sur votre navigateur web ! Procurez-vous la version complète ou téléchargez Chrome pour une meilleure expérience. + Désolé, ce jeu est connu pour tourner lentement sur votre navigateur web ! Procurez-vous la version complète ou téléchargez Chrome pour une meilleure expérience. savegameLevel: Niveau savegameLevelUnknown: Niveau inconnu - continue: Continuer newGame: Nouvelle partie madeBy: Créé par @@ -165,7 +167,7 @@ dialogs: reset: Réinitialiser getStandalone: Se procurer la version complète deleteGame: Je sais ce que je fais - viewUpdate: Voir les mises-à-jour + viewUpdate: Voir les mises à jour showUpgrades: Montrer les améliorations showKeybindings: Montrer les raccourcis @@ -180,7 +182,7 @@ dialogs: Votre sauvegarde a été importée avec succès. gameLoadFailure: - title: Le jeu est cassé + title: La sauvegarde est corrompue text: >- Impossible de charger votre sauvegarde: @@ -201,7 +203,7 @@ dialogs: editKeybinding: title: Changer les contrôles - desc: Appuyez sur la touche que vous voulez assigner, ou Escape pour annuler. + desc: Appuyez sur la touche que vous voulez assigner, ou Échap pour annuler. resetKeybindingsConfirmation: title: Réinitialiser les contrôles @@ -220,7 +222,7 @@ dialogs: desc: Vous ne pouvez avoir qu'une seule sauvegarde en même temps dans la version démo. Merci d'effacer celle en cours ou alternativement de vous procurer la version complète ! updateSummary: - title: Nouvel mise-à-jour ! + title: Nouvelle mise à jour ! desc: >- Voici les modifications depuis votre dernière session: @@ -233,13 +235,12 @@ dialogs: massDeleteConfirm: title: Confirmation de suppression desc: >- - Vous allez supprimer pas mal de bâtiments ( pour être exact) ! Êtes vous certains de vouloir faire cela ? + Vous allez supprimer pas mal de bâtiments ( pour être exact) ! Êtes vous certains de vouloir faire ça ? massCutConfirm: title: Confirmer la coupure desc: >- - Vous vous apprêtez à couper beaucoup de bâtiments ( pour être précis) ! Êtes-vous - certains de vouloir faire cela ? + Vous vous apprêtez à couper beaucoup de bâtiments ( pour être précis) ! Êtes-vous certains de vouloir faire ça ? blueprintsNotUnlocked: title: Pas encore débloqué @@ -249,7 +250,7 @@ dialogs: keybindingsIntroduction: title: Raccourcis utiles desc: >- - Le jeu a plein de raccourcis facilitant la construction de grandes usines. + Le jeu a de nombreux raccourcis facilitant la construction de grandes usines. En voici quelques uns, n'hésitez pas à aller découvrir les raccourcis !

CTRL + Glisser: Sélectionne une zone à copier / effacer.
SHIFT: Laissez appuyé pour placer plusieurs fois le même bâtiment.
@@ -258,7 +259,7 @@ dialogs: createMarker: title: Nouvelle balise desc: Donnez-lui un nom, vous pouvez aussi inclure le raccourci d'une forme (Que vous pouvez générer ici) - titleEdit: Edit Marker + titleEdit: Éditer cette balise markerDemoLimit: desc: Vous ne pouvez créer que deux balises dans la démo. Achetez la version complète pour en faire autant que vous voulez ! @@ -266,11 +267,11 @@ dialogs: exportScreenshotWarning: title: Exporter une capture d'écran desc: >- - Vous avez demandé à exporter votre base sous la forme d'une capture d'écran. Soyez conscient que cela peut s'avérer passablement lent pour une grande base, voire même planter votre jeu ! + Vous avez demandé à exporter votre base sous la forme d'une capture d'écran. Soyez conscient que cela peut s'avérer passablement lent pour une grande base, voire même faire planter votre jeu ! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + title: Confirmer la coupe + desc: Vous n'avez pas les moyens de copier cette zone ! Etes vous certain de vouloir la couper ? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -294,7 +295,7 @@ ingame: copySelection: Copier clearSelection: Effacer la sélection pipette: Pipette - switchLayers: Switch layers + switchLayers: Échanger les calques # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -351,10 +352,10 @@ ingame: description: Affiche le nombre de formes stockées dans votre bâtiment central. produced: title: Produit - description: Affiche tous les formes que votre usine entière produit, en incluant les formes intermédiaires. + description: Affiche tous les formes que votre usine produit, en incluant les formes intermédiaires. delivered: title: Délivré - description: Affiche les formes qui ont été livrées dans votre centre. + description: Affiche les formes qui ont été livrées dans votre bâtiment central. noShapesProduced: Aucune forme n'a été produite jusqu'à présent. # Displays the shapes per minute, e.g. '523 / m' @@ -398,7 +399,7 @@ ingame: Connectez l'extracteur avec un convoyeur vers votre centre !

Astuce: Cliquez et faites glisser le convoyeur avec votre souris ! 1_3_expand: >- - Ceci n'est PAS un jeu incrémental et inactif ! Construisez plus d'extracteurs et de convoyeurs pour atteindre plus vite votre votre but.

Astuce: Gardez SHIFT enfoncé pour placer plusieurs extracteurs, et utilisez R pour les faire pivoter. + Ceci n'est PAS un jeu incrémental et inactif ! Construisez plus d'extracteurs et de convoyeurs pour atteindre plus vite votre votre but.

Astuce: Gardez MAJ enfoncé pour placer plusieurs extracteurs, et utilisez R pour les faire pivoter. colors: red: Rouge @@ -409,11 +410,11 @@ ingame: cyan: Cyan white: Blanc uncolored: Non coloré - black: Black + black: Noir shapeViewer: title: Calques empty: Vide - copyKey: Copy Key + copyKey: Copier la clé de forme # All shop upgrades shopUpgrades: @@ -486,6 +487,9 @@ buildings: ccw: name: Pivoteur inversé description: Fait pivoter une forme de 90 degrés vers la gauche. + fl: + name: Retourneur + description: Tourne la forme de 180 degrés. stacker: default: @@ -525,25 +529,25 @@ buildings: levelShortcut: NV wire: default: - name: Energy Wire - description: Allows you to transport energy. + name: Ligne énergétique + description: Permet de transporter de l'énergie. advanced_processor: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + name: Inverseur de couleur + description: Accepte une couleur ou une forme et l'inverse. energy_generator: - deliver: Deliver - toGenerateEnergy: For + deliver: Délivrer + toGenerateEnergy: Pour default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: Générateur d'énergie + description: Genère de l'énergie en consommant des formes. wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Duplicateur de ligne + description: Sépare une ligne énergétique en deux. merger: - name: Wire Merger - description: Merges two energy wires into one. + name: Fusionneur de ligne + description: Fusionne deux lignes énergétiques en une seule. storyRewards: # Those are the rewards gained from completing the store @@ -566,7 +570,7 @@ storyRewards: reward_stacker: title: Combineur - desc: Vous pouvez maintenant combiner deux formes avec le combineur ! Les deux entrées sont combinée et si elles ne peuvent êtres mises l'une à côté de l'autre, elles sont fusionnées. Sinon, la forme de droite est placée au dessus de la forme de gauche après avoir été légèrement réduite. + desc: Vous pouvez maintenant combiner deux formes avec le combineur ! Les deux entrées sont combinées et si elles ne peuvent êtres mises l'une à côté de l'autre, elles sont fusionnées. Sinon, la forme de droite est placée au dessus de la forme de gauche après avoir été légèrement réduite. reward_splitter: title: Distributeur/Rassembleur @@ -617,8 +621,6 @@ storyRewards: title: Patrons desc: Vous pouvez maintenant copier et coller des parties de votre usines ! Sélectionnez une zone (Appuyez sur CTRL, et sélectionnez avec votre souris), et appuyez sur 'C' pour la copier.

Coller n'est pas gratuit, vous devez produire des formes de patrons pour vous le payer (les mêmes que celles que vous venez de livrer). - # Question from the translator: Should shortcuts be hardcoded in this message ? - # Special reward, which is shown when there is no reward actually no_reward: title: Niveau suivant @@ -633,8 +635,10 @@ storyRewards: settings: title: Options categories: - game: Jeu - app: Application + general: Général + userInterface: Interface Utilisateur + advanced: Avancé + performance: Performance versionBadges: dev: Développement @@ -705,9 +709,9 @@ settings: Affiche ou non le bouton 'Afficher un indice' dans le coin inférieur gauche. language: - title: Langage + title: Langue description: >- - Change le langage. Toutes les traductions sont des contributions des utilisateurs et pourraient être partiellement incomplètes ! + Change la langue. Toutes les traductions sont des contributions des utilisateurs et pourraient être partiellement incomplètes ! movementSpeed: title: Vitesse de déplacement @@ -719,11 +723,13 @@ settings: fast: Rapide super_fast: Très rapide extremely_fast: Extrêmement rapide + enableTunnelSmartplace: title: Tunnels intelligents description: >- Si cette option est sélectionnée, placer des tunnels effacera automatiquement les convoyeurs inutiles. Cela permet aussi d'étirer les tunnels et les tunnels en surnombre seront effacés. + vignette: title: Effet de vignette description: >- @@ -740,10 +746,12 @@ settings: ten_minutes: 10 Minutes twenty_minutes: 20 Minutes disabled: Désactivé + compactBuildingInfo: title: Informations réduites sur les bâtiments description: >- Raccourcit les panneaux d'information sur les bâtiments en n'affichant que les ratios. Dans le cas contraire, une description et une imagine sont présentés. + disableCutDeleteWarnings: title: Désactive les avertissement pour Couper/Effacer description: >- @@ -752,12 +760,39 @@ settings: enableColorBlindHelper: title: Mode Daltonien description: Active divers outils qui permettent de jouer à ce jeu si vous êtes daltonien. + rotationByBuilding: title: Rotation par catégorie de bâtiment description: >- Chaque catégorie de bâtiment enregistre le sens de rotation que vous lui avez assigné la dernière fois, de manière individuelle. Cela sera sans doute plus confortable si vous alternez fréquemment entre le placement de différents types de bâtiments. + lowQualityMapResources: + title: Ressources de la carte de plus basse qualité + description: >- + Simplifie le rendu des ressources sur la carte lorsqu'elle est zoomée opur améliorer les performances. + C'est encore plus clean, n'oubliez pas d'essayer ! + + disableTileGrid: + title: Desactiver la grille de placement + description: >- + Desactiver la grille de placement peut aider les performances. Ça rend aussi le jeu encore plus uni! + + clearCursorOnDeleteWhilePlacing: + title: Effacer le curseur avec clic droit + description: >- + Activé par défaut, efface le curseur lorsque vous faites un clic droit en ayant un bâtiment selectioné pour la constructio. Si desactivé, vous pouvez detruire les bâtiments en faisant un clic droit tout en placant un bâtiment. + + lowQualityTextures: + title: Textures de basse résolution (Moche) + description: >- + Utilise des textures de basse qualité pour augmenter les performances. Cela va rendre le jeu moche! + + displayChunkBorders: + title: Monter les bordures de chunks + description: >- + Le jeu est divisé en parties de 16x16 cases, si ce réglage est activé, les bordures de chaque partie sont affichées. + keybindings: title: Contrôles hint: >- @@ -824,11 +859,11 @@ keybindings: lockBeltDirection: Utiliser le plannificateur de convoyeurs switchDirectionLockSide: "Plannificateur: changer de côté" pipette: Pipette - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire + menuClose: Fermer le menu + switchLayers: Échanger les calques + advanced_processor: Inverseur de couleur + energy_generator: Générateur d'énergie + wire: Ligne énergétique about: title: À propos de ce jeu @@ -839,9 +874,9 @@ about: Si vous souhaitez contribuer, allez voir shapez.io sur github.

- Ce jeu n'aurait pu être réalisé sans la précieuse communauté discord autour de + Ce jeu n'aurait pu être réalisé sans la précieuse communauté Discord autour de mes jeux - Vous devriez vraiment envisager de joindre le serveur discord !

+ target="_blank">serveur Discord !

La bande son a été créée par Peppsen - Il est impressionnant !

@@ -865,4 +900,4 @@ demo: # French translation version v0.5 based on english v1.1.8 by Didier WEERTS 'The Corsaire' # -# French translation completed (and corrected) by Pascal Grossé and Withers001 +# French translation completed (and corrected) by Pascal Grossé, martypiton and Withers001. diff --git a/translations/base-hr.yaml b/translations/base-hr.yaml index 01d43304..5a221561 100644 --- a/translations/base-hr.yaml +++ b/translations/base-hr.yaml @@ -15,7 +15,7 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # @@ -47,6 +47,7 @@ # + Rotator = Obrtač (jer mi Okretač zvuči nekako krivo) # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io je igra o izradi tvornica za automatizaciju stvaranja i spajanja sve složenijih oblika unutar beskonačno velike mape. @@ -120,6 +121,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: " " + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -186,7 +190,6 @@ mainMenu: # TODO - dialogs: buttons: ok: OK @@ -531,6 +534,9 @@ buildings: ccw: name: Obrtač (↺) description: Okreće oblike za 90 stupnjeva u smjeru suprotnom od kazaljke na satu. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -670,8 +676,9 @@ storyRewards: settings: title: Postavke categories: - game: Igra - app: Aplikacija + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: Development @@ -881,7 +888,7 @@ about: If you want to contribute, check out shapez.io on github.

- This game wouldn't have been possible without the great discord community around my games - You should really join the discord server!

+ This game wouldn't have been possible without the great Discord community around my games - You should really join the Discord server!

The soundtrack was made by Peppsen - He's awesome.

diff --git a/translations/base-hu.yaml b/translations/base-hu.yaml index 798cff44..bc5b727e 100644 --- a/translations/base-hu.yaml +++ b/translations/base-hu.yaml @@ -15,13 +15,17 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page - shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. + shortText: A shapez.io-ban gyárak építésével kell automatizálni az egyre összetettebb alakzatok gyártását és kombinálását egy végtelen méretű térképen. + + # This is the text shown above the Discord link + discordLink: Hivatalos Discord - Beszélgessünk! # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: @@ -30,76 +34,78 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + A shapez.io egy olyan játék, amelyben gyárak építésével kell automatizálni az egyre összetettebb alakzatok gyártását és összeillesztését, mindezt egy végtelenül növekvő térképen. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + A kívánt alakzatok kézbesítése lehetővé teszi a játékban való előrehaladást, és a gyártási folyamatot felgyorsító fejlesztések feloldását. - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Ahogy egyre több és több alakzatot kell kézbesíteni, úgy a gyártási folyamatot is fel kell skálázni - Ne feledkezz meg az erőforrásokról sem, egy [b]végtelen méretű térképen[/b] terjeszkedhetsz! - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Előbb vagy utóbb színeket kell majd összekeverned és lefesteni az alakzatokat - Keverd össze a piros, töld és kék színeket, hogy új árnyalatokat hozz létre, és fesd le az alakzatokat velük, hogy teljesíteni tudd az elvárásokat. - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + A játékban 18 fokozatosan erősödő szint található (ami már így is órákra le tud kötni!), de folyamatosan adok új tartalmakat hozzá - Nagyon sok tervem van! - [b]Standalone Advantages[/b] + A játék megvásárlásával Tiéd lehet a teljes (önálló) verzió, amely még többet tartalmaz, és azonnal hozzáférsz a legfrissebb tartalmakhoz. + + [b]Az Önálló Játék Előnyei[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Éjszakai Mód + [*] Végtelen Útpontok + [*] Végtelen Játék Mentés + [*] Kiegészítő Beállítások + [*] Hamarosan: Vezetékek és Energia! A cél (nagyjából) 2020 Július vége. + [*] Hamarosan: További Szintek + [*] Lehetővé teszi, hogy tovább fejleszzem a shapez.io-t ❤️ [/list] - [b]Future Updates[/b] + [b]Tervezett Frissítések[/b] - I am updating the game very often and trying to push an update at least every week! + Nagyon gyakran frissítem a játékot, igyekszem minden héten egy új frissítést kiadni! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Különböző térképek és kihívások (pl. pályák akadályokkal) + [*] Fejtörők (Juttasd a célba a kívánt alakzatot egy korlátozott méretű területen / korlátozott darab épülettel) + [*] Sztori-mód, ahol az épületek pénzbe kerülnek + [*] Testreszabható térképgenerátor (Beállítható forrás/alakzat/sűrűség, seed és mások) + [*] További alakzattípusok + [*] Teljesítménybeli javítások (A játék már most nagyon jól fut!) + [*] És még sok más! [/list] - [b]This game is open source![/b] + [b]A játék nyílt forráskódú![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Bárki közreműködhet. Aktív részese vagyok a közösségnek, és igyekszem minden javaslatot és visszajelzéset figyelembe venni. + Mindenképpen látogass el a Trello-mra a teljes ütemtervért! - [b]Links[/b] + [b]Linkek[/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Hivatalos Discord[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Ütemterv[/url] [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://github.com/tobspr/shapez.io]Forráskód (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Segíts lefordítani[/url] [/list] - discordLink: Official Discord - Chat with me! - global: loading: Betöltés error: Hiba # How big numbers are rendered, e.g. "10,000" - thousandsDivider: "," + thousandsDivider: "." + + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "," # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: - thousands: E + thousands: e millions: M - billions: Mlrd - trillions: T + billions: Mrd + trillions: Tr # Shown for infinitely big numbers - infinite: inf + infinite: végtelen time: # Used for formatting past time dates @@ -129,49 +135,47 @@ global: demoBanners: # This is the "advertisement" shown in the main menu and other various places - title: Demó verzi + title: Demó verzió intro: >- - Get the standalone to unlock all features! + Vásárold meg az önálló verziót a teljes játékélményért! mainMenu: play: Játék - changelog: Changelog + continue: Folytatás + newGame: Új Játék + changelog: Változások + subreddit: Reddit importSavegame: Importálás openSourceHint: Ez a játék nyílt forráskódú! discordLink: Hivatalos Discord Szerver - helpTranslate: Segíts a fordításban! + helpTranslate: Segíts fordítani! + madeBy: Készítette # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - Sorry, but the game is known to run slow on your browser! Get the standalone version or download chrome for the full experience. + Elnézést, de a játék ezen a böngészőn problémásan fut. Vásárold meg az Önálló Verziót, vagy töltsd le a Chrome-ot a teljes játékélményért. savegameLevel: . szint savegameLevelUnknown: Ismeretlen szint - - continue: Continue - newGame: New Game - madeBy: Made by - subreddit: Reddit - dialogs: buttons: ok: OK delete: Törlés - cancel: Megszakítás + cancel: Mégse later: Később restart: Újrakezdés reset: Visszaállítás - getStandalone: Get Standalone - deleteGame: Tudom mit csinálok - viewUpdate: View Update - showUpgrades: Show Upgrades - showKeybindings: Show Keybindings + getStandalone: Teljes Verzió + deleteGame: Játék Törlése + viewUpdate: Frissítés Megtekintése + showUpgrades: Fejlesztések + showKeybindings: Irányítás importSavegameError: title: Importálás Hiba text: >- - Failed to import your savegame: Nem sikerült importálni a mentésed. + Nem sikerült importálni a mentésed: importSavegameSuccess: title: Mentés Importálva @@ -179,19 +183,19 @@ dialogs: A mentésed sikeresen importálva lett. gameLoadFailure: - title: Game is broken + title: A játék elromlott text: >- - Failed to load your savegame: Nem sikerült betölteni a mentésed + Nem sikerült betölteni a mentésed: confirmSavegameDelete: - title: Confirm deletion + title: Törlés megerősítése text: >- Biztos, hogy ki akarod törölni? savegameDeletionError: title: Sikertelen törlés text: >- - Failed to delete the savegame: Nem sikerült törölni a mentésed. + Nem sikerült törölni a mentésed: restartRequired: title: Újraindítás szükséges @@ -199,135 +203,146 @@ dialogs: Újra kell indítanod a játékot, hogy életbe lépjenek a módosítások. editKeybinding: - title: Change Keybinding - desc: Press the key or mouse button you want to assign, or escape to cancel. + title: Gyorsbillentyű módosítása + desc: Nyomd meg a billentyűt vagy egérgombot, amit használni szeretnél, vagy nyomj ESC-et, ha mégse. resetKeybindingsConfirmation: - title: Reset keybindings - desc: This will reset all keybindings to their default values. Please confirm. + title: Gyorsbillentyűk visszaállítása + desc: Ez minden gyorsbillentyűt visszaállít az eredeti állapotára. Biztos vagy benne? keybindingsResetOk: - title: Keybindings reset - desc: The keybindings have been reset to their respective defaults! + title: Gyorsbillentyűk visszaállítva + desc: A gyorsbillentyűk az eredeti értékekre visszaállítva! featureRestriction: - title: Demo Version - desc: You tried to access a feature () which is not available in the demo. Consider to get the standalone for the full experience! + title: Demó Verzió + desc: Egy olyan funkciót próbáltál elérni (), amely nem elérhető a Demóban. Vásárold meg an Önálló verziót a teljes játékélményért! oneSavegameLimit: - title: Limited savegames - desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone! + title: Egy Játékmentés + desc: A Demó verzióban egyszerre csak egy játékmentésed lehet. Töröld a meglévő mentésedet, vagy vásárold meg az Önálló verziót! updateSummary: title: Új frissítés! desc: >- - Here are the changes since you last played: + Íme a változások a legutóbbi játékod óta: upgradesIntroduction: - title: Unlock Upgrades + title: Szerezz Fejlesztéseket desc: >- - All shapes you produce can be used to unlock upgrades - Don't destroy your old factories! - The upgrades tab can be found on the top right corner of the screen. + Minden legyártott alakzatot felhasználhatsz a fejlesztésekhez - Ne töröld ki a régi gyáraidat! + A Fejlesztések lap a képernyő jobb felső sarkában található. massDeleteConfirm: - title: Confirm delete + title: Törlés megerősítése desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? + Egy csomó épületet akarsz egyszerre törölni (egészen pontosan -t)! Biztos, hogy ezt szeretnéd? + + massCutConfirm: + title: Biztosan kivágod? + desc: >- + Egy csomó épületet akarsz egyszerre kivágni (egészen pontosan -t)! Biztos, hogy ezt szeretnéd? + + massCutInsufficientConfirm: + title: Kivágás megerősítése + desc: Nincs elég Tervrajzod ennek a beillsztéséhez! Egészen biztos, hogy kivágod? blueprintsNotUnlocked: title: Még nincs feloldva desc: >- - Blueprints have not been unlocked yet! Complete more levels to unlock them. + A Tervrajzokat a 12-es szinten fogod feloldani. keybindingsIntroduction: - title: Useful keybindings + title: Hasznos billentyűk desc: >- - This game has a lot of keybindings which make it easier to build big factories. - Here are a few, but be sure to check out the keybindings!

- CTRL + Drag: Select area to copy / delete.
- SHIFT: Hold to place multiple of one building.
- ALT: Invert orientation of placed belts.
+ A játék sok hasznos gyorsbillentyűt tartalmaz, amelyek megkönnyítik a gyárépítést. + Íme, néhány, de feltétlenül nézd meg a gyorsbillentyűket!

+ CTRL + Húzás: Terület kijelölése másolás/törléshez.
+ SHIFT: Egyszerre több épületet rak le.
+ ALT: Megfordítja a futószalagok irányát lehelyezéskor.
createMarker: - title: New Marker - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) - titleEdit: Edit Marker + title: Új Jelölő + desc: Adj neki egy nevet, vagy egy alakzat gyorskódját (amit itt tudsz legenerálni) + titleEdit: Jelölő Szerkesztése markerDemoLimit: - desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! - massCutConfirm: - title: Confirm cut - desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you - want to do this? + desc: A Demó verzióban csak két Jelölőd lehet. Vásárold meg az Önálló verziót, hogy feloldd ezt a korlátozást! exportScreenshotWarning: - title: Export screenshot + title: Képernyőkép exportálása desc: >- - You requested to export your base as a screenshot. Please note that this can - be quite slow for a big base and even crash your game! - - massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + A teljes bázisod képének lementését választottad. Vedd figyelembe, hogy ez nagy méretű bázisoknál igen lassú lehet, de akár a játék összeomlását is okozhatja! ingame: # This is shown in the top left corner and displays useful keybindings in # every situation keybindingsOverlay: - moveMap: Move + moveMap: Mozgatás selectBuildings: Terület kijelölése - stopPlacement: Stop placement + stopPlacement: Lehelyezés megszakítása rotateBuilding: Épület forgatása - placeMultiple: Place multiple - reverseOrientation: Reverse orientation - disableAutoOrientation: Disable auto orientation - toggleHud: Toggle HUD - placeBuilding: Place building - createMarker: Create Marker - delete: Destroy - pasteLastBlueprint: Paste last blueprint - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side - cutSelection: Cut - copySelection: Copy - clearSelection: Clear Selection - pipette: Pipette - switchLayers: Switch layers + placeMultiple: Több lehelyezése + reverseOrientation: Irány megfordítása + disableAutoOrientation: Automatikus iránykeresés kikapcsolása + toggleHud: Kezelőfelület ki/bekapcsolása + placeBuilding: Épület lehelyezése + createMarker: Jelölő készítése + delete: Törlés + pasteLastBlueprint: Legutóbb használt Tervrajz beillesztése + lockBeltDirection: Futószalag-tervező engedélyezése + plannerSwitchSide: Tervező oldal váltás + cutSelection: Kivágás + copySelection: Másolás + clearSelection: Kijelölés megszüntetése + pipette: Pipetta + switchLayers: Réteg váltás + + # Names of the colors, used for the color blind mode + colors: + red: Piros + green: Zöld + blue: Kék + yellow: Sárga + purple: Lila + cyan: Világoskék + white: Fehér + black: Fekete + uncolored: Színezetlen # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) buildingPlacement: # Buildings can have different variants which are unlocked at later levels, # and this is the hint shown when there are multiple variants available. - cycleBuildingVariants: Nyomd meg a -t, hogy válts a variációk között. + cycleBuildingVariants: Nyomd meg a -t, a variációk váltogatásához. # Shows the hotkey in the ui, e.g. "Hotkey: Q" hotkeyLabel: >- - Hotkey: + Gyorsbillentyű: infoTexts: - speed: Gyorsaság - range: Range - storage: Storage + speed: Sebesség + range: Távolság + storage: Kapacitás oneItemPerSecond: 1 tárgy / mp itemsPerSecond: tárgy / mp itemsPerSecondDouble: (x2) - tiles: tiles + tiles: csempe # The notification when completing a level levelCompleteNotification: # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: . szint - completed: Completed - unlockText: Feloldva ! + levelTitle: . Szint + completed: Teljesítve + unlockText: Feloldva! buttonNextLevel: Következő Szint # Notifications on the lower right notifications: newUpgrade: Egy új fejlesztés elérhető! - gameSaved: A játékod el lett mentve. + gameSaved: A játékállás mentve. # The "Upgrades" window shop: @@ -335,12 +350,12 @@ ingame: buttonUnlock: Fejlesztés # Gets replaced to e.g. "Tier IX" - tier: Tier + tier: . Szint # The roman number for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXIMUM LEVEL (Speed x) + maximumLevel: LEGMAGASABB SZINT (x Sebesség) # The "Statistics" window statistics: @@ -348,14 +363,14 @@ ingame: dataSources: stored: title: Tárolva - description: Displaying amount of stored shapes in your central building. + description: Az összes tárolt alakzatod a központi épületben. produced: title: Gyártva - description: Displaying all shapes your whole factory produces, including intermediate products. + description: Az összes eddig legyártott alakzatod, beleértve a köztes alakzatokat is. delivered: - title: Delivered - description: Displaying shapes which are delivered to your central building. - noShapesProduced: No shapes have been produced so far. + title: Beszállítva + description: Az összes alakzat, amely jelenleg kézbesítés alatt van a központba. + noShapesProduced: Még nem gyártottál egy alazkatot sem. # Displays the shapes per minute, e.g. '523 / m' shapesPerMinute: / p @@ -364,8 +379,8 @@ ingame: settingsMenu: playtime: Játékidő - buildingsPlaced: Épület - beltsPlaced: Futószalag + buildingsPlaced: Épületek száma + beltsPlaced: Futószalagok hossza buttons: continue: Folytatás @@ -384,160 +399,169 @@ ingame: # Map markers waypoints: - waypoints: Markers - hub: HUB - description: Left-click a marker to jump to it, right-click to delete it.

Press to create a marker from the current view, or right-click to create a marker at the selected location. - creationSuccessNotification: Marker has been created. + waypoints: Jelölők + hub: KÖZPONT + description: Bal klikk egy jelölőre az odaugráshoz, jobb klikk a törléshez.

Nyomj -t egy jelölő készítéséhez a jelenlegi nézetből, vagy jobb klikk egy jelölő készítéséhez a kiválasztott helyre. + creationSuccessNotification: Jelölő létrehozva. + + # Shape viewer + shapeViewer: + title: Rétegek + empty: Üres + copyKey: Gyorskód másolása # Interactive tutorial interactiveTutorial: - title: Tutorial + title: Oktatás hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! + 1_1_extractor: Helyezz egy bányát egy kör alakzat tetejére a kibányászásához! 1_2_conveyor: >- - Connect the extractor with a conveyor belt to your hub!

Tip: Click and drag the belt with your mouse! + Kösd össze a bányát egy futószalag segítségével a Központi épülettel!

Tipp: Kattints és húzd a futószalagot az egérrel! 1_3_expand: >- - This is NOT an idle game! Build more extractors and belts to finish the goal quicker.

Tip: Hold SHIFT to place multiple extractors, and use R to rotate them. - - colors: - red: Red - green: Green - blue: Blue - yellow: Yellow - purple: Purple - cyan: Cyan - white: White - uncolored: No color - black: Black - shapeViewer: - title: Layers - empty: Empty - copyKey: Copy Key + Ez NEM egy tétlen játék! Építs több bányát és futószalagot, hogy hamarabb elérd a célt.

Tipp: Tartsd lenyomva a SHIFT-et, hogy egyszerre több bányát helyezz le, és nyomj R-t a forgatáshoz. # All shop upgrades shopUpgrades: belt: - name: Belts, Distributor & Tunnels - description: Speed x → x + name: Futószalagok, Elosztók & Alagutak + description: x → x Sebesség miner: - name: Extraction - description: Speed x → x + name: Bányászat + description: x → x Sebesség processors: - name: Cutting, Rotating & Stacking - description: Speed x → x + name: Vágás, Forgatás & Összeillesztés + description: x → x Sebesség painting: - name: Mixing & Painting - description: Speed x → x + name: Keverés & Festés + description: x → x Sebesség # Buildings and their name / description buildings: - belt: - default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. - - miner: # Internal name for the Extractor - default: - name: &miner Extractor - description: Place over a shape or color to extract it. - - chainable: - name: Extractor (Chain) - description: Place over a shape or color to extract it. Can be chained. - - underground_belt: # Internal name for the Tunnel - default: - name: &underground_belt Tunnel - description: Allows to tunnel resources under buildings and belts. - - tier2: - name: Tunnel Tier II - description: Allows to tunnel resources under buildings and belts. - - splitter: # Internal name for the Balancer - default: - name: &splitter Balancer - description: Multifunctional - Evenly distributes all inputs onto all outputs. - - compact: - name: Merger (compact) - description: Merges two conveyor belts into one. - - compact-inverse: - name: Merger (compact) - description: Merges two conveyor belts into one. - - cutter: - default: - name: &cutter Cutter - description: Cuts shapes from top to bottom and outputs both halfs. If you use only one part, be sure to destroy the other part or it will stall! - quad: - name: Cutter (Quad) - description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other part or it will stall! - - rotater: - default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. - ccw: - name: Rotate (CCW) - description: Rotates shapes counter clockwise by 90 degrees. - - stacker: - default: - name: &stacker Stacker - description: Stacks both items. If they can not be merged, the right item is placed above the left item. - - mixer: - default: - name: &mixer Color Mixer - description: Mixes two colors using additive blending. - - painter: - default: - name: &painter Painter - description: &painter_desc Colors the whole shape on the left input with the color from the right input. - double: - name: Painter (Double) - description: Colors the shapes on the left inputs with the color from the top input. - quad: - name: Painter (Quad) - description: Allows to color each quadrant of the shape with a different color. - mirrored: - name: *painter - description: *painter_desc - - trash: - default: - name: &trash Trash - description: Accepts inputs from all sides and destroys them. Forever. - - storage: - name: Storage - description: Stores excess items, up to a given capacity. Can be used as an overflow gate. hub: deliver: Deliver toUnlock: to unlock levelShortcut: LVL + + belt: + default: + name: &belt Futószalag + description: Elemeket szállít, tartsd nyomva az egérgombot egyszerre több lerakásához. + wire: default: - name: Energy Wire + name: &wire Energy Wire description: Allows you to transport energy. + + # Internal name for the Extractor + miner: + default: + name: &miner Bányász + description: Tedd egy alakzatra vagy színre a kibányászásához. + + chainable: + name: Bányász (összekapcsolható) + description: Tedd egy alakzatra vagy színre a kibányászásához. Több egymáshoz kapcsolható. + + # Internal name for the Tunnel + underground_belt: + default: + name: &underground_belt Alagút + description: Segítségével futószalagok és épületek alatt átvezethetők az elemek. + + tier2: + name: Alagút II + description: Segítségével futószalagok és épületek alatt átvezethetők az elemek. + + # Internal name for the Balancer + splitter: + default: + name: &splitter Elosztó + description: Többfunkciós - Egyenletesen szétosztja a bementeket a kimenetekre. + + compact: + name: Egyesítő (kompakt) + description: Két futószalagot egyesít. + + compact-inverse: + name: Egyesítő (kompakt) + description: Két futószalagot egyesít. + + cutter: + default: + name: &cutter Vágó + description: Függőlegesen félbevágja az alakzatokat. Ha csak az egyik felet akarod használni, ne felejtsd el a másikat kukába küldeni, különben eldugítja! + quad: + name: Vágó (negyedelő) + description: Négyfelé vágja az alakzatokat. Cuts shapes into four parts. Ha csak az egyik felet akarod használni, ne felejtsd el a többit a kukába küldeni, különben eldugítja! + advanced_processor: default: - name: Color Inverter + name: &advanced_processor Color Inverter description: Accepts a color or shape and inverts it. + + rotater: + default: + name: &rotater Forgató + description: Elforgatja az alakzatot óramutató irányában 90 fokkal. + ccw: + name: Forgató (fordított) + description: Elforgatja az alakzatot óramutatóval ellentétesen 90 fokkal. + fl: + name: Forgató (180) + description: Elforgatja az alakzatot 180 fokkal. + + stacker: + default: + name: &stacker Egyesítő + description: Egyesít két elemet. Ha nem lehet összeilleszteni őket, a jobboldali elem a baloldali tetejére kerül. + + mixer: + default: + name: &mixer Színkeverő + description: Összekever két színt összeadó színkeveréssel. + + painter: + default: + name: &painter Festő + description: &painter_desc Beszínezi az alakzatot a baloldali bemeneten a jobboldali bemeneten érkező színnel. + + mirrored: + name: *painter + description: *painter_desc + + double: + name: Festő (Dupla) + description: Beszínezi az alakzatokat a baloldali bemeneteken a fenti bemeneten érkező színnel. + + quad: + name: Festő (Négyszeres) + description: Az alakzat négy negyedét különböző színekkel lehet vele színezni. + + trash: + default: + name: &trash Kuka + description: Bármelyik irányból lehet hozzá csatlakozni, és megsemmisíti a beleküldött elemeket. Örökre. + + storage: + name: Tároló + description: Tárolja a fölös elemeket egy bizonyos kapacitásig. + energy_generator: deliver: Deliver + + # This will be shown before the amount, so for example 'For 123 Energy' toGenerateEnergy: For + default: - name: Energy Generator + name: &energy_generator Energy Generator description: Generates energy by consuming shapes. + wire_crossings: default: - name: Wire Splitter + name: &wire_crossings Wire Splitter description: Splits a energy wire into two. + merger: name: Wire Merger description: Merges two energy wires into one. @@ -628,8 +652,9 @@ storyRewards: settings: title: Beállítások categories: - game: Game - app: Application + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: Development @@ -839,9 +864,9 @@ about: If you want to contribute, check out shapez.io on github.

- This game wouldn't have been possible without the great discord community + This game wouldn't have been possible without the great Discord community around my games - You should really join the discord server!

+ target="_blank">Discord server!

The soundtrack was made by Peppsen - He's awesome.

diff --git a/translations/base-ind.yaml b/translations/base-ind.yaml new file mode 100644 index 00000000..80e1238a --- /dev/null +++ b/translations/base-ind.yaml @@ -0,0 +1,876 @@ +# +# GAME TRANSLATIONS +# +# Contributing: +# +# If you want to contribute, please make a pull request on this respository +# and I will have a look. +# +# Placeholders: +# +# Do *not* replace placeholders! Placeholders have a special syntax like +# `Hotkey: `. They are encapsulated within angle brackets. The correct +# translation for this one in German for example would be: `Taste: ` (notice +# how the placeholder stayed '' and was not replaced!) +# +# Adding a new language: +# +# If you want to add a new language, ask me in the Discord and I will setup +# the basic structure so the game also detects it. +# + +--- +steamPage: + # This is the short text appearing on the steam page + shortText: shapez.io adalah permainan membangun pabrik-pabrik dengan tujuan untuk mengautomatiskan pembentukan dan pemrosesan bentuk-bentuk yang bertambah semakin kompleks di dalam area permainan yang meluas secara tak terhingga. + + # This is the text shown above the discord link + discordLink: Tautan Resmi Discord – Obrol dengan saya! + # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. + # NOTICE: + # - Do not translate the first line (This is the gif image at the start of the store) + # - Please keep the markup (Stuff like [b], [list] etc) in the same format + longText: >- + [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] + + shapez.io adalah permainan membangun pabrik-pabrik dengan tujuan untuk mengautomatiskan pembentukan dan pemrosesan bentuk-bentuk yang bertambah semakin kompleks di dalam area permainan yang meluas secara tak terhingga. + + Setelah pengiriman bentuk-bentuk yang diminta, Anda akan maju dalam permainan dan membuka tingkatan versi-versi mesin selanjutnya untuk mempercepat pabrik Anda. + + Seiring meningkatnya kesulitan dari bentuk-bentuk yang diminta, Anda harus meningkatkan pabrik Anda untuk mengatasi kesulitan tersebut – Jangan lupa dengan sumber-sumber daya, Anda harus memperluas ke seluruh [b]area yang tidak terbatas[/b]! + + Kemudian Anda harus mencampurkan warna-warna dan mencat bentuk-bentuk dengannya – Campurkan merah, hijau, dan biru untuk memproduksi warna-warna lain dan mencat bentuk-bentuk dengannya untuk memenuhi permintaan. + + Permainan ini mempunyai 18 level-level progresif (yang mana akan membuat Anda sibuk berjam-jam!), akan tetapi saya akan terus menambahkan konten-konten baru – Ada banyak yang direncanakan! + + Membeli permainan ini akan memberikan Anda akses ke versi penuh yang memiliki fitur-fitur tambahan, dan Anda juga akan menerima akses ke fitur-fitur yang baru dikembangkan. + + [b]Keuntungan Versi Penuh[/b] + + [list] + [*] Versi Permainan Gelap + [*] Titik Arah Tak Terhingga + [*] Penyimpanan Permainan Tak Terhingga + [*] Pengaturan-pengaturan Tambahan + [*] Akan datang: Kawat & Energi! Akan dicoba untuk dicapai untuk (kira-kira) akhir Juli 2020. + [*] Akan datang: Level-level tambahan + [*] Memperkenankan saya untuk terus mengembangkan shapez.io ❤️ + [/list] + + [b]Pembaruan di Masa Depan[/b] + + Saya seringkali membarui permainan ini dan terus mencoba untuk menciptakan pembaruan paling sedikit sekali seminggu! + + [list] + [*] Peta-peta dan tantangan-tantangan berbeda (contohnya, peta-peta dengan berbagai rintangan) + [*] Berbagai teka-teki (Kirim bentuk yang diminta dengan area terbatas atau sekelompok bangunan tertentu) + [*] Modus cerita dimana bangunan-bangunan memiliki biaya. + [*] Generator peta yang dapat dikonfigurasi (Konfigurasikan sumber daya/ukuran bentuk/kepadatan, benih dan lainnya) + [*] Tipe-tipe bentuk tambahan + [*] Peningkatan kinerja (Permainannya sudah bekerja cukup baik!) + [*] Dan masih banyak lagi! + [/list] + + [b]Permainan ini bekerja secara open source![/b] + + Siapa saja dapat berkontribusi, saya terlibat aktif di dalam komunitas dan akan mencoba untuk meninjau dan menerima semua saran untuk dipertimbangkan dimana memungkinkan. + Pastikan Anda periksa papan trello saya untuk peta perencanaan yang lengkap! + + [b]Tautan-tautan[/b] + + [list] + [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] + [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] + [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [/list] + +global: + loading: Memuat + error: Terdapat kesalahan + + # How big numbers are rendered, e.g. "10,000" + thousandsDivider: "," + + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. + suffix: + thousands: k + millions: M + billions: B + trillions: T + + # Shown for infinitely big numbers + infinite: tak terhingga + + time: + # Used for formatting past time dates + oneSecondAgo: satu detik yang lalu + xSecondsAgo: detik yang lalu + oneMinuteAgo: satu menit yang lalu + xMinutesAgo: menit yang lalu + oneHourAgo: satu jam yang lalu + xHoursAgo: jam yang lalu + oneDayAgo: satu hari yang lalu + xDaysAgo: hari yang lalu + + # Short formats for times, e.g. '5h 23m' + secondsShort: det + minutesAndSecondsShort: m det + hoursAndMinutesShort: j m + + xMinutes: menit + + keys: + tab: TAB + control: CTRL + alt: ALT + escape: ESC + shift: SHIFT + space: SPACE + +demoBanners: + # This is the "advertisement" shown in the main menu and other various places + title: Versi Demo + intro: >- + Dapatkan versi penuh untuk membuka semua fitur! + +mainMenu: + play: Mulai Permainan + continue: Lanjutkan Permainan + newGame: Permainan Baru + changelog: Ganti Data Log + subreddit: Reddit + importSavegame: Impor Data Simpanan + openSourceHint: Permainan ini bekerja secara open source! + discordLink: Server Discord Resmi + helpTranslate: Bantu Terjemahkan! + madeBy: Dibuat oleh + + # This is shown when using firefox and other browsers which are not supported. + browserWarning: >- + Maaf, tetapi permainan ini biasanya lambat pada perambah (browser) Anda! Dapatkan versi penuh atau unduh Chrome untuk pengalaman sepenuhnya. + + savegameLevel: Level + savegameLevelUnknown: Level tidak diketahui + +dialogs: + buttons: + ok: OK + delete: Hapus + cancel: Batal + later: Nanti + restart: Mulai Ulang + reset: Setel Ulang + getStandalone: Dapatkan Versi Penuh + deleteGame: Saya tahu apa yang saya kerjakan + viewUpdate: Tampilkan Pembaruan + showUpgrades: Tunjukkan Tingkatan + showKeybindings: Tunjukan Tombol Pintas + + importSavegameError: + title: Kesalahan pada Impor + text: >- + Gagal memasukkan data simpanan Anda: + + importSavegameSuccess: + title: Impor Berhasil + text: >- + Data simpanan Anda berhasil dimasukkan. + + gameLoadFailure: + title: Permainan Rusak + text: >- + Gagal memuat data simpanan Anda: + + confirmSavegameDelete: + title: Konfirmasi Penghapusan + text: >- + Apakah Anda yakin untuk menghapus data permainan? + + savegameDeletionError: + title: Gagal Menghapus + text: >- + Gagal untuk menghapus data simpanan: + + restartRequired: + title: Diperlukan untuk Memulai Kembali + text: >- + Anda harus memulai kembali permainan untuk menerapkan pengaturan. + + editKeybinding: + title: Ganti Tombol Pintas + desc: Tekan tombol pada papan ketik atau tetikus yang ingin anda tetapkan, atau tekan escape untuk membatalkan. + + resetKeybindingsConfirmation: + title: Setel Ulang Tombol-tombol Pintas + desc: Ini akan menyetel ulang semua tombol pintas kepada pengaturan awalnya. Harap konfirmasi. + + keybindingsResetOk: + title: Setel Ulang + desc: Tombol-tombol pintas sudah disetel ulang ke pengaturan awalnya! + + featureRestriction: + title: Versi Demo + desc: Anda mencoba untuk mengakses fitur () yang tidak tersedia pada versi demo. Pertimbangkan untuk mendapatkan versi penuh untuk pengalaman sepenuhnya! + + oneSavegameLimit: + title: Penyimpanan Permainan Terbatas + desc: Anda hanya dapat memiliki satu simpanan permainan dalam versi demo. Harap hapus yang telah ada atau dapatkan versi penuh! + + updateSummary: + title: Pembaruan Baru! + desc: >- + Berikut perubahan-perubahan yang telah dibuat sejak Anda main terakhir kali: + + upgradesIntroduction: + title: Buka Tingkatan-tingkatan + desc: >- + Semua bentuk yang anda produksi dapat digunakan untuk membuka tingkatan baru - Jangan hancurkan pabrik-pabrik lama Anda! + Tab tingkatan dapat ditemukan di sudut atas kanan layar Anda. + + massDeleteConfirm: + title: Konfirmasi Penghapusan + desc: >- + Anda akan menghapus banyak bangunan (tepatnya )! Apakah Anda yakin untuk melakukannya? + + massCutConfirm: + title: Pastikan Pemindahan + desc: >- + Anda akan memindahkan banyak bangunan (tepatnya )! Apakah Anda yakin untuk melakukannya? + + massCutInsufficientConfirm: + title: Tidak Mampu Memindahkan + desc: >- + Anda tidak mampu menanggung biaya pemindahan area ini! Apakah Anda yakin untuk memindahkannya? + + blueprintsNotUnlocked: + title: Belum Terbuka + desc: >- + Selesaikan level 12 untuk membuka cetak biru! + + keybindingsIntroduction: + title: Tombol Pintas Berguna + desc: >- + Permainan ini memiliki banyak tombol pintas yang membuatnya lebih mudah untuk membangun pabrik-pabrik besar. + Berikut adalah beberapa, namun pastikan Anda perhatikan tombol-tombol pintasnya!

+ CTRL + Tarik: Pilih sebuah area.
+ SHIFT: Tahan untuk meletakkan beberapa kali bangunan yang.
+ ALT: Ganti orientasi sabuk konveyor yang telah diletakkan.
+ + createMarker: + title: Penanda Baru + titleEdit: Sunting Penanda + desc: Berikan nama yang berarti, Anda juga dapat memasukkan tombol pintas suatu bentuk (yang dapat Anda buat disini) + + markerDemoLimit: + desc: Anda hanya dapat memuat dua penanda pada versi demo. Dapatkan versi penuh untuk penanda-penanda tak terhingga! + + exportScreenshotWarning: + title: Ekspor Tangkapan Layar + desc: Anda meminta untuk mengekspor pangkalan pusat Anda sebagai tangkapan layar. Harap ketahui bahwa ini bisa menjadi lambat untuk pangkalan pusat yang besar dan bahkan dapat membuat permainan Anda mogok! + +ingame: + # This is shown in the top left corner and displays useful keybindings in + # every situation + keybindingsOverlay: + moveMap: Pindahkan + selectBuildings: Pilih area + stopPlacement: Hentikan peletakan + rotateBuilding: Putar bangunan + placeMultiple: Letakkan beberapa + reverseOrientation: Balik orientasi + disableAutoOrientation: Nonaktifkan orientasi otomatis. + toggleHud: Ganti HUD + placeBuilding: Letakan bangunan + createMarker: Ciptakan penanda + delete: Hapus + pasteLastBlueprint: Sisipkan cetak biru terakhir + lockBeltDirection: Aktifkan perencana sabuk konveyor + plannerSwitchSide: Balik sisi perencana + cutSelection: Pindahkan + copySelection: Gandakan + clearSelection: Hapus seleksi + pipette: Pipet + switchLayers: Ganti lapisan + + # Names of the colors, used for the color blind mode + colors: + red: Merah + green: Hijau + blue: Biru + yellow: Kuning + purple: Ungu + cyan: Biru kehijauan + white: Putih + black: Hitam + uncolored: Abu-abu + + # Everything related to placing buildings (I.e. as soon as you selected a building + # from the toolbar) + buildingPlacement: + # Buildings can have different variants which are unlocked at later levels, + # and this is the hint shown when there are multiple variants available. + cycleBuildingVariants: Tekan untuk ganti varian. + + # Shows the hotkey in the ui, e.g. "Hotkey: Q" + hotkeyLabel: >- + Hotkey: + + infoTexts: + speed: Kecepatan + range: Rentang + storage: Penyimpanan + oneItemPerSecond: satu artikel / detik + itemsPerSecond: artikel / detik + itemsPerSecondDouble: (x2) + + tiles: ubin + + # The notification when completing a level + levelCompleteNotification: + # is replaced by the actual level, so this gets 'Level 03' for example. + levelTitle: Level + completed: Selesai + unlockText: Membuka ! + buttonNextLevel: Level Selanjutnya + + # Notifications on the lower right + notifications: + newUpgrade: Tingkatan baru tersedia! + gameSaved: Permainan Anda telah disimpan. + + # The "Upgrades" window + shop: + title: Tingkatan-tingkatan + buttonUnlock: Tingkatkan + + # Gets replaced to e.g. "Tier IX" + tier: Tingkat + + # The roman number for each tier + tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] + + maximumLevel: LEVEL MAKSIMUM (Kecepatan x) + + # The "Statistics" window + statistics: + title: Statistika + dataSources: + stored: + title: Tersimpan + description: Menunjukan jumlah bentuk-bentuk yang tersimpan pada bangunan pusat Anda. + produced: + title: Terproduksi + description: Menunjukkan semua bentuk yang diproduksi seluruh pabrik Anda, termasuk produk-produk antara. + delivered: + title: Terkirim + description: Menunjukkan bentuk-bentuk yang telah terkirim ke bangunan pusat Anda. + noShapesProduced: Sejauh ini belum diproduksi. + + # Displays the shapes per minute, e.g. '523 / m' + shapesPerMinute: / m + + # Settings menu, when you press "ESC" + settingsMenu: + playtime: Waktu bermain + + buildingsPlaced: Bangunan + beltsPlaced: Sabuk konveyor + + buttons: + continue: Lanjutkan + settings: Pengaturan + menu: Kembali ke menu + + # Bottom left tutorial hints + tutorialHints: + title: Butuh bantuan? + showHint: Tampilkan petunjuk + hideHint: Tutup + + # When placing a blueprint + blueprintPlacer: + cost: Biaya + + # Map markers + waypoints: + waypoints: Penanda + hub: PUSAT + description: Klik tombol kiri tetikus pada penanda untuk melompat kepadanya, klik tombol kanan untuk menghapusnya.

Tekan untuk membuat penanda dari sudut pandang saat ini, atau klik tombol kanan untuk membuat penanda pada lokasi yang dipilih. + creationSuccessNotification: Penanda telah dibuat. + + # Shape viewer + shapeViewer: + title: Lapisan-lapisan + empty: Kosong + copyKey: Gandakan tombol + + # Interactive tutorial + interactiveTutorial: + title: Penuntun + hints: + 1_1_extractor: Letakkan ekstraktor diatas bentuk lingkaran untuk mengekstrak bentuk tersebut! + 1_2_conveyor: >- + Hubungkan ekstraktor dengan sabuk konveyor ke pusat pangkalan Anda!

Kiat: Klik dan seret sabuk konveyor dengan tetikus! + + 1_3_expand: >- + Ini BUKAN permainan menganggur! Bangun lebih banyak ekstraktor dan sabuk konveyor untuk menyelesaikan obyektif dengan lebih cepat.

Kiat: Tahan tombolSHIFT untuk meletakkan beberapa ekstraktor, dan gunakan tombol R untuk memutar. + +# All shop upgrades +shopUpgrades: + belt: + name: Sabuk konveyor, Pembagi Arus & Terowongan + description: Kecepatan x → x + miner: + name: Ekstraksi + description: Kecepatan x → x + processors: + name: Memotong, Memutar & Menyusun + description: Speed x → x + painting: + name: Mencampur & Mencat + description: Kecepatan x → x + +# Buildings and their name / description +buildings: + hub: + deliver: Kirim + toUnlock: untuk membuka + levelShortcut: LVL + + belt: + default: + name: &belt Sabuk Konveyor + description: Mengangkut artikel-artikel, tahan dan seret untuk meletakkan beberapa. + + wire: + default: + name: &wire Kawat Energi + description: Memungkinkan anda untuk mengangkut energi. + + miner: # Internal name for the Extractor + default: + name: &miner Ekstraktor + description: Letakkan diatas sumber bentuk atau warna untuk mengekstraksi mereka. + + chainable: + name: Ekstraktor (Berantai) + description: Letakkan di atas sumber bentuk atau warna untuk mengekstraksi mereka. Dapat dirantai. + + underground_belt: # Internal name for the Tunnel + default: + name: &underground_belt Terowongan + description: Memungkinkan Anda untuk mengangkut sumber-sumber daya dibawah bangunan-bangunan atau sabuk konveyor. + + tier2: + name: Terowongan Tingkat II + description: Memungkinkan Anda untuk mengangkut sumber-sumber daya dibawah bangunan-bangunan atau sabuk konveyor. + + splitter: # Internal name for the Balancer + default: + name: &splitter Pengimbang + description: Multifungsi – Mendistribusi secara merata semua masukan ke semua keluaran. + + compact: + name: Penggabung (Padat) + description: Menggabungkan dua sabuk konveyor menjadi satu. + + compact-inverse: + name: Penggabung (Padat) + description: Menggabungkan dua sabuk konveyor menjadi satu. + + cutter: + default: + name: &cutter Pemotong + description: Memotong bentuk-bentuk secara vertikal dan mengeluarkan kedua bagian. Apabila Anda hanya menggunakan satu bagian, pastikan Anda lenyapkan bagian lain atau mesin akan macet! + quad: + name: Pemotong (Empat Bagian) + description: Memotong bentuk-bentuk menjadi empat bagian. Apabila Anda hanya menggunakan satu bagian, pastikan Anda lenyapkan bagian-bagian lain atau mesin akan macet! + + advanced_processor: + default: + name: &advanced_processor Pembalik Warna + description: Menerima warna atau bentuk dan kemudian membaliknya. + + rotater: + default: + name: &rotater Pemutar + description: Memutar bentuk searah jarum jam sebesar 90 derajat. + ccw: + name: Pemutar (Berlawanan Arah Jarum Jam) + description: Memutar bentuk berlawanan arah jarum jam sebesar 90 derajat. + fl: + name: Pemutar (180) + description: Memutar bentuk sebesar 180 derajat. + + stacker: + default: + name: &stacker Penyusun + description: Menggabungkan kedua artikel. Apabila mereka tidak dapat digabungkan, artikel kanan akan diletakkan diatas artikel kiri. + + mixer: + default: + name: &mixer Pencampur Warna + description: Mencampurkan dua warna menggunakan campuran aditif. + + painter: + default: + name: &painter Pencat + description: &painter_desc Mencat keseluruhan bentuk dari input kiri dengan warna dari input atas. + mirrored: + name: *painter + description: *painter_desc + + double: + name: Pencat (Ganda) + description: Mencat bentuk-bentuk dari input kiri dengan warna dari input atas. + quad: + name: Pencat (Empat Bagian) + description: Memungkinkan Anda untuk mencat setiap kuadran bentuk dengan warna-warna berbeda. + + trash: + default: + name: &trash Tong Sampah + description: Menerima input dari semua sisi dan menghancurkannya. Selamanya. + + storage: + name: Penyimpanan + description: Menyimpan artikel-artikel berlebih, sampai kapasitas tertentu. Dapat dipergunakan sebagai gerbang luapan. + energy_generator: + deliver: Pengiriman + + # This will be shown before the amount, so for example 'For 123 Energy' + toGenerateEnergy: Untuk + + default: + name: &energy_generator Pembangkit Energi + description: Menciptakan energy dengan mengonsumsi bentuk-bentuk. + + wire_crossings: + default: + name: &wire_crossings Pembelah Kawat + description: Membelah satu kawat energy menjadi dua. + + merger: + name: Penggabung Kawat + description: Menggabungkan dua kawat energy menjadi satu. + +storyRewards: + # Those are the rewards gained from completing the store + reward_cutter_and_trash: + title: Memotong Bentuk + desc: Anda baru saja membuka pemotong - ia memotong bentuk-bentuk separuhnya dari atas ke bawah tanpa memperhatikan orientasinya!

Pastikan Anda membuang yang tidak terpakai, atau mesin akan macet - Untuk tujuan ini saya memberikan Anda tong sampah, yang menghancurkan semua yang anda masukkan kedalamnya! + + reward_rotater: + title: Memutar + desc: Pemutar telah dibuka! Ia memutar bentuk-bentuk searah jarum jam sebesar 90 derajat. + + reward_painter: + title: Pengecatan + desc: >- + Pencat telah dibuka – Ekstraksi beberapa warna (seperti yang Anda lakukan dengan bentuk) dan kemudian kombinasikan dengan bentuk di dalam pencat untuk mewarnai mereka!

Catatan: Apabila Anda buta warna, terdapat mode buta warna di dalam pengaturan! + + reward_mixer: + title: Pencampuran Warna + desc: Pencampur telah dibuka – Kombinasikan dua warna menggunakan pencampuran aditif dengan bangunan ini! + + reward_stacker: + title: Penyusun + desc: Anda sekarang dapat mengombinasikan bentuk-bentuk dengan penyusun! Kedua input akan dikombinasikan, dan apabila mereka dapat diletakan disebelah satu sama lain, mereka akan terpadukan. Apabila tidak dapat, input kanan akan diletakkan diatas input kiri! + + reward_splitter: + title: Pembagi/Penggabung + desc: Pengimbang multifungsi telah dibuka – Ia dapat digunakan untuk membangun pabrik yang lebih besar dengan membagi dan menggabungkan artikel-artikel ke berbagai sabuk konveyor!

+ + reward_tunnel: + title: Terowongan + desc: Terowongan telah dibuka – Sekarang Anda dapat memindahkan artikel-artikel melalui terowongan di bawah sabuk-sabuk konveyor dan bangungan-bangunan dengannya! + + reward_rotater_ccw: + title: Memutar Berlawanan Arah Jarum Jam + desc: Anda telah membuka varian dari Pemutar - Ia memungkinkan Anda untuk memutar bentuk-bentuk berlawanan arah jarum jam! Untuk membangunnya, pilih pemutar dan tekan 'T' to memilih varian! + + reward_miner_chainable: + title: Merantai Ekstraktor + desc: Anda telah membuka ekstraktor rantai! Ia dapat meneruskan sumberdaya ekstraksinya ke ekstraktor selanjutnya sehingga Anda dapat mengekstraksi dengan lebih efisien! + + reward_underground_belt_tier_2: + title: Terowongan Tingkat II + desc: Anda telah membuka varian baru terowongan - Ia memiliki jangkauan yang lebih panjang, dan sekarang Anda juga dapat memadukan terowongan-terowongan tersebut! + + reward_splitter_compact: + title: Pengimbang Padat + desc: >- + Anda telah membuka varian padat dari pengimbang - Ia menerima dua input dan menggabungkannya ke dalam satu konveyor! + + reward_cutter_quad: + title: Pemotongan Empat Bagian + desc: Anda telah membuka varian dari pemotong - Ia memungkinkan Anda memotong bentuk-bentuk ke dalam empat bagian daripada hanya dua bagian! + + reward_painter_double: + title: Pengecatan Ganda + desc: Anda telah membuka varian dari pencat - Ia bekerja seperti pencat biasa namun dapat memproses dua bentuk sekaligus mengonsumsi hanya satu warna daripada dua! + + reward_painter_quad: + title: Pengecatan Empat Bagian + desc: Anda telah membuka varian dari pencat - Ia memungkinkan Anda untuk mencat setiap bagian dari masing-masing bentuk sendiri-sendiri! + + reward_storage: + title: Penyangga Penyimpanan + desc: Anda telah membuka varian dari tong sampah - Ia memungkinkan Anda untuk menyimpan artikel-artikel sebanyak kapasitas tertentu! + + reward_freeplay: + title: Permainan Bebas + desc: Anda berhasil! Anda telah membuka mode permainan bebas! Ini berarti sekarang bentuk-bentuk akan dihasilkan secara acak! (Jangan khawatir, lebih banyak konten akan direncanakan untuk versi penuh!) + + reward_blueprints: + title: Cetak Biru + desc: Anda sekarang dapat menyalin dan meletakkan bagian dari pabrik Anda! Pilih sebuah area (tahan CTRL, lalu seret dengan tetikus), dan tekan 'C' untuk menggandakannya.

Untuk meletakannya tidak gratis, Anda harus memproduksi bentuk cetak biru untuk dapat melakukannya! (Bentuk yang baru saja anda kirim). + + # Special reward, which is shown when there is no reward actually + no_reward: + title: Level Selanjutnya + desc: >- + Level ini tidak memiliki hadiah, namun yang selanjutnya akan!

Catatan: Sebaiknya Anda jangan hancurkan pabrik yang telah ada – Anda membutuhkan semua bentuk-bentuk tersebut lagi nanti untuk membuka tingkatan-tingkatan selanjutnya! + + no_reward_freeplay: + title: Level Selanjutnya + desc: >- + Selamat! Omong-omong, lebih banyak konten telah direncanakan untuk versi penuh! + +settings: + title: Pengaturan + categories: + general: Umum + userInterface: Antarmuka Pengguna + advanced: Tingkat Tinggi + + versionBadges: + dev: Pengembangan + staging: Pementasan + prod: Produksi + buildDate: Dibangun + + labels: + uiScale: + title: Skala Antarmuka + description: >- + Ganti ukuran antarmuka pengguna. Antarmuka tetap akan berskalakan berdasar resolusi peralatan Anda, tetapi pengaturan ini mengontrol besar skala. + scales: + super_small: Sangat kecil + small: Kecil + regular: Reguler + large: Besar + huge: Sangat besar + + autosaveInterval: + title: Jeda Penyimpanan Otomatis + description: >- + Mengatur seberapa sering permainan menyimpan secara otomatis. Anda juga dapat menonaktifkannya sama sekali disini. + + intervals: + one_minute: 1 Menit + two_minutes: 2 Menit + five_minutes: 5 Menit + ten_minutes: 10 Menit + twenty_minutes: 20 Menit + disabled: Dinonaktifkan + + scrollWheelSensitivity: + title: Kepekaan perbesaran + description: >- + Mengubah seberapa peka perbesaran yang dilakukan (baik dengan roda tetikus atau trackpad). + sensitivity: + super_slow: Sangat lambat + slow: Lambat + regular: Reguler + fast: Cepat + super_fast: Sangat cepat + + movementSpeed: + title: Kecepatan gerakan + description: >- + Mengubah seberapa cepat pandangan bergerak ketika menggunakan papan ketik. + speeds: + super_slow: Sangat lambat + slow: Lambat + regular: Reguler + fast: Cepat + super_fast: Sangat cepat + extremely_fast: Luar biasa cepat + + language: + title: Bahasa + description: >- + Ganti bahasa. Semua terjemahan adalah contribusi pengguna dan mungkin saja tidak lengkap! + + enableColorBlindHelper: + title: Mode buta warna + description: >- + Mengaktifkan berbagai peralatan yang memungkinkan Anda bermain apabila Anda buta warna. + + fullscreen: + title: Layar penuh + description: >- + Direkomendasikan untuk bermain dengan layar penuh untuk mendapatkan pengalaman terbaik. Hanya tersedia dalam versi penuh. + + soundsMuted: + title: Bisukan suara + description: >- + Apabila diaktifkan, membisukan semua efek suara. + + musicMuted: + title: Bisukan musik + description: >- + Apabila diaktifkan, membisukan semua musik. + + theme: + title: Tema permainan + description: >- + Pilih tema permainan (terang/gelap). + themes: + dark: Gelap + light: Terang + + refreshRate: + title: Target Simulasi + description: >- + Apabila Anda memiliki monitor 144hz, ganti laju penyegaran sehingga permainan dapat disimulasikan dengan benar pada laju yang lebih tinggi. Ini mungkin saja mengurangi laju bingkai per detik (frames per second) apabila computer anda terlalu lambat. + + alwaysMultiplace: + title: Peletakkan berganda + description: >- + Apabila diaktifkan, semua bangunan akan tetap terpilih setelah penempatan sampai Anda membatalkannya. Ini sama saja dengan menahan tombol SHIFT secara permanen. + + offerHints: + title: Petunjuk & penuntun + description: >- + Apakah akan menawarkan petunjuk dan penuntun ketika bermain. Juga menyembunyikan elemen-elemen antarmuka pengguna (user interface) tertentu sampai level tertentu untuk membuat lebih mudah untuk bermain. + + enableTunnelSmartplace: + title: Terowongan cerdas + description: >- + Ketika diaktifkan, proses penempatan terowongan akan menghapus konveyor yang tidak berguna secara otomatis. Ini juga memungkinkan Anda untuk menyeret terowongan dan kelebihan terowongan akan dihilangkan. + + vignette: + title: Vinyet + description: >- + Mengaktifkan vinyet, yang menggelapkan sudut-sudut layar dan membuat teks lebih mudah dibaca. + + rotationByBuilding: + title: Pemutaran masing-masing tipe bangunan + description: >- + Setiap tipe bangunan mengingat putaran yang Anda tetapkan kepadanya. Ini mungkin lebih nyaman apabila Anda sering berganti untuk menempatkan berbagai tipe bangunan. + + compactBuildingInfo: + title: Pemadatan informasi banguna + description: >- + Memendekkan kotak-kotak informasi bangunan-bangunan dengan hanya menampilkan rasionya. Jika tidak, deskripsi dan gambar ditampilkan. + + disableCutDeleteWarnings: + title: Nonaktifkan peringatan pemindahan/penghapusan + description: >- + Menonaktifkan peringatan yang muncul ketikan pemindahkan/menghapus lebih dari 100 entitas. + +keybindings: + title: Tombol pintas + hint: >- + Petunjuk: Pastikan Anda menggunakan CTRL, SHIFT and ALT! Mereka memungkinkan berbagai opsi penempatan. + + resetKeybindings: Setel Ulang Tombol Pintas + + categoryLabels: + general: Aplikasi + ingame: Permainan + navigation: Navigasi + placement: Penempatan + massSelect: Pemilihan massal + buildings: Tombol pintas bangunan + placementModifiers: Pengubah penempatan + + mappings: + confirm: Konfirmasi + back: Kembali + mapMoveUp: Geser ke atas + mapMoveRight: Geser ke kanan + mapMoveDown: Geser ke bawah + mapMoveLeft: Geser ke kiri + mapMoveFaster: Geser lebih cepat + centerMap: Pusat peta + + mapZoomIn: Perbesar + mapZoomOut: Perkecil + createMarker: Buat penanda + + menuOpenShop: Tingkatan-tingkatan + menuOpenStats: Statistik + menuClose: Tutup menu + + toggleHud: Alihkan HUD + toggleFPSInfo: Alihkan laju bingkan per detik (frame per second) dan informasi debug + switchLayers: Ganti lapisan + exportScreenshot: Ekspor keseluruhan pangkalan pusat sebagai gambar + belt: *belt + splitter: *splitter + underground_belt: *underground_belt + miner: *miner + cutter: *cutter + advanced_processor: *advanced_processor + rotater: *rotater + stacker: *stacker + mixer: *mixer + energy_generator: *energy_generator + painter: *painter + trash: *trash + wire: *wire + + pipette: Pipet + rotateWhilePlacing: Putar + rotateInverseModifier: >- + Modifier: Putar berlawanan arah jarum jam sebagai gantinya + cycleBuildingVariants: Ganti varian + confirmMassDelete: Hapus area + pasteLastBlueprint: Gandakan cetak biru terakhir + cycleBuildings: Ganti bangunan + lockBeltDirection: Aktifkan perencana konveyor + switchDirectionLockSide: >- + Planner: Alih sisi + + massSelectStart: Tahan dan seret untuk memulai + massSelectSelectMultiple: Pilih berbagai area + massSelectCopy: Gandakan area + massSelectCut: Pindahkan area + + placementDisableAutoOrientation: Nonaktifkan orientasi otomatis + placeMultiple: Tinggal di mode penempatan + placeInverse: Balikkan orientasi otomatis konveyor + +about: + title: Tentang permainan ini + body: >- + Permainan ini bekerja secara open source dan dikembangkan oleh Tobias Springer (ini adalah saya).

+ + Apabila Anda ingin berkontribusi, periksa shapez.io di github.

+ + Permainan ini tidak mungkin ada tanpa komunitas Discord di sekitar permainan saya – Anda hendaknya bergabung server Discord!

+ + Lagunya dibuat oleh Peppsen - Dia mengagumkan.

+ + Akhirnya, banyak terima kasih kepada teman baik saya Niklas - Tanpa sesi-sesi factorio kami, permainan ini tidak mungkin tercipta. + +changelog: + title: Catatan Perubahan + +demo: + features: + restoringGames: Mengembalikan simpanan permainan + importingGames: Memasukkan simpanan permainan + oneGameLimit: Terbatas pada satu simpanan permainan + customizeKeybindings: Sesuaikan tombol-tombol pintas + exportingBase: Mengekspor keseluruhan pangkalan pusat sebagai gambar + + settingNotAvailable: Tidak tersedia dalam versi demo. diff --git a/translations/base-it.yaml b/translations/base-it.yaml index a9e88aa4..5b48402a 100644 --- a/translations/base-it.yaml +++ b/translations/base-it.yaml @@ -15,10 +15,11 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: In shapez.io potrai costruire delle fabbriche per automatizzare la creazione e la combinazione di forme sempre più complesse, in una mappa infinita. @@ -30,72 +31,76 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + In shapez.io potrai costruire delle fabbriche per automatizzare la creazione e la combinazione di forme sempre più complesse, in una mappa infinita. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Una volta che avrai consegnato le forme richieste, progredirai nel gioco e sbloccherai dei miglioramenti per rendere la tua fabbrica più veloce. - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Per rispondere alla crescente richiesta di forme, dovrai ingrandire la tua fabbrica - Non dimenticarti delle risorse, però; dovrai espanderti attraverso la [b]mappa infinita[/b]! - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Presto dovrai mescolare colori e usarli per verniciare le tue forme - Combina le risorse dei colori rosso, verde e blu per produrre colori differenti, verniciare le forme con essi e soddisfare la richiesta. - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + Nel gioco sono presenti 18 livelli progressivi (Che già dovrebbero tenerti occupato per ore) Ma sto costantemente aggiungendo nuovi contenuti - C'è molto in programma! - [b]Standalone Advantages[/b] + Acquistare il gioco ti darà accesso alla versione standalone, con caratteristiche aggiuntive e l'accesso ai nuovi contenuti sviluppati. + + [b]Vantaggi della versione completa[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Modalità scura + [*] Segnapunti illimitati + [*] Salvataggi illimitati + [*] Opzioni aggiuntive + [*] In arrivo: Cavi ed energia! Previsti (approssimativamente) per la fine di Luglio 2020. + [*] Coming soon: Più livelli + [*] Mi consente di svillupare ulteriormente shapez.io ❤️ [/list] - [b]Future Updates[/b] + [b]Aggiornamenti futuri[/b] - I am updating the game very often and trying to push an update at least every week! + Sto aggiornando il gioco molto di frequente e cerco di pubblicare un nuovo aggiornamento almeno una volta a settimana. [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Mappe diverse e sfide (ad esempio mappe con ostacoli) + [*] Rompicapi (Consegna la forma richiesta utilizzando un'area limitata o un insieme ristretto di edifici) + [*] Una modalità storia in cui gli edifici hanno un costo. + [*] Generatore della mappa configurabile (Configura dimensione e densità delle forme/risorse, seed e altro) + [*] Tipi di forma aggiuntivi. + [*] Miglioramenti delle prestazioni (Il gioco funziona già piuttosto bene!) + [*] E molto altro! [/list] - [b]This game is open source![/b] + [b]Questo gioco è open source![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Chiunque può contribuire, interagisco attivamente con la community, cerco leggere tutti i suggerimenti e tengo in considerazione i feedback quando possibile. + Visita la mia pagina su trello per la tabella di marcia completa! [b]Links[/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Server ufficiale Discord[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Tabella di marcia[/url] [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://github.com/tobspr/shapez.io]Codice sorgente(GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Aiuto per le traduzioni[/url] [/list] - discordLink: Official Discord - Chat with me! + discordLink: Server ufficiale Discord - Chatta con me! global: loading: Caricamento error: Errore # How big numbers are rendered, e.g. "10,000" - thousandsDivider: "," + thousandsDivider: "'" + + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "," # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k millions: M - billions: B + billions: G trillions: T # Shown for infinitely big numbers @@ -131,7 +136,7 @@ demoBanners: # This is the "advertisement" shown in the main menu and other various places title: Versione Demo intro: >- - Ottieni la versione standalone per sbloccare tutte le funzioni! + Ottieni la versione completa per sbloccare tutte le funzioni! mainMenu: play: Play @@ -143,12 +148,11 @@ mainMenu: # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - Ci spiace, ma il gioco è molto lento su questo browser! Ottieni la versione standalone oppure scarica Chrome per provare l'esperienza completa. + Ci spiace, ma il gioco è molto lento su questo browser! Ottieni la versione completa oppure scarica Chrome per l'intera esperienza. savegameLevel: Livello savegameLevelUnknown: Livello sconosciuto - continue: Continua newGame: Nuova partita madeBy: Creato da @@ -160,12 +164,12 @@ dialogs: delete: Elimina cancel: Annulla later: Più tardi - restart: Ricomincia + restart: Riavvia reset: Reset getStandalone: Ottieni la versione completa deleteGame: So cosa sto facendo viewUpdate: Mostra aggiornamento - showUpgrades: Mostra upgrade + showUpgrades: Mostra miglioramenti showKeybindings: Mostra scorciatoie importSavegameError: @@ -196,42 +200,43 @@ dialogs: restartRequired: title: Restart richiesto text: >- - Per applicare le nuove impostazioni è necessario il Restart del gioco. + Per applicare le nuove impostazioni è necessario riavviare del gioco. editKeybinding: title: Cambia comandi - desc: Premi un nuovo tasto o un tasto del mouse a cui vuoi assegnare questo comando, Esc per cancellarlo. + desc: Premi un nuovo tasto o un tasto del mouse a cui vuoi assegnare questo comando, Esc per annullare. resetKeybindingsConfirmation: title: Reset comandi assegnati - desc: Così riporterai tutti comandi al loro stato di default. Perfavore conferma. + desc: Così riporterai tutti comandi al loro stato predefinto. Per favore conferma. + keybindingsResetOk: title: Successo nel reset dei comandi - desc: I comandi sono stati riassegnati ai loro rispettivi comandi di default! + desc: I comandi predefiniti sono stati ripristinati! featureRestriction: title: Versione Demo - desc: Hai provato ad accedere ad una feature () che non è disponibile nella Demo. Considera di prendere la versione standalne per un'esperienza completa! + desc: Hai provato ad accedere ad una caratteristica () che non è disponibile nella Demo. Considera di prendere la versione completa per l'intera esperienza! oneSavegameLimit: title: Salvataggi limitati - desc: Puoi avere solo un salvataggio nella versione Demo. Perfavore rimuovi il salvataggio già esistente o prendi la versione standalone! + desc: Puoi avere solo un salvataggio nella versione Demo. Perfavore rimuovi il salvataggio già esistente o prendi la versione completa! updateSummary: - title: Nuovo update! + title: Nuovo aggiornamento! desc: >- Qui puoi trovare i cambiamenti dall'ultima volta che hai giocato: upgradesIntroduction: - title: Aggiornamenti sbloccati + title: Miglioramenti sbloccati desc: >- Tutte le forme che produci possono essere utilizzate per i miglioramenti - Non distruggere le tue vecchie fabbriche! - Puoi trovare gli aggiornamenti nell'angolo in alto a destra dello schermo. + Puoi trovare i miglioramenti nell'angolo in alto a destra dello schermo. massDeleteConfirm: title: Conferma la rimozione desc: >- - Stai rimuovendo molte strutture ( to be exact)! + Stai rimuovendo molte strutture ( per essere precisi)! Sei sicuro di volerlo fare? blueprintsNotUnlocked: @@ -243,33 +248,33 @@ dialogs: title: Comandi utili desc: >- Questo gioco ha molti comandi utili che possono rendere più semplice la costruzione delle fabbriche. - Qui ce ne sono un paio, ma sii sicuro controlla i comandi!

+ Qui ce ne sono un paio, ma dovresti controllare i comandi!

CTRL + Drag: Seleziona l'area da copiare / cancella.
- SHIFT: Tieni premuto per costruire copie dalla struttura.
- ALT: Invert l'orientamento dei nastri trasportatori.
+ SHIFT: Tieni premuto per costruire copie dell'edificio.
+ ALT: Inverti l'orientamento dei nastri trasportatori.
createMarker: - title: Nuovo Marker - desc: Dagli un magnifico nome, puoi anche includere short key di una figura (Che puoi generare here) - titleEdit: Edit Marker + title: Nuovo segnapunto + desc: Dagli un nome con un significato, puoi anche includere il codice di una figura (Che puoi generare qui) + titleEdit: Modifica segnapunto markerDemoLimit: - desc: Puoi creare solo due Marker personalizzati nella Demo. Prendi la versione standalone per Marker personalizzati illimitati! + desc: Puoi creare solo due segnapunti personalizzati nella Demo. Ottieni la versione completa per avere segnapunti personalizzati illimitati! massCutConfirm: title: Conferma taglio desc: >- - Stai tagliando molte strutture ( to be exact)! + Stai tagliando molte strutture ( per essere precisi)! Sei sicuro di volerlo fare? exportScreenshotWarning: title: Esportare screenshot desc: >- Hai richiesto di esportare la tua base come screenshot. Perfavore tieni conto che potrebbe - essere lento per una grossa base e che potrebbe crushare il gioco! + essere lento per una grossa base e che potrebbe causare il crash del gioco! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + title: Conferma taglia + desc: Non puoi permetterti di incollare quest'area! Sei sicuro di volerla tagliare? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -278,23 +283,22 @@ ingame: moveMap: Sposta selectBuildings: Seleziona area stopPlacement: Concludi posizionamento - rotateBuilding: Ruota costruzione + rotateBuilding: Ruota edificio placeMultiple: Posiziona multiplo reverseOrientation: Inverti orientamento disableAutoOrientation: Disabilita orientamento automatico toggleHud: Mostra/Nascondi HUD placeBuilding: Posiziona costruzione createMarker: Crea etichetta - delete: Distruggi - pasteLastBlueprint: Paste last blueprint - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side + delete: Cancella + pasteLastBlueprint: Incolla l'ultimo progetto + lockBeltDirection: Attiva pianificatore nastri + plannerSwitchSide: Cambia direzione pianificatore cutSelection: Taglia copySelection: Copia clearSelection: Annulla selezione pipette: Contagocce - switchLayers: Switch layers - + switchLayers: Cambia livello # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) buildingPlacement: @@ -314,47 +318,48 @@ ingame: itemsPerSecond: oggetti / s itemsPerSecondDouble: (x2) - tiles: titles + tiles: caselle # The notification when completing a level levelCompleteNotification: # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Livello completed: Completato - unlockText: Sbloccato ! + unlockText: >- + Sbloccato: ! buttonNextLevel: Prossimo livello # Notifications on the lower right notifications: - newUpgrade: U nuovo aggiornamento è disponibile! - gameSaved: La tua partita è stata salvata. + newUpgrade: È disponibile un nuovo aggiornamento! + gameSaved: Partita salvata. # The "Upgrades" window shop: - title: Aggiornamenti + title: Miglioramenti buttonUnlock: Sblocca # Gets replaced to e.g. "Tier IX" - tier: Tier + tier: Grado # The roman number for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: LIVELLO MASSIMO (Speed x) + maximumLevel: GRADO MASSIMO (Velocità x) # The "Statistics" window statistics: title: Statistiche dataSources: stored: - title: Immagazzinati - description: Displaying amount of stored shapes in your central building. + title: Immagazzinate + description: Mostra il numero di forme immagizzinate nell'edificio centrale. produced: - title: Prodotti - description: Displaying all shapes your whole factory produces, including intermediate products. + title: Prodotte + description: Mostra tutte le forme prodotte dalla tua fabbrica, inclusi i prodotti intermedi. delivered: - title: Delivered - description: Displaying shapes which are delivered to your central building. + title: Consegnate + description: Mostra le forme che vengono consegnate all'edificio centrale. noShapesProduced: No shapes have been produced so far. # Displays the shapes per minute, e.g. '523 / m' @@ -364,7 +369,7 @@ ingame: settingsMenu: playtime: Tempo di gioco - buildingsPlaced: Buildings + buildingsPlaced: Edifici beltsPlaced: Nastri buttons: @@ -384,50 +389,50 @@ ingame: # Map markers waypoints: - waypoints: Markers + waypoints: Segnapunti hub: HUB - description: Left-click a marker to jump to it, right-click to delete it.

Press to create a marker from the current view, or right-click to create a marker at the selected location. - creationSuccessNotification: Marker has been created. + description: Click sinistro su un segnapunto per raggiungerlo, click destro per cancellarlo.

Premi per creare un segnapunto dalla visuale corrente, oppure click destro per creare un segnapunto nella posizione selezionata. + creationSuccessNotification: Il segnapunto è stato creato. # Interactive tutorial interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! + 1_1_extractor: Posiziona un estrattore sopra una forma circolare per estrarla! 1_2_conveyor: >- - Connect the extractor with a conveyor belt to your hub!

Tip: Click and drag the belt with your mouse! + Connetti l'estrattore all'Hub centrale utilizzando un nastro trasportatore!

Suggerimento: Clicca e trascina il nastro con il mouse! 1_3_expand: >- - This is NOT an idle game! Build more extractors and belts to finish the goal quicker.

Tip: Hold SHIFT to place multiple extractors, and use R to rotate them. + Questo NON è un idle game! Costruisci più estrattori e nastri per raggiungere l'obiettivo più velocemente.

Suggerimento: Tieni premuto MAIUSC per piazzare estrattori multipli, e usa R per ruotarli. colors: red: Rosso green: Verde blue: Blu yellow: Giallo - purple: Viola + purple: Magenta cyan: Azzurro white: Bianco uncolored: No colore - black: Black + black: Nero shapeViewer: - title: Livelli + title: Strati empty: Vuoto - copyKey: Copy Key + copyKey: Copia codice # All shop upgrades shopUpgrades: belt: - name: Belts, Distributor & Tunnels + name: Nastri, distribuzione e tunnel description: Velocità x → x miner: name: Estrazione description: Velocità x → x processors: - name: Cutting, Rotating & Stacking + name: Taglio, rotazione e impilamento description: Velocità x → x painting: - name: Mixing & Painting + name: Mix e verniciatura description: Velocità x → x # Buildings and their name / description @@ -470,24 +475,27 @@ buildings: cutter: default: - name: &cutter Cutter - description: Cuts shapes from top to bottom and outputs both halfs. If you use only one part, be sure to destroy the other part or it will stall! + name: &cutter Tagliatrice + description: Taglia le forme verticalmente e restituisce le metà destra e sinistra. Se usi solo una parte, distruggi l'altra o la macchina si fermerà! quad: - name: Cutter (Quad) - description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other part or it will stall! + name: Tagliatrice (4x) + description: Taglia le forme in quattro parti. Se usi solo una parte, distruggi le altre o la macchina si fermerà! rotater: default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. + name: &rotater Ruotatrice + description: Ruota le forme di 90 gradi in senso orario. ccw: - name: Rotate (CCW) - description: Rotates shapes counter clockwise by 90 degrees. + name: Ruotatrice (Ant.) + description: Ruota le forme di 90 gradi in senso antiorario. + fl: + name: Ruotatrice (180) + description: Ruota le forme di 180 gradi. stacker: default: - name: &stacker Stacker - description: Stacks both items. If they can not be merged, the right item is placed above the left item. + name: &stacker Impilatrice + description: Unisce o impila i due oggetti, se gli oggetti non possono essere uniti, l'oggetto destro è posizionato sopra il sinstro. mixer: default: @@ -496,14 +504,14 @@ buildings: painter: default: - name: &painter Verniciatore - description: &painter_desc Colora l'intera forma dell'ingresso sinistro con il colore dell'ingresso destro. + name: &painter Verniciatrice + description: &painter_desc Colora l'intera forma dall'ingresso sinistro con il colore dall'ingresso destro. double: - name: Verniciatore (Doppio) - description: Colors the shapes on the left inputs with the color from the top input. + name: Verniciatrice (2x) + description: Colora le forme dagli ingressi sinistri con il colore dall'ingresso destro. quad: - name: Verniciatore (Quadruplo) - description: Allows to color each quadrant of the shape with a different color. + name: Verniciatrice (4x) + description: Consente di colorare ogni quadrante della forma con un colore diverso. mirrored: name: *painter description: *painter_desc @@ -511,155 +519,158 @@ buildings: trash: default: name: &trash Cestino - description: Accetta ingressi da tutti i lati e li distrugge. per sempre. + description: Accetta oggetti da tutti i lati e li distrugge. Per sempre. storage: - name: Storage - description: Stores excess items, up to a given capacity. Can be used as an overflow gate. + name: Stoccaggio + #Literal translation, quite ugly, might need rephrasing + description: Immagazzina gli oggetti in eccesso, fino ad una certa capacità. Può essere usato come varco per le eccedenze hub: deliver: Consegna toUnlock: per sbloccare levelShortcut: LVL wire: default: - name: Energy Wire - description: Allows you to transport energy. + name: Cavo energetico + description: Ti consente di trasportare energia. advanced_processor: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + name: Invertitore di colori + description: Accetta un colore o una forma e li inverte. energy_generator: - deliver: Deliver - toGenerateEnergy: For + deliver: Consegna + toGenerateEnergy: per generare default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: Generatore di energia + description: Genera energia consumando forme. wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Separatore cavi + description: Divide un cavo energetico in due. merger: - name: Wire Merger - description: Merges two energy wires into one. + name: Giunzione cavi + description: Unisce due cavi energetici in uno. storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: - title: Cutting Shapes - desc: You just unlocked the cutter - it cuts shapes half from top to bottom regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will stall - For this purpose I gave you a trash, which destroys everything you put into it! + title: Taglio forme + desc: Hai appena sbloccato la tagliatrice - taglia le forme verticalmente indipendentemente da come è orientata!

Elimina gli scarti, o altrimenti si bloccherà - A questo scopo ti ho dato un cestino, che distrugge qualsiasi cosa tu metta dentro! reward_rotater: - title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. + title: Rotazione + desc: La ruotatrice è stata sbloccata! Ruota le forme di 90 gradi in senso orario. reward_painter: - title: Painting + title: Verniciatura desc: >- - The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, there is a color blind mode in the settings! + La verniciatrice è stata sbloccata - Estrai dalle vene colorate (esattamente come fai con le forme) e combina il colore con una forma nella veniciatrice per colorarla!

PS: Se sei daltonico, c'è la modalità daltonici nelle opzioni! reward_mixer: - title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! + title: Mix colori + desc: Il mixer è stato sbloccato - Con questo edificio, puoi combinare due colori mediante sintesi additiva! - reward_stacker: - title: Combiner - desc: You can now combine shapes with the combiner! Both inputs are combined, and if they can be put next to each other, they will be fused. If not, the right input is stacked on top of the left input! + rreward_stacker: + title: Impilatrice + desc: >- + Ora puoi unire forme con l'impilatrice! Le forme in ingresso vengono combinate: se possono essere poste l'una accanto all'altra verranno fuse, altrimenti le forme dall'ingresso destro vengono impilate sopra quelle dal sinistro! reward_splitter: - title: Splitter/Merger - desc: The multifunctional balancer has been unlocked - It can be used to build bigger factories by splitting and merging items onto multiple belts!

+ title: Separatore/Agrregatore + desc: Il bilanciatore multifunzione è stato sbloccato - Può essere usato per costruire fabbriche più grandi unendo o dividendo gli oggetti tra diversi nastri!

reward_tunnel: title: Tunnel - desc: The tunnel has been unlocked - You can now pipe items through belts and buildings with it! + desc: Il tunnel è stato sbloccato - In questo modo puoi trasportare oggetti al di sotto di nastri ed edifici! reward_rotater_ccw: - title: CCW Rotating - desc: You have unlocked a variant of the rotater - It allows to rotate counter clockwise! To build it, select the rotater and press 'T' to cycle its variants! + title: Rotazione antioraria + desc: Hai sbloccato una variante della ruotatrice - Consente di ruotare in senso antiorario! Per costruirla, seleziona la ruotatrice e premi 'T' per cambiare variante! reward_miner_chainable: - title: Chaining Extractor - desc: You have unlocked the chaining extractor! It can forward its resources to other extractors so you can more efficiently extract resources! + title: Estrattore a catena + desc: Hai sbloccato l'estrattore a catena! Può trasferire le sue risorse ad altri estrattori, così puoi estrarre risorse in modo più efficiente! reward_underground_belt_tier_2: - title: Tunnel Tier II - desc: You have unlocked a new variant of the tunnel - It has a bigger range, and you can also mix-n-match those tunnels now! + title: Tunnel grado II + desc: Hai sbloccato una nuova variante del tunnel - Ha un raggio più ampio e puoi anche mischiare le due varianti ora! reward_splitter_compact: - title: Compact Balancer + title: Bilanciatore compatto desc: >- - You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one! + Hai sbloccato una variante compatta del bilanciatore - Accetta due ingressi e li unisce! reward_cutter_quad: - title: Quad Cutting - desc: You have unlocked a variant of the cutter - It allows you to cut shapes in four parts instead of just two! + title: Taglio quadruplo + desc: Hai sbloccato una variante della tagliatrice - Cconsente di tagliare le forme in quattro parti invece che in due! reward_painter_double: - title: Double Painting - desc: You have unlocked a variant of the painter - It works as the regular painter but processes two shapes at once consuming just one color instead of two! + title: Verniciatura doppia + desc: Hai sbloccato una variante della verniciatrice - Funziona come una normale verniciatrice, ma processa due forme alla volta consumando solo un'unità di colore invece che due! reward_painter_quad: - title: Quad Painting - desc: You have unlocked a variant of the painter - It allows to paint each part of the shape individually! + title: Verniciatrice + desc: Hai sbloccato una variante della verniciatrice - Consente di verniciare ogni parte della forma indipendentemente! reward_storage: - title: Storage Buffer - desc: You have unlocked a variant of the trash - It allows to store items up to a given capacity! + title: Unità di stoccaggio + desc: Hai sbloccato una variante del cestino - Consente di immagazzinare oggetti fino ad una certa capacità! reward_freeplay: - title: Freeplay - desc: You did it! You unlocked the free-play mode! This means that shapes are now randomly generated! (No worries, more content is planned for the standalone!) + title: Modalità libera + desc: Ce l'hai fatta! Hai sbloccato la modalità libera! Questo significa che adesso le forme sono generate casualmente! (Non preoccuparti, altri contenuti sono in programma per la versione completa!) reward_blueprints: - title: Blueprints - desc: You can now copy and paste parts of your factory! Select an area (Hold CTRL, then drag with your mouse), and press 'C' to copy it.

Pasting it is not free, you need to produce blueprint shapes to afford it! (Those you just delivered). + title: Progetti + desc: Ora puoi copiare ed incollare parti della tua fabbrica! Seleziona un'area (Tieni premuto CTRL e trascina con il mouse) e premi 'C' per copiarla.

Incollarla non è gratis, devi produrre forme progetto per potertelo permettere! (Quelle che hai appena consegnato). # Special reward, which is shown when there is no reward actually no_reward: - title: Next level + title: Prossimo livello desc: >- - This level gave you no reward, but the next one will!

PS: Better don't destroy your existing factory - You need all those shapes later again to unlock upgrades! + Questo livello non ti ha dato alcuna ricompensa, ma il prossimo lo farà!

PS: Meglio non distruggere la fabbrica che hai costruito - Successivamente avrai bisogno di tutte quelle forme per sbloccare i miglioramenti! no_reward_freeplay: - title: Next level + title: Prossimo livello desc: >- - Congratulations! By the way, more content is planned for the standalone! + Congratulazioni! Ci sono altri contenuti in prgramma per la versione completa! settings: title: Impostazioni categories: - game: Gioco - app: Applicazione + general: Generali + userInterface: Interfaccia utente + advanced: Avanzate versionBadges: dev: Sviluppo staging: Staging prod: Produzione - buildDate: Built + buildDate: Build del labels: uiScale: - title: Interface scale + title: Dimensione interfaccia description: >- - Changes the size of the user interface. The interface will still scale based on your device resolution, but this setting controls the amount of scale. + Cambia la dimensione dell'interfaccia utente. L'interfaccia continuerà a cambiare in base alla risoluzione del tuo dispositivo, ma questa impostazione controlla la proporzione. scales: - super_small: Super small - small: Small - regular: Regular - large: Large - huge: Huge + super_small: Minuscola + small: Piccola + regular: Normale + large: Grande + huge: Enorme scrollWheelSensitivity: - title: Zoom sensitivity + title: Sensibilità zoom description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + Determina quanto è sensibile lo zoom (Sia rotella del mouse che trackpad). sensitivity: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super fast + super_slow: Molto lento + slow: Lento + regular: Regolare + fast: Veloce + super_fast: Molto veloce language: title: Lingua @@ -667,9 +678,9 @@ settings: Cambia la lingua. Tutte le traduzioni sono realizzate dagli utenti e potrebbero essere incomplete! fullscreen: - title: Fullscreen + title: Schermo intero description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. + È consigliabile giocare a schermo intero per la migliore esperienza. Disponibile solo nella versione completa. soundsMuted: title: Silenzia Suoni @@ -691,23 +702,23 @@ settings: light: Chiaro refreshRate: - title: Simulation Target + title: Obiettivo della simulazione description: >- - If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. + Se hai un monitor a 144Hz, cambia la frequenza di aggiornamento, in modo tale che il gioco possa correttamente simulare alla frequenza di aggiornamento più alta. Questo potrebbe abbasare i frame al secondo se il tuo computer è troppo lento. alwaysMultiplace: - title: Multiplace + title: Posizionamento multiplo description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. + Se abilitato, tutti gli edifici rimarranno selezionati dopo il posizionamento finchè non lo annullerai. È equivalente a tenere costantemente premuto MAIUSC. offerHints: - title: Hints & Tutorials + title: Indizi e tutorial description: >- - Whether to offer hints and tutorials while playing. Also hides certain UI elements onto a given level to make it easier to get into the game. + Determina se saranno presenti indizi e tutorial durante il gioco. Inoltre, nasconde alcuni elementi dell'interfaccia in certi livelli per semplificare le prime fasi di gioco. movementSpeed: - title: Movement speed - description: Changes how fast the view moves when using the keyboard. + title: Velocità di movimento + description: Determina la velocità di spostamento sulla mappa quando si usa la tastiera. speeds: super_slow: Molto lento slow: Lento @@ -716,79 +727,75 @@ settings: super_fast: Molto veloce extremely_fast: Velocissimo enableTunnelSmartplace: - title: Smart Tunnels + title: Tunnel intelligenti description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. - This also enables to drag tunnels and excess tunnels will get removed. + Se abilitato, piazzare un tunnel rimuoverà anche qualsiasi nastro superfluo. + Consente anche di trascinare i tunnel: i tunnel in eccesso verrano rimossi. vignette: - title: Vignetta + title: Vignettatura description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. + Abilita la vignettatura che scurisce gli angoli dello schermo e rende i testi più leggibili. autosaveInterval: - title: Autosave Interval + title: Intervallo salvataggio automatico description: >- - Controls how often the game saves automatically. You can also disable it - entirely here. + Determina ogni quanto il gioco salva automaticamente. + Qui puoi anche disabilitarlo completamente. intervals: - one_minute: 1 Minute - two_minutes: 2 Minutes - five_minutes: 5 Minutes - ten_minutes: 10 Minutes - twenty_minutes: 20 Minutes - disabled: Disabled + one_minute: 1 Minuto + two_minutes: 2 Minuti + five_minutes: 5 Minuti + ten_minutes: 10 Minuti + twenty_minutes: 20 Minuti + disabled: Disabilitato compactBuildingInfo: - title: Compact Building Infos + title: Info edifici compatte description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a - description and image is shown. + Accorcia le informazioni sugli edifici mostrandone solo la velocità. In caso contrario saranno mostrate immagine e descrizione. disableCutDeleteWarnings: - title: Disable Cut/Delete Warnings + title: Disabilita avvertimenti taglia/cancella description: >- - Disable the warning dialogs brought up when cutting/deleting more than 100 - entities. + Disabilita i messaggi d'avvertimento quando tagli o cancelli più di 100 entità. enableColorBlindHelper: - title: Color Blind Mode - description: Enables various tools which allow to play the game if you are color blind. + title: Modalità daltonici + description: Abilita vari strumenti che ti consentono di giocare se sei daltonico. rotationByBuilding: - title: Rotation by building type + title: Rotazione per tipo di edificio description: >- - Each building type remembers the rotation you last set it to individually. - This may be more comfortable if you frequently switch between placing - different building types. + Ogni tipo di edificio ricorderà l'ultimo orientamento che hai selezionato indipendentemente dagli altri tipi. + È utile se cambi spesso tipo di edificio. keybindings: - title: Keybindings + title: Comandi hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. + Suggerimento: Usa spesso CTRL, MAIUSC e ALT! Abilitano opzioni di posizionamento alternative. - resetKeybindings: Reset Keyinbindings + resetKeybindings: Reimposta comandi categoryLabels: - general: Applicazione + general: Generale ingame: Gioco navigation: Navigazione placement: Posizionamento - massSelect: Mass Select - buildings: Building Shortcuts - placementModifiers: Placement Modifiers + massSelect: Selezione di massa + buildings: Scorciatoie edifici + placementModifiers: Modificatori piazzamento mappings: confirm: Conferma back: Indietro - mapMoveUp: Move Up - mapMoveRight: Move Right - mapMoveDown: Move Down - mapMoveLeft: Move Left + mapMoveUp: Spostati sù + mapMoveRight: Spostati a destra + mapMoveDown: Spostati giù + mapMoveLeft: Spostati a sinistra centerMap: Centra mappa - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker + mapZoomIn: Aumenta zoom + mapZoomOut: Riduci zoom + createMarker: Crea segnapunto - menuOpenShop: Upgrade + menuOpenShop: Miglioramenti menuOpenStats: Statistiche toggleHud: Mostra/Nascondi HUD @@ -806,50 +813,48 @@ keybindings: rotateWhilePlacing: Ruota rotateInverseModifier: >- - Modifier: Rotate CCW instead + Modificatore: Ruota in senso antiorario cycleBuildingVariants: Cicla varianti confirmMassDelete: Conferma eliminazione di massa - cycleBuildings: Cycle Buildings + cycleBuildings: Cicla edifici - massSelectStart: Hold and drag to start + massSelectStart: Clicca e trascina per cominciare massSelectSelectMultiple: Seleziona aree multiple massSelectCopy: Copia area - placementDisableAutoOrientation: Disable automatic orientation - placeMultiple: Stay in placement mode - placeInverse: Invert automatic belt orientation - pasteLastBlueprint: Paste last blueprint - massSelectCut: Cut area - exportScreenshot: Export whole Base as Image - mapMoveFaster: Move Faster - lockBeltDirection: Enable belt planner - switchDirectionLockSide: "Planner: Switch side" - pipette: Pipette - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire + placementDisableAutoOrientation: Disabilita orientamento automatico + placeMultiple: Rimani in modalità posizionamento + placeInverse: Inverti direzione automatica nastri + pasteLastBlueprint: Incolla l'ultimo progetto + massSelectCut: Taglia area + exportScreenshot: Esporta l'intera base come immagine + mapMoveFaster: Muoviti più rapidamente + lockBeltDirection: Abilita pianificatore nastri + switchDirectionLockSide: "Pianificatore: cambia direzione" + pipette: Contagocce + menuClose: Chiudi menù + switchLayers: Cambia livello + advanced_processor: Inversore di colore + energy_generator: Generatore di energia + wire: Cavo energetico about: title: Riguardo questo gioco body: >- - This game is open source and developed by Tobias Springer (this is me).

+ Questo gioco è open source e sviluppato da Tobias Springer (me).

- If you want to contribute, check out shapez.io on github.

+ Se vuoi contribuire visita la pagina github di shapez.io.

- This game wouldn't have been possible without the great discord community - around my games - You should really join the discord server!

+ Realizzare questo gioco non sarebbe stato possibile senza la grande community di Discord per i miei giochi - Unisciti al server di Discord!

- The soundtrack was made by Peppsen - He's awesome.

+ La colonna sonora è stata composta daPeppsen - È un grande.

- Finally, huge thanks to my best friend Niklas - Without our - factorio sessions this game would never have existed. + Per finire, grazie di cuore al mio migliore amico Niklas - Senza le nostre sessioni su factorio questo gioco non sarebbe mai esistito. changelog: title: Changelog diff --git a/translations/base-ja.yaml b/translations/base-ja.yaml index f9f37b64..951a2684 100644 --- a/translations/base-ja.yaml +++ b/translations/base-ja.yaml @@ -15,10 +15,11 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.ioは無限のマップ内で様々な"形"を資源とし、段々と複雑になっていく形の作成や合成の自動化を目指して工場を構築するゲームです。 @@ -30,32 +31,32 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.ioは無限のマップ内で様々な"形"を資源とし、段々と複雑になっていく形の作成や合成の自動化を目指して工場を構築するゲームです。 + 求められた"形"を届けることで様々なアップグレードを手に入れることができ、さらに工場の効率を上げることができます。 - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + "形"の需要が増えるにつれ、工場を拡大する必要があります - より多くの資源を手に入れるために[b]無限のマップ[!b]を開拓していく必要があります。 - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + "形"に色を塗る必要もあります - 赤、緑、青を混ぜ、さまざまな色を作り需要に応じて色が塗られた"形"を製造できます。 - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + 現在このゲームには18個のレベルがあり、今後これを拡大していく予定です - 他にも様々なアップデートを準備しています! - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + このゲームを買うことによってスタンドアローン版の様々な機能が使えるようになり、新しいアップデートもすぐに手に入ります。 - [b]Standalone Advantages[/b] + [b]スタンドアローン版で使える機能[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] ダークモード + [*] ウェイポイントの制限がありません + [*] セーブの数の制限がありません + [*] 様々な設定 + [*] 追加予定: ワイヤーとエネルギー! (7月末を目指しています) + [*] 追加予定: より多くのレベル + [*] shapez.io開発が助けられます❤️ [/list] - [b]Future Updates[/b] + [b]今後の予定[/b] - I am updating the game very often and trying to push an update at least every week! + 週に一回はアップデートを出せることを目指しています。 [list] [*] Different maps and challenges (e.g. maps with obstacles) @@ -67,22 +68,22 @@ steamPage: [*] And much more! [/list] - [b]This game is open source![/b] + [b]このゲームはオープンソースです![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + 誰でもこのゲームの開発を手伝うことができ、私もプレーヤーの意見をできるだけゲームに取り入れようとしています。 + Trelloで今後の予定が全て確認できます。 - [b]Links[/b] + [b]外部リンク[/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] - [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://discord.com/invite/HN7EVzV]公式Discord[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]今後の予定[/url] + [*] [url=https://www.reddit.com/r/shapezio]Reddit[/url] + [*] [url=https://github.com/tobspr/shapez.io]ソースコード(GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]翻訳に参加[/url] [/list] - discordLink: Official Discord - Chat with me! + discordLink: 公式Discord - 私と話せます! global: loading: ロード中 @@ -91,6 +92,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -131,14 +135,14 @@ demoBanners: # This is the "advertisement" shown in the main menu and other various places title: デモ版 intro: >- - スタンドアローン版を手に入れ、すべての要素をアンロックしましょう! + スタンドアローン版を手に入れ、すべての機能をアンロックしましょう! mainMenu: play: プレイ changelog: 更新履歴 importSavegame: インポート openSourceHint: このゲームはオープンソースです - discordLink: 公式Discordサーバ + discordLink: 公式Discord helpTranslate: 翻訳に参加 # This is shown when using firefox and other browsers which are not supported. @@ -148,10 +152,9 @@ mainMenu: savegameLevel: レベル savegameLevelUnknown: 不明なレベル - continue: 続きから newGame: 新規ゲーム - madeBy: Made by + madeBy: 制作者 subreddit: Reddit dialogs: @@ -409,7 +412,7 @@ ingame: cyan: シアン white: 白 uncolored: 無色 - black: Black + black: 黒 shapeViewer: title: レイヤー empty: 空 @@ -488,6 +491,9 @@ buildings: ccw: name: 回転機 (逆) description: 形を反時計回り方向に90度回転します。 + fl: + name: 回転機 (180) + description: 形を180度回転します。 stacker: default: @@ -528,20 +534,20 @@ buildings: advanced_processor: default: name: Color Inverter - description: Accepts a color or shape and inverts it. + description: 入力された色や形の色を反転します。 energy_generator: deliver: Deliver toGenerateEnergy: For default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: エネルギー発電機 + description: 入力された形を使って、エネルギーを発電します。 wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: ワイヤー分配機 + description: 1つのワイヤーを2つのワイヤーに分配します。 merger: - name: Wire Merger - description: Merges two energy wires into one. + name: ワイヤー合流機 + description: 2つのワイヤーを1つのワイヤーに合流します。 storyRewards: # Those are the rewards gained from completing the store @@ -629,8 +635,9 @@ storyRewards: settings: title: 設定 categories: - game: ゲーム - app: アプリケーション + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: Development @@ -834,7 +841,7 @@ about: 開発に参加したい場合は以下をチェックしてみてください。shapez.io on github.

- このゲームはdiscordでの素晴らしいコミュニティなしには実現しませんでした。 - このサーバにも是非参加してください! discord server!

+ このゲームはdiscordでの素晴らしいコミュニティなしには実現しませんでした。 - このサーバにも是非参加してください! Discord server!

サウンドトラックはPeppsenにより製作されました。 - 彼は素晴らしいです

diff --git a/translations/base-kor.yaml b/translations/base-kor.yaml index 6e6c58d6..4c9048fb 100644 --- a/translations/base-kor.yaml +++ b/translations/base-kor.yaml @@ -15,13 +15,14 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page - shortText: shapez.io는 무한한 공간에서 점점 더 복잡한 도형의 생산과 조합을 자동화하는 공장들을 짓는 게임입니다. + shortText: shapez.io는 무한한 공간에서 점점 더 복잡한 도형의 생산과 조합을 자동화하는 공장을 짓는 게임입니다. # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: @@ -30,59 +31,59 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.io는 무한한 공간에서 점점 더 복잡한 도형의 생산과 조합을 자동화하는 공장을 짓는 게임입니다. + 요청된 도형을 전달해 게임을 진행하고 업그레이드를 통해 공장을 가속시킬 수 있습니다. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + 도형에 대한 수요가 증가함에 따라, 여러분은 수요에 맞게 공장을 확장해야 합니다. - [b]무한한 공간[/b]으로 확장하여 도형 재료를 구하는 것도 잊지 마세요. - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + 곧이어 여러분은 색을 섞고 도형을 색칠 할 것입니다. - 빨강, 초록, 파랑 색을 섞어서 만든 다양한 색으로 수요를 만족시키세요. - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + 이 게임에는 18개의 레벨이 있습니다 (이것 만으로도 여러분은 이미 몇시간이 걸렸을 거예요!) 하지만 저는 항상 새로운 콘텐츠를 추가하고 있습니다 - 계획해 놓은 것들이 많습니다! - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + 게임을 구입하면 추가 기능이 있는 독립 실행형 버전을 이용할 수 있으며 새로 개발된 기능도 이용할 수 있습니다. - [b]Standalone Advantages[/b] + [b]유료 버전의 장점[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] 다크 모드 + [*] 제한 없는 마커 + [*] 제한 없는 저장 + [*] 더 다양한 설정 + [*] 출시 예고: 전선 & 에너지! 2020년 7월 말을 목표로 하는 중. + [*] 출시 예고: 더 많은 레벨 + [*] shapez.io를 개발하는 데 도움이 됨 ❤️ [/list] - [b]Future Updates[/b] + [b]향후 업데이트[/b] - I am updating the game very often and trying to push an update at least every week! + 저는 게임을 자주 업데이트하고 있고 적어도 매주마다 업데이트를 추진하려고 노력 중입니다! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] 다양한 맵과 챌린지 (e.g. 장애물이 있는 맵) + [*] 퍼즐 (제한된 영역/건물만으로 도형 전달하기) + [*] 건물에 비용이 드는 스토리 모드 + [*] 설정 가능한 맵 생성기 (자원/도형, 크기/밀도, 시드 등) + [*] 더 많은 종류의 도형 + [*] 성능 향상 (지금도 게임이 잘 되긴 합니다!) + [*] 그 외 다수! [/list] - [b]This game is open source![/b] + [b]이 게임은 오픈소스 입니다![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + 누구나 참여할 수 있으며, 저는 커뮤니티에 적극적으로 참여하고 있고 가능한 경우 모든 제안을 검토하고 피드백을 고려하려고 합니다. + 전체 로드맵을 위해 반드시 내 Trello 보드를 확인하세요! - [b]Links[/b] + [b]링크[/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] - [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://discord.com/invite/HN7EVzV]공식 디스코드[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]로드맵[/url] + [*] [url=https://www.reddit.com/r/shapezio]서브레딧[/url] + [*] [url=https://github.com/tobspr/shapez.io]소스 코드 (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]번역을 도와주세요![/url] [/list] - discordLink: Official Discord - Chat with me! + discordLink: 공식 디스코드 - 채팅해요! global: loading: 로딩중 @@ -91,6 +92,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -131,7 +135,7 @@ demoBanners: # This is the "advertisement" shown in the main menu and other various places title: 무료 버전 intro: >- - 유료 버전을 구매해서 모든 컨탠츠를 사용해 보세요! + 유료 버전을 구매해서 모든 콘텐츠를 사용해 보세요! mainMenu: play: 시작 @@ -147,11 +151,10 @@ mainMenu: savegameLevel: 레벨 savegameLevelUnknown: 레벨 모름 - continue: 계속하기 newGame: 새 게임 madeBy: 제작 - subreddit: Reddit + subreddit: 레딧 dialogs: buttons: @@ -175,7 +178,7 @@ dialogs: importSavegameSuccess: title: 저장 파일 불러오기 성공 text: >- - 저장 파일이 성공적으로 불러와졌습니다. + 저장 파일을 성공적으로 불러왔습니다. gameLoadFailure: title: 저장 파일 에러 @@ -202,20 +205,20 @@ dialogs: desc: 당신이 원하는 키나 마우스 버튼을 눌러서 바꾸거나 ESC를 눌러 취소하세요. resetKeybindingsConfirmation: - title: 키바인딩 제설정 + title: 키바인딩 재설정 desc: 이것은 모든 키바인딩을 기본값으로 초기화합니다. keybindingsResetOk: - title: 키바인딩 제설정 완료 + title: 키바인딩 재설정 완료 desc: 모든 키바인딩이 기본값으로 재설정 되었습니다! featureRestriction: - title: 데모 버전 - desc: 데모 버전에는 없는 컨탠츠()로 시도했습니다. 유료 버전을 구입해서 모든 컨텐츠를 사용해보세요! + title: 체험판 버전 + desc: 체험판 버전에는 없는 콘텐츠()로 시도했습니다. 유료 버전을 구입해서 모든 콘텐츠를 사용해보세요! oneSavegameLimit: title: 저장파일 개수 제한 - desc: 데모 버전에서는 저장 파일을 한 번에 한 개만 사용할 수 있습니다. 이미 있는 저장 파일을 지우거나 유료 버전을 구입 해주새요. + desc: 체험판 버전에서는 저장 파일을 한 번에 한 개만 사용할 수 있습니다. 이미 있는 저장 파일을 지우거나 유료 버전을 구입 해주새요. updateSummary: title: 신규 버전! @@ -255,20 +258,20 @@ dialogs: createMarker: title: 새로운 마커 desc: 이 장소에 이름을 지어주세요, 당신은 원하는 모양으로 단축키를 생성할 수 있습니다. (여기에서 만들 수 있습니다.) - titleEdit: Edit Marker + titleEdit: 마커 변경 markerDemoLimit: - desc: 데모 버전에서는 마커를 2개 까지만 놓을 수 있습니다. 유료 버전을 구입하면 마커를 무제한으로 놓을 수 있습니다! + desc: 체험판 버전에서는 마커를 2개 까지만 놓을 수 있습니다. 유료 버전을 구입하면 마커를 무제한으로 놓을 수 있습니다! exportScreenshotWarning: title: 스크린샷 내보내기 desc: >- - 당신은 당신의 공장을 스크린샷으로 내보내려 하고있습니다. 공장이 너무 큰 경우에는 + 당신은 공장을 스크린샷으로 내보내려 하고있습니다. 공장이 너무 큰 경우에는 시간이 오래 걸리거나 게임이 꺼질 수도 있음을 알려드립니다! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + title: 자르기 확인 + desc: 이 곳에는 붙여넣기를 할 수 없습니다! 정말 자르시겠습니까? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -292,7 +295,7 @@ ingame: copySelection: 선택된 부분 복사하기 clearSelection: 선택된 부분 지우기 pipette: 스포이드 - switchLayers: Switch layers + switchLayers: 레이어 전환 # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -339,7 +342,7 @@ ingame: # The roman number for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: 최대 (Speed x) + maximumLevel: 최대 레벨 (속도 x) # The "Statistics" window statistics: @@ -386,7 +389,7 @@ ingame: waypoints: 마커 hub: 중앙 건물 description: 마커를 좌클릭해서 그곳으로 가고, 우클릭해서 삭제합니다.

을 눌러 지금 있는 곳에 마커를 놓거나 우클릭해서 원하는 곳에 놓으세요. - creationSuccessNotification: 마커가 성공적으로 제작되었습니다. + creationSuccessNotification: 마커가 성공적으로 생성되었습니다. # Interactive tutorial interactiveTutorial: @@ -394,10 +397,10 @@ ingame: hints: 1_1_extractor: 추출기원 모양의 도형에 놓아서 추출하세요! 1_2_conveyor: >- - 추출기를 컨베이어 벨트로 당신의 중앙 건물에 연결하세요!

팁: 마우스로 벨트를 클릭해서 드래그하세요! + 추출기를 컨베이어 벨트로 당신의 중앙 건물에 연결하세요!

팁: 마우스로 벨트를 클릭하고 드래그하세요! 1_3_expand: >- - 이것은 방치형 게임이 아닙니다! 추출기를 더 놓아 목표를 빨리 달성하세요.

팁: SHIFT를 눌러 여러 개의 추출기를 놓고 R로 회전 시키세요. + 이것은 방치형 게임이 아닙니다! 추출기를 더 놓아 목표를 빨리 달성하세요.

팁: SHIFT를 눌러 여러 개의 추출기를 놓고 R로 방향을 바꾸세요. colors: red: 빨강 @@ -407,12 +410,12 @@ ingame: purple: 보라 cyan: 청록 white: 하양 - uncolored: 색 - black: Black + uncolored: 회색 + black: 검정 shapeViewer: title: 층 empty: 비었음 - copyKey: Copy Key + copyKey: 키 복사하기 # All shop upgrades shopUpgrades: @@ -457,7 +460,7 @@ buildings: tier2: name: 터널 티어 II - description: 도형을 건물과 벨트 밑으로 통과시킴. + description: 도형을 건물과 벨트 밑으로 터널 보다 빨리 통과시킴. splitter: # Internal name for the Balancer default: @@ -487,10 +490,13 @@ buildings: ccw: name: 회전기 (반시계방향) description: 도형을 반시계방향으로 90도 회전시킨다. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: - name: &stacker 스택커 + name: &stacker 결합기 description: 도형 2개를 쌓는다. 합칠 수가 없다면 오른쪽 도형이 왼쪽 도형 위에 놓아진다. mixer: @@ -522,25 +528,25 @@ buildings: description: 할당된 용량만큼 초과되는 도형을 저장한다. wire: default: - name: Energy Wire - description: Allows you to transport energy. + name: 전선 + description: 에너지를 전송한다. advanced_processor: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + name: 색 반전기 + description: 색소나 도형을 받아 색을 반전시킨다. energy_generator: - deliver: Deliver - toGenerateEnergy: For + deliver: 연료 + toGenerateEnergy: 마다 default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: 발전기 + description: 도형을 소비해 에너지를 만듭니다. wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: 전선 분배기 + description: 에너지 와이어를 두 개로 분할합니다. merger: - name: Wire Merger - description: Merges two energy wires into one. + name: 전선 병합기 + description: 두 개의 에너지 와이어를 하나로 병합합니다. storyRewards: # Those are the rewards gained from completing the store @@ -574,8 +580,8 @@ storyRewards: desc: 터널이 잠금 해제되었습니다! 자원을 건물과 벨트 밑으로 운송 할 수 있습니다. reward_rotater_ccw: - title: 회전기 (반시게방향) - desc: 반시게방향 회전기가 잠금 해제되었습니다! 이것을 배치하려면 회전기를 선택하고 T를 눌러서 변형된 버전을 사용하세요! + title: 회전기 (반시계방향) + desc: 반시계방향 회전기가 잠금 해제되었습니다! 이것을 배치하려면 회전기를 선택하고 T를 눌러서 변형된 버전을 사용하세요! reward_miner_chainable: title: 체인 추출기 @@ -607,11 +613,11 @@ storyRewards: desc: 저장소가 잠금 해제되었습니다! 주어진 용량만큼 자원을 저장할 수 있습니다! reward_freeplay: - title: 프리플레이 모드 - desc: 해내셨군요! 프리플레이 모드가 잠금 해제되었습니다! 이제 도형이 랜덤으로 생성됩니다! (걱정 마세요, 유료버전에는 더 많은 컨텐츠가 계획되어 있습니다!) + title: 자유 모드 + desc: 해내셨군요! 자유 모드가 잠금 해제되었습니다! 이제 도형이 랜덤으로 생성됩니다! (걱정 마세요, 유료버전에는 더 많은 컨텐츠가 계획되어 있습니다!) reward_blueprints: - title: 블루프린트 + title: 청사진 desc: 이제부터는 공장의 일부 영역을 복사하여 붙여넣기 할 수 있습니다! CTRL을 누르면서 드래그해서 먼저 영역을 선택하세요.

그 다음에는 C, DEL, ESC 로 복사하거나, 지우거나, 취소 하세요.

복사는 무료가 이닙니다. 특별한 "화폐" 도형으로 돈을 지불하고 복사가 됩니다. # Special reward, which is shown when there is no reward actually @@ -628,13 +634,14 @@ storyRewards: settings: title: 설정 categories: - game: 게임 - app: 앱 + general: 일반 + userInterface: 유저 인터페이스 + advanced: 고급 versionBadges: - dev: 발전 중 - staging: 단계적으로 발전 중 - prod: 제작 중 + dev: 개발 + staging: 검증 + prod: 배포 buildDate: 날짜 labels: @@ -647,12 +654,12 @@ settings: small: 작게 regular: 보통 large: 크게 - huge: 거대하게 + huge: 매우 크게 scrollWheelSensitivity: title: 확대 민감도 description: >- - 마우스 휠이나 트렉패드로 확대하는 데의 민감도 + 마우스 휠이나 트랙패드로 확대하는 데의 민감도 sensitivity: super_slow: 매우 느리게 slow: 느리게 @@ -675,15 +682,15 @@ settings: language: title: 언어 description: >- - 언어 바꾸기 - 모든 언어팩은 사용자들이 만든 것이므로 완성되지 않았을 수 있습니다.. + 언어 바꾸기 - 모든 언어팩은 사용자들이 만든 것이므로 정확하지 않을 수 있습니다! fullscreen: - title: Fullscreen + title: 전체화면 description: >- - 이 게임은 풀 스크린으로 하는 것이 가장 좋습니다. 풀 스크린 모드는 유료 버전에서만 가능합니다. + 이 게임은 전체화면으로 하는 것이 가장 좋습니다. 전체화면은 유료 버전에서만 가능합니다. soundsMuted: - title: 소리 끄기 + title: 효과음 끄기 description: >- 모든 효과음을 끕니다. @@ -701,19 +708,19 @@ settings: light: 밝은 테마 refreshRate: - title: 모니터 리프레쉬 속도 + title: 시뮬레이션 빈도 description: >- - 당신의 모니터의 리프세쉬 속도가 144hz 보다 높으면 이 설정을 바꾸어서 게임이 더 빨리 리프레시 되게 하세요. 만약에 컴퓨터가 느리다면 FPS에 영양을 미칠 수 있습니다. + 144hz 모니터가 있다면 이 설정을 바꿔 게임이 높은 빈도로 적절히 시뮬레이션되게 하세요. 만약에 컴퓨터가 느리다면 FPS에 영양을 미칠 수 있습니다. alwaysMultiplace: title: 항상 여러 개 배치 description: >- - 배치 이후에도 모든 빌딩이 선택되어 있습니다. SHIFT를 계속 누르고 있는 것과 같은 효과입니다. + 활성화된 경우 모든 건물은 따로 취소하기 전까지 배치 후 선택된 상태로 유지됩니다. SHIFT를 계속 누르고 있는 것과 같은 효과입니다. offerHints: title: 힌트와 튜토리얼 description: >- - 이것을 끄면 힌트와 튜토리얼이 나오지 않습니다. 또한 게임에 쉽게 들어가기 위해서 주어진 레벨에서 특정 UI 요소를 숨길 수도 있습니다. + 이것을 끄면 힌트와 튜토리얼이 나오지 않습니다. 또한 특정 UI 요소를 지정된 레벨까지 숨겨 게임에 쉽게 들어갈 수 있습니다. enableTunnelSmartplace: title: 스마트 터널 @@ -722,14 +729,14 @@ settings: 또한, 터널을 당겨서 남는 터널을 없앱니다. vignette: - title: 삽화 + title: 비네트 효과 description: >- - 화면의 코너를 어둡게 만들어 텍스트를 읽기 쉽게 해주는 삽화를 활성화 시킵니다. + 화면의 모서리를 어둡게 만들어 텍스트를 읽기 쉽게 해주는 비네트 효과를 활성화 시킵니다. autosaveInterval: title: 자동저장 주기 description: >- - 자동저장을 얼마나 자주 할 것인지 정합니다. 자동저장기능을 끌 수도 있습니다. + 자동저장을 얼마나 자주 할 것인지 정합니다. 자동저장 기능을 끌 수도 있습니다. intervals: one_minute: 1분 two_minutes: 2분 @@ -738,7 +745,7 @@ settings: twenty_minutes: 20분 disabled: 기능 끄기 compactBuildingInfo: - title: 간결한 건물 정보 + title: 간단한 건물 정보 description: >- 건물의 정보창을 해당 건물의 능률만 보이도록 줄입니다. 아니면, 설명과 이미지가 보입니다. @@ -769,8 +776,8 @@ keybindings: navigation: 둘러보기 placement: 놓기 massSelect: 다중 선택 - buildings: 건물 쇼트컷 - placementModifiers: 배치 수정기 + buildings: 건물 단축키 + placementModifiers: 배치 옵션 mappings: confirm: 확인 @@ -815,18 +822,18 @@ keybindings: massSelectCut: 영역 자르기 placementDisableAutoOrientation: 자동 회전 끄기 - placeMultiple: 배치 모드에 있기 - placeInverse: 자동 벨트 회전 뒤집기 + placeMultiple: 배치 모드 유지 + placeInverse: 반대 방향으로 벨트 배치 exportScreenshot: 공장 전체를 이미지로 내보내기 mapMoveFaster: 더 빠르게 움직이기 lockBeltDirection: 벨트 플래너 활성화 switchDirectionLockSide: "플래너: 방향 바꾸기" - pipette: 피펫 - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire + pipette: 스포이드 + menuClose: 메뉴 닫기 + switchLayers: 레이어 전환 + advanced_processor: 색 반전기 + energy_generator: 발전기 + wire: 전선 about: title: 이 게임의 정보 @@ -855,7 +862,7 @@ demo: restoringGames: 게임 자장 파일 리스토어 하기 importingGames: 게임 저장 파일 불러오기 oneGameLimit: 게임 저장 파일 최대 1개 - customizeKeybindings: 키바인딩 설정하기 + customizeKeybindings: 키 설정하기 exportingBase: 공장 전체를 이미지로 내보내기 - settingNotAvailable: 데모 버전에서 사용 불가 + settingNotAvailable: 체험판 버전에서 사용 불가 diff --git a/translations/base-lt.yaml b/translations/base-lt.yaml index 81d23e95..79a450bf 100644 --- a/translations/base-lt.yaml +++ b/translations/base-lt.yaml @@ -15,10 +15,11 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. @@ -91,6 +92,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -148,7 +152,6 @@ mainMenu: savegameLevel: Level savegameLevelUnknown: Unknown Level - continue: Continue newGame: New Game madeBy: Made by @@ -488,6 +491,9 @@ buildings: ccw: name: Rotate (CCW) description: Rotates shapes counter clockwise by 90 degrees. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -629,8 +635,9 @@ storyRewards: settings: title: Settings categories: - game: Game - app: Application + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: Development @@ -839,9 +846,9 @@ about: If you want to contribute, check out shapez.io on github.

- This game wouldn't have been possible without the great discord community + This game wouldn't have been possible without the great Discord community around my games - You should really join the discord server!

+ target="_blank">Discord server!

The soundtrack was made by Peppsen - He's awesome.

diff --git a/translations/base-nl.yaml b/translations/base-nl.yaml index 0626033a..2f061268 100644 --- a/translations/base-nl.yaml +++ b/translations/base-nl.yaml @@ -15,10 +15,11 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io is een spel dat draait om het bouwen van fabrieken voor het produceren en automatiseren van steeds complexere vormen in een oneindig groot speelveld. @@ -30,59 +31,59 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.io is een spel dat draait om het bouwen van fabrieken om steeds complexere vormen te produceren en deze productie te automatiseren in een oneindig groot speelveld. + Door het leveren van de gevraagde vormen, kom je verder in het spel en ontgrendel je upgrades waar je fabriek sneller van wordt. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + De vraag naar vormen wordt steeds groter, wat betekent dat je de fabriek moet uitbreiden om de vraag tegemoet te komen. Om de juiste grondstoffen te delven zul je steeds verder in het [b]oneindig grote speelveld[/b] moeten gaan werken! - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Omdat simpele vormen snel saai worden, moet je kleuren mengen om de vormen te verven - Combineer rode, groene en blauwe grondstoffen om verschillende kleuren te produceren en gebruik deze om de vormen te verven, zodat je de vraag hiernaar tegemoet kan komen. - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Dit spel bevat 18 levels (Waar je al uren mee bezig zal zijn!), maar ik ben continu bezig om het spel uit te breiden - er staat veel in de planning! - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + Wanneer je het spel koopt dan krijg je toegang tot de standalone versie. Deze heeft extra functies en je krijgt ook toegang tot nieuwe ontwikkelingen. - [b]Standalone Advantages[/b] + [b]Standalone Voordelen[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Donkere modus + [*] Oneindig veel markeringen + [*] Oneindig veel savegames + [*] Extra opties + [*] Binnenkort: Kabels & Energie! Hopelijk vanaf eind juli 2020. + [*] Binnenkort: Meer Levels + [*] Help mij om shapez.io verder te ontwikkelen ❤️ [/list] - [b]Future Updates[/b] + [b]Geplande Updates[/b] - I am updating the game very often and trying to push an update at least every week! + Ik update het spel regelmatig en probeer dit zeker eenmaal per week te doen! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Verschillende speelvelden en uitdagingen (bijv. obstakels) + [*] Puzzels (Bezorg de gevraagde vorm binnen een afgesloten gebied of met bepaalde gebouwen) + [*] Een verhaalmodus waar gebouwen iets kosten + [*] Aanpasbare speelveldgenerator (Kies de hoeveelheid en grootte van grondstoffen, seed en meer) + [*] Meer soorten vormen + [*] Prestatieverbeteringen (Het spel loopt al vrij goed!) + [*] En nog veel meer! [/list] - [b]This game is open source![/b] + [b]Dit spel is open source![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Iedereen kan bijdragen. Ik ben actief in de community en probeer naar alle suggesties en feedback te kijken en deze op te nemen in de ontwikkeling. + Bekijk mijn trello-bord voor het volledige stappenplan! [b]Links[/b] [list] [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Stappenplan[/url] [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help met vertalen[/url] [/list] - discordLink: Official Discord - Chat with me! + discordLink: Officiële Discord - Chat met mij! global: loading: Laden @@ -91,11 +92,14 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "." + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "," + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: - thousands: K + thousands: k millions: M - billions: G + billions: B trillions: T # Shown for infinitely big numbers @@ -138,7 +142,7 @@ mainMenu: changelog: Changelog importSavegame: Importeren openSourceHint: Dit spel is open source! - discordLink: Officiële discord-server (Engelstalig) + discordLink: Officiële Discord-server (Engelstalig) helpTranslate: Help met vertalen! # This is shown when using firefox and other browsers which are not supported. @@ -148,7 +152,6 @@ mainMenu: savegameLevel: Level savegameLevelUnknown: Onbekend Level - continue: Verder newGame: Nieuw Spel madeBy: Gemaakt door @@ -166,15 +169,15 @@ dialogs: deleteGame: Ik weet wat ik doe viewUpdate: Zie Update showUpgrades: Zie Upgrades - showKeybindings: Zie sneltoetsen + showKeybindings: Zie Sneltoetsen importSavegameError: - title: Import Error + title: Importeer error text: >- Het importeren van je savegame is mislukt: importSavegameSuccess: - title: Savegame Geïmporteerd + title: Savegame geïmporteerd text: >- Je savegame is succesvol geïmporteerd. @@ -224,7 +227,7 @@ dialogs: Dit zijn de veranderingen sinds je voor het laatst gespeeld hebt: upgradesIntroduction: - title: Ontgrendel Upgrades + title: Ontgrendel upgrades desc: >- Alle vormen die je produceert kunnen gebruikt worden om upgrades te ontgrendelen - vernietig je oude fabrieken niet! Het upgrades-tabblad staat in de rechterbovenhoek van het scherm. @@ -266,8 +269,8 @@ dialogs: Je hebt aangegeven dat je jouw basis wil exporteren als screenshot. Als je een grote basis hebt kan dit proces langzaam zijn en er zelfs voor zorgen dat je spel crasht! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + title: Bevestig knippen + desc: Je kunt het je niet veroorloven om de selectie te plakken! Weet je zeker dat je het wil knippen? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -284,14 +287,14 @@ ingame: placeBuilding: Plaats gebouw createMarker: Plaats markering delete: Vernietig - pasteLastBlueprint: Plak de laatst gekopiëerde blauwdruk - lockBeltDirection: Maak gebruik van de lopende band planner + pasteLastBlueprint: Plak laatst gekopiëerde blauwdruk + lockBeltDirection: Gebruik lopende band planner plannerSwitchSide: Draai de richting van de planner cutSelection: Knip - copySelection: Kopiëer + copySelection: Kopieer clearSelection: Annuleer selectie pipette: Pipet - switchLayers: Switch layers + switchLayers: Wissel lagen # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -346,7 +349,7 @@ ingame: dataSources: stored: title: In opslag - description: Geeft weer hoe veel vormen er zijn opgeslagen in de HUB. + description: Geeft alle vormen weer die opgeslagen zijn in de HUB. produced: title: Geproduceerd description: Geeft alle vormen weer die op dit moment geproduceerd worden, inclusief tussenproducten. @@ -368,7 +371,7 @@ ingame: buttons: continue: Verder spelen settings: Opties - menu: Terug naar het menu + menu: Terug naar het Menu # Bottom left tutorial hints tutorialHints: @@ -407,7 +410,7 @@ ingame: cyan: Cyaan white: Wit uncolored: Geen kleur - black: Black + black: Zwart shapeViewer: title: Lagen empty: Leeg @@ -481,6 +484,9 @@ buildings: ccw: name: Roteerder (andersom) description: Draait vormen 90 graden tegen de klok in. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -498,7 +504,7 @@ buildings: description: &painter_desc Verft de volledige vorm in de linker input met de kleur van de rechter input. double: name: Verver (Dubbel) - description: Verft de vormen in de linker inputs met de kleur van de rechter input. + description: Verft de vormen in de linker input met de kleur van de rechter input. quad: name: Verver (Quad) description: Verft elke kwart van de vorm een andere kleur. @@ -521,25 +527,25 @@ buildings: levelShortcut: LVL wire: default: - name: Energy Wire - description: Allows you to transport energy. + name: Energiekabel + description: Voor transport van energie. advanced_processor: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + name: Kleur-omkeerder + description: Keert de kleur om van een voorwerp. energy_generator: - deliver: Deliver - toGenerateEnergy: For + deliver: Lever + toGenerateEnergy: Voor default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: Energiegenerator + description: Wekt energie op door vormen te consumeren. wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Kabelsplijter + description: Splijt één kabel in twee. merger: - name: Wire Merger - description: Merges two energy wires into one. + name: Kabelvoeger + description: Voegt twee kabels samen tot één. storyRewards: # Those are the rewards gained from completing the store @@ -590,7 +596,7 @@ storyRewards: Je hebt een compacte variant van de verdeler ontgrendeld - Dit voegt twee lopende banden samen tot één. reward_cutter_quad: - title: Quad Cutting + title: Quad Knippen desc: Je hebt een variant van de knipper ontgrendeld - Dit knipt vormen in vier stukken in plaats van twee! reward_painter_double: @@ -602,7 +608,7 @@ storyRewards: desc: Je hebt een variant van de verver ontgrendeld - Het verft elk kwadrant van de vorm een andere kleur! reward_storage: - title: Opslag buffer + title: Opslagbuffer desc: Je hebt een variant van de vuilnisbak ontgrendeld - Het slaat voorwerpen op tot een zekere hoeveelheid! reward_freeplay: @@ -627,8 +633,9 @@ storyRewards: settings: title: Opties categories: - game: Spel - app: Applicatie + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: Ontwikkeling @@ -646,7 +653,7 @@ settings: small: Klein regular: Middel large: Groot - huge: Wumbo + huge: Jumbo scrollWheelSensitivity: title: Zoom-gevoeligheid @@ -822,11 +829,11 @@ keybindings: lockBeltDirection: Schakel lopende band-planner in switchDirectionLockSide: "Planner: Wissel van richting" pipette: Pipet - menuClose: Sluit menu + menuClose: Sluit Menu switchLayers: Lagen omwisselen - advanced_processor: Kleur Omvormer - energy_generator: Energie generator - wire: Energie Draad + advanced_processor: Kleur-omvormer + energy_generator: Energiegenerator + wire: Energiekabel about: title: Over dit spel @@ -837,9 +844,9 @@ about: Als je ook bij wil dragen, ga dan naar shapez.io op github.

- Dit spel was niet mogelijk geweest zonder de geweldige discord community + Dit spel was niet mogelijk geweest zonder de geweldige Discord community rondom mijn spellen - Je zou eens lid moeten worden van de discord server (engelstalig)!

+ target="_blank">Discord server (engelstalig)!

De muziek is gemaakt door Peppsen - Hij is geweldig.

diff --git a/translations/base-no.yaml b/translations/base-no.yaml index ab8769d5..a0c57941 100644 --- a/translations/base-no.yaml +++ b/translations/base-no.yaml @@ -15,13 +15,14 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page - shortText: shapez.io er et spill som handler om å bygge fabrikker for å automatisere produksjon og kombinering av former med økende kompleksitet på et ubegrenset brett. + shortText: shapez.io er et spill som handler om å bygge fabrikker for å automatisere produksjon og kombinasjon av former med økende kompleksitet på et uendelig ekspanderende brett. # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: @@ -30,59 +31,59 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + Shapez.io er et spill som handler om å bygge fabrikker for å automatisere produksjon og kombinasjon av former med økende kompleksitet på et uendelig ekspanderende brett. + Ved leveranse av de forespurte formene vil du komme videre i spillet og låse opp oppgraderinger for å øke farten på fabrikken din - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Etter hvert som forespørselen av former øker, vil du være nødt til å utvide fabrikken din for å møte etterspørselen - Ikke glem ressursene, du vil bli nødt til å utvide over det [b]uendelige brettet[/b]! - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Snart blir du nødt til å plande farger og male formene dine med dem - Kombiner røde, grønne og blåe farge ressurser for å produsere forskjellige farger og male former med dem for å tilfredstille etterspørselen. - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Dette spillet har 18 progressive nivåer (Noe som burde holde deg opptatt i flere timer allerede!) men jeg legger stadig til nytt innhold - Det er mye som er planlagt! - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + Kjøp av spillet gir deg tilgang til den frittstående versjonen som har mange tilleggsfunksjoner og du vil også få tilgang til nyutviklede funksjoner. - [b]Standalone Advantages[/b] + [b]Frittstående fordeler[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Mørk Modus + [*] Ubegrensede Veipunkter + [*] Uendelige Lagringsfiler + [*] Tilleggsinnstillinger + [*] Kommer snart: Ledninger og strøm! Sikter mot (omtrent) slutten av Juli 2020. + [*] Kommer snart: Flere Nivåer + [*] Tillater meg å fortsette å utvikle shapez.io ❤️ [/list] - [b]Future Updates[/b] + [b]Fremtidige Oppdateringer[/b] - I am updating the game very often and trying to push an update at least every week! + Jeg oppdaterer spillet veldig ofte og prøver å presse inn minst en oppdatering hver uke! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Forskjellige nivåer og utfordringer (f.eks. nivåer med hindringer) + [*] Gåter (lever den forspurte formen med et begrenset område / sett med bygninger) + [*] En historiemodus der bygninger har en pris + [*] Konfigurerbar kartgenerator (Konfigurer ressurser/former, størrelse/tetthet, seed og mer) + [*] Flere typer former + [*] Ytelsesforbedringer (Spillet kjører allerede ganske bra!) + [*] Og mye mer! [/list] - [b]This game is open source![/b] + [b]Dette spillet er åpen kildekode![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Hvem som helst kan bidra, Jeg er aktivt involvert i samfunnet og forsøker å gå gjennom alle forslag og ta tilbakemelding i betraktning der det er mulig. + Sørg for å sjekke trello panelet mitt for hele veikartet! - [b]Links[/b] + [b]Lenker[/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Offisiell Discord[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Veikart[/url] [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://github.com/tobspr/shapez.io]Kildekode (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Hjelp til å oversette[/url] [/list] - discordLink: Official Discord - Chat with me! + discordLink: Offisiell Discord - Chat med meg! global: loading: Laster @@ -91,6 +92,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -138,17 +142,16 @@ mainMenu: changelog: Endringshistorikk importSavegame: Importer openSourceHint: Dette spillet er åpen kildekode! - discordLink: Offisiel Discord Server + discordLink: Offisiel Discord-Server helpTranslate: Hjelp oversetting! # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - Beklager, men spillet er kjent for å kjøre sakte på din nettleser! Skaff deg frittstående versjon, eller last ned Chrome for den fulle opplevelsen. + Beklager, men spillet er kjent for å kjøre sakte i din nettleser! Skaff deg den frittstående versjonen, eller last ned Chrome for den fulle opplevelsen. savegameLevel: Nivå savegameLevelUnknown: Ukjent Nivå - continue: Fortsett newGame: Nytt Spill madeBy: Laget av @@ -169,14 +172,14 @@ dialogs: showKeybindings: Se Hurtigtaster importSavegameError: - title: Importerings feil + title: Importeringsfeil text: >- Kunne ikke importere lagringsfilen: importSavegameSuccess: title: Lagringsfil importert text: >- - Din Lagringsfil ble vellykket importert. + Din Lagringsfil ble importert. gameLoadFailure: title: Lagringsfilen er ødelagt @@ -203,20 +206,20 @@ dialogs: desc: Trykk på knappen eller museknappen du vil tildele, eller escape for å avbryte. resetKeybindingsConfirmation: - title: Nullstill Hurtigtaster - desc: Dette vil nullstille alle hurtigtaster tilbake til standard. Vennligst bekreft. + title: Tilbakestill Hurtigtaster + desc: Dette vil tilbakestille alle hurtigtaster. Er du sikker?. keybindingsResetOk: - title: Hurtigtaster nullstilt - desc: Hurtigtastene har blitt nullstilt tilbake til standard! + title: Hurtigtaster tilbakestillt + desc: Hurtigtastene har blitt tilbakestillt til standard! featureRestriction: - title: Demo Versjon - desc: Du prøvde å benytte deg av en funksjon () som ikke er tilgjengelig i demoen. Vurder å skaffe frittstående versjon for den fulle opplevelsen! + title: Demoversjon + desc: Du prøvde å benytte deg av en funksjon () som ikke er tilgjengelig i demoen. Vurder å skaffe den frittstående versjonen for den fulle opplevelsen! oneSavegameLimit: - title: Begrenset Lagringsfiler - desc: Du kan du ha en lagringsfil om gangen i demo versjonen. Vennligst slett den eksisterende, eller skaff frittstående versjon! + title: Begrenset antall Lagringsfiler + desc: Du kan du ha en lagringsfil om gangen i demoversjonen. Vennligst slett den eksisterende, eller skaff den frittstående versjonen! updateSummary: title: Ny oppdatering!! @@ -235,7 +238,7 @@ dialogs: Du skal til å slette mange bygninger ( for å være nøyaktig)! Er du sikker på at du ønsker å gjøre dette? massCutConfirm: - title: Bekreft Klipping + title: Bekreft Utlipping desc: >- Du klipper ut mange bygninger ( for å være nøyaktig)! Er du sikker på at du ønsker å gjøre dette? @@ -250,23 +253,23 @@ dialogs: Spillet har mange hurtigtaster som gjør det enklere å bygge store fabrikker. Her er noen få, men sørg for å sjekke ut hurtigtaster!

CTRL + Dra: Velg et område.
- SHIFT: Hold trykket for å plassere flere av en bygning.
- ALT: Inverter orientasjon av plasserte belter.
+ SHIFT: Hold inne for å plassere flere av en bygning.
+ ALT: Inverter rettning på plasserte samlebånd.
createMarker: title: Ny Markør - desc: Gi markøren et meningsfullt navn, du kan også inkludere "short key" av et objekt (Som du kan generere her) - titleEdit: Edit Marker + desc: Gi markøren et meningsfullt navn, du kan også inkludere en "short key" av et objekt (Som du kan generere her) + titleEdit: Rediger markør markerDemoLimit: - desc: Du kan kun ha to markører i demo verjsonen. Skaff deg frittstående versjon for ubegrensede markører! + desc: Du kan kun ha to markører i demoverjsonen. Skaff deg den frittstående versjonen for ubegrensede markører! exportScreenshotWarning: title: Eksporter skjermbilde desc: Du forespurte å eksportere bilde av basen din som et skjermbilde. Vær obs på at dette kan ta lang tid for en stor base, og i verste fall kræsje spillet ditt (Husk å lagre først)! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + title: Bekreft Utklipping + desc: Du har ikke råd til å lime inn dette området! er du sikker på at du vil klippe det ut? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -290,7 +293,7 @@ ingame: copySelection: Kopier clearSelection: Fjern Valgte pipette: Pipette - switchLayers: Switch layers + switchLayers: Bytt lag # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -362,7 +365,7 @@ ingame: playtime: Spilletid buildingsPlaced: Bygninger - beltsPlaced: Belter + beltsPlaced: Samlebånd buttons: continue: Fortsett @@ -390,7 +393,7 @@ ingame: interactiveTutorial: title: Opplæring hints: - 1_1_extractor: Plasser en utdrager på toppen av en sirkel form for å samle den! + 1_1_extractor: Plasser en utdrager på toppen av en sirkelform for å samle den! 1_2_conveyor: >- Koble utdrageren med et transportbånd til hovedbygningen!

Tips: Trykk og dra beltet med musa! @@ -406,7 +409,7 @@ ingame: cyan: Cyan white: Hvit uncolored: Ingen farge - black: Black + black: Svart shapeViewer: title: Lag empty: Tom @@ -415,7 +418,7 @@ ingame: # All shop upgrades shopUpgrades: belt: - name: Belter, Distributører & Tuneller + name: Belter, Distributører & Tunneler description: Hastighet x → x miner: name: Utdrager @@ -436,7 +439,7 @@ buildings: belt: default: - name: &belt Transportbånd + name: &belt Samlebånd description: Transporterer objekter, hold og dra for å plassere flere. miner: # Internal name for the Extractor @@ -450,7 +453,7 @@ buildings: underground_belt: # Internal name for the Tunnel default: - name: &underground_belt Tunell + name: &underground_belt Tunnel description: Lar deg bruke tuneller for å transportere objekter under bygninger og belter. tier2: @@ -473,23 +476,26 @@ buildings: cutter: default: name: &cutter Kutter - description: Kutter objekter fra top til bunn og spytter ut begge halvdeler. Hvis du bare skal bruke den ene biten, sørg for å ødelegge den andre biten ellers vil det låse seg! + description: Kutter objekter fra top til bunn og spytter ut begge halvdeler. Hvis du bare skal bruke den ene biten, sørg for å ødelegge den andre biten ellers vil det stoppe opp! quad: name: Kutter (4-Veis) - description: Kutter objekter til 4 biter. Hvis du bare skal bruke den ene biten, sørg for å ødelegge den andre biten ellers vil det låse seg! + description: Kutter objekter til 4 biter. Hvis du bare skal bruke den ene biten, sørg for å ødelegge den andre biten ellers vil det stoppe opp! rotater: default: name: &rotater Roter - description: Roter objekter med klokken, 90 grader. + description: Roter former med klokken, 90 grader. ccw: name: Roter (Mot klokken) - description: Roter objekter mot klokken, 90 grader. + description: Roter former mot klokken, 90 grader. + fl: + name: Rotate (180) + description: Roterer former 180 grader. stacker: default: name: &stacker Stabler - description: Stabler begge objekter. Hvis de ikke kan bli stablet sidelengs, vil høyre stables over den andre. + description: Stabler begge formene. Hvis de ikke kan bli stablet sidelengs, vil høyre stables over den andre. mixer: default: @@ -499,13 +505,13 @@ buildings: painter: default: name: &painter Maler - description: &painter_desc Maler hele objektet på venstre inngang med fargen fra øverste inngang. + description: &painter_desc Maler hele formen på venstre inngang med fargen fra øverste inngang. double: name: Maler (Dobbel) - description: Maler hele objektet på venstre inngang med fargen fra øverste inngang. + description: Maler hele formen på venstre inngang med fargen fra øverste inngang. quad: - name: Maler (Fireganger) - description: Farger enhver kvadrant av objektet med forskjellige farger. + name: Maler (Firedobbel) + description: Farger hvert hjørne av formen med forskjellige farger. mirrored: name: *painter description: *painter_desc @@ -513,38 +519,38 @@ buildings: trash: default: name: &trash Søppelkasse - description: Tar imot objekter fra alle sider og ødelegger de. For alltid. + description: Tar imot former og farger fra alle sider og ødelegger de. For alltid. storage: name: Lagringsboks - description: Lagrer overflødige objekter, opp til en viss kapasitet. Kan bli brukt som mellomlagring for overflyt. + description: Lagrer overflødige former og farger, opp til en viss kapasitet. Kan bli brukt som mellomlagring for overflyt. wire: default: - name: Energy Wire - description: Allows you to transport energy. + name: Energikabel + description: Lar deg transportere energi. advanced_processor: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + name: Fargeinverterer + description: Tar imot en farge eller form og inverterer den. energy_generator: - deliver: Deliver + deliver: Lever toGenerateEnergy: For default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: Energigenerator + description: Genererer energi ved å ta imot former. wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Kabeldeler + description: Deler en energikabel i to. merger: - name: Wire Merger - description: Merges two energy wires into one. + name: Kabelsammenslåer + description: Slår sammen to energikabler til en. storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Kutt Objekter - desc: Du åpnet nettop kutter - den kutter objekter i to fra topp til bunn uavhengig av rotasjon!

Husk å kvitt deg med alt søppel, ellers kiler det seg fast - For dette formålet har du søplekassen, som ødelegger alt du putter i den! + desc: Du åpnet nettop kutter - den kutter former i to fra topp til bunn uavhengig av rotasjon!

Husk å kvitt deg med alt søppel, ellers kiler det seg fast - Derfor har jeg gitt deg søplekassen, som ødelegger alt du putter i den! reward_rotater: title: Rotering @@ -553,7 +559,7 @@ storyRewards: reward_painter: title: Maling desc: >- - Maleren har blitt tilgjengelig - Hent ut fargeressurser (på samme måte som du gjør med objekter) og kombiner det med et objekt i maleren for å male de!

PS: Hvis du er fargeblind, så er det en modus for fargeblinde i instillinger! + Maleren har blitt tilgjengelig - Hent ut fargeressurser (på samme måte som du gjør med objekter) og kombiner det med et objekt i maleren for å male de!

PS: Hvis du er fargeblind, så er det en modus for fargeblinde i instillingene! reward_mixer: title: Fargemikser @@ -565,23 +571,23 @@ storyRewards: reward_splitter: title: Fordeler/Sammenslåer - desc: Den multifunksjonelle fordeleren har blitt tilgjengelig - Den kan brukes til å bygge større fabrikker ved å fordele og slå sammen objekter til flere transportbånd!

+ desc: Den multifunksjonelle fordeleren har blitt tilgjengelig - Den kan brukes til å bygge større fabrikker ved å fordele og slå sammen objekter til flere samlebånd!

reward_tunnel: - title: Tunell - desc: Tunellen har blitt tilgjengelig - Du kan nå transportere objekter under transportbelter og bygninger med den! + title: Tunnel + desc: Tunnelen har blitt tilgjengelig - Du kan nå transportere objekter under samlebånd og bygninger med den! reward_rotater_ccw: - title: Mot klokken rotering + title: Rotering mot klokken desc: Du har åpnte en variant av rotereren - Den tillater rotasjoner mot klokken! For å bygge den, velg rotereren og trykk 'T' for å veksle mellom variantene! reward_miner_chainable: - title: Kjede Utdrager - desc: Du har åpnet kjede utdrageren! Den sender videre sine resurser til andre utdragere så de kan mer effektivt hente ut resurser! + title: Kjedeutdrager + desc: Du har åpnet kjedeutdrageren! Den sender sine resurser videre til andre utdragere så de kan hente ut ressurser mer effektivt! reward_underground_belt_tier_2: - title: Tunell Nivå II - desc: Du har åpnet en ny variant av tunellen - Den har lengre rekkevidde, og du kan også blande de forskjellige tunellene nå! + title: Tunnel Nivå II + desc: Du har åpnet en ny variant av tunnelen - Den har lengre rekkevidde, og du kan også blande de forskjellige tunnelene nå! reward_splitter_compact: title: Kompakt Utjevning @@ -594,50 +600,51 @@ storyRewards: reward_painter_double: title: Dobbel Maling - desc: Du har åpnet en variant av maleren - Den fungerer som vanlig maler, men prosesserer to objekter om gangen, konsumerer bare en farge istedenfor to! + desc: Du har åpnet en variant av maleren - Den fungerer som vanlig maler, men maler to objekter om gangen, konsumerer bare en farge istedenfor to! reward_painter_quad: - title: Firegangers Maling + title: 4-Veis Maling desc: Du har åpnet en variant av maleren - Den lar deg male hver del av objektet individuelt! reward_storage: - title: Lagrings Buffer - desc: Du har åpnet en variant av søplekassen - Den lar deg lagre objekter opp til en viss mengde! + title: Lagringsbuffer + desc: Du har åpnet en variant av søpplekassen - Den lar deg lagre objekter opp til en viss mengde! reward_freeplay: title: Frispill - desc: Du klarte det! Du åpnet frispill modus! Dette betyr at formene er nå tilfeldig generert! (Frykt ikke, mer innhold er planlagt for frittstående versjon!) + desc: Du klarte det! Du åpnet frispillmodus! Dette betyr at formene er nå tilfeldig generert! (Ikke vær redd, mer innhold er planlagt for den frittstående versjonen!) reward_blueprints: title: Blåkopier - desc: Du kan nå kopiere og lime inn deler av fabrikken din! Velg et område (Hold inne CTRL, så dra med musa), trykk så 'C' for å kopiere det.

Lime det inn er ikke gratis, du må produsere blåkopi objekter for å få råd til det! (Det du nettop leverte). + desc: Du kan nå kopiere og lime inn deler av fabrikken din! Velg et område (Hold inne CTRL, så dra med musa), trykk så 'C' for å kopiere det.

Lime det inn er ikke gratis, du må produsere blåkopiobjekter for å få råd til det! (Det du nettop leverte). # Special reward, which is shown when there is no reward actually no_reward: title: Neste nivå desc: >- - Dette nivået ga deg ingen belønning, men neste gjør det!

PS: Burde ikke ødelegge din nåværende fabrikk - Du trenger alle de objektene senere for å åpne nye ting! + Dette nivået ga deg ingen belønning, men neste gjør det!

PS: Du burde ikke ødelegge din nåværende fabrikk - Du trenger alle de objektene senere for å åpne nye ting! no_reward_freeplay: title: Neste nivå desc: >- - Gratulerer!! Forresten, mer innhold er planlagt for frittstående versjon! + Gratulerer!! Forresten, mer innhold er planlagt for den frittstående versjonen! settings: title: Instillinger categories: - game: Spill - app: Applikasjon + general: Generelt + userInterface: Brukergrensesnitt + advanced: Avansert versionBadges: dev: Utvikling - staging: Icenesettelse + staging: Iscenesettelse prod: Produksjon buildDate: Bygget labels: uiScale: - title: Grensesnitt skala + title: Grensesnittskala description: >- Endrer størrelsen på brukergrensesnitt. Grensesnittet vil fortsatt skaleres basert på din enhets oppløsning, men denne instillingen styrer mengden den skalerer. scales: @@ -648,9 +655,9 @@ settings: huge: Gigantisk scrollWheelSensitivity: - title: Forstørrelses sensitivitet + title: Forstørrelsessensitivitet description: >- - Endrer hvor sensitiv forstørringen er (Enten musehjulet eller trackpad). + Endrer hvor sensitiv forstørringen er (Enten musehjulet eller museplate). sensitivity: super_slow: Veldig Sakte slow: Sakte @@ -663,7 +670,7 @@ settings: description: >- Endrer hvor raskt bildet beveger seg når man bruker tastaturet. speeds: - super_slow: Veldig Sakte slow + super_slow: Veldig Sakte slow: Sakte regular: Vanlig fast: Raskt @@ -683,30 +690,30 @@ settings: soundsMuted: title: Skru av lyder description: >- - Hvis aktivert, skrur av alle lydeffekter. + Skrur av alle lydeffekter. musicMuted: title: Skru av Musikk description: >- - Hvis aktivert, skrur av all musikk. + Skrur av all musikk. theme: title: Spilltema description: >- - Velg spilltema (lys / mørk). + Velg spilltema (lyst / mørk). themes: dark: Mørk - light: Lys + light: Lyst refreshRate: - title: Simulerings Mål + title: Simuleringsmål description: >- Hvis du har en 144hz skjerm, endre oppdateringsfrekvensen her så vil spillet simuleres mer korrekt på høyere oppdateringsfrekvenser. Dette kan redusere FPS om din PC er for treg. alwaysMultiplace: title: Plasser flere description: >- - Hvis aktivert, alle bygg vil forbli valgt etter plassering inntil du avbryter det. Dette tilsvarer å holde SHIFT nede permanent. + Hvis aktivert vil alle bygg forbli valgt etter plassering inntil du avbryter det. Dette tilsvarer å holde SHIFT nede permanent. offerHints: title: Hint & Opplæring @@ -716,8 +723,8 @@ settings: enableTunnelSmartplace: title: Smarte Tuneller description: >- - Når aktivert, plassering av tuneller vil automatisk fjerne unødvendige bånd. - Dette lar deg også dra og slippe tuneller, og overflødige tuneller blir fjernet. + Når aktivert vil plassering av tunneler automatisk fjerne unødvendige bånd. + Dette lar deg også dra og slippe tunneler, og overflødige tunneler blir fjernet. vignette: title: Vignett description: >- @@ -739,21 +746,21 @@ settings: compactBuildingInfo: title: Kompakt Bygningsinformasjon description: >- - Forkorter informasjonsboksen for bygninger ved å bare vise dems forhold. Ellers - vises en beskrivelse og bilde er vist. + Forkorter informasjonsboksen for bygninger ved å bare vise deres forhold. Ellers + vises en beskrivelse og et bilde. disableCutDeleteWarnings: - title: Deaktiverer Kutt/Slette Advarsler + title: Deaktiverer Utklipps- og Sletteadvarsler description: >- - Deaktiverer advarselsdialogen som kommer frem når du kutter/sletter mer enn 100 + Deaktiverer advarselsmeldingen som kommer frem når du klipper ut eller sletter mer enn 100 bygninger. enableColorBlindHelper: - title: Fargeblind Modus + title: Fargeblindmodus description: Aktiverer forskjellige verktøy som lar deg spille spillet om du er fargeblind. rotationByBuilding: title: Roter basert på bygningstype description: >- - Hver bygning type husker rotasjonen du sist brukte individuelt. + Hver bygningstype husker rotasjonen du sist brukte på dee. Dette kan være mer komfortabelt hvis du ofte veksler mellom plassering av forskjellige bygninger. @@ -770,8 +777,8 @@ keybindings: navigation: Navigering placement: Plassering massSelect: Velg Masse - buildings: Bygnings Snarvei - placementModifiers: Plasserings Alternativer + buildings: Bygningssnarvei + placementModifiers: Plasseringsalternativer mappings: confirm: Bekreft @@ -791,7 +798,7 @@ keybindings: menuOpenStats: Statistikk toggleHud: Veksle Grensesnitt - toggleFPSInfo: Veksle FPS og debug informasjon + toggleFPSInfo: Veksle FPS-og debuginformasjon exportScreenshot: Eksporter hele basen som et bilde belt: *belt splitter: *splitter @@ -815,19 +822,19 @@ keybindings: massSelectStart: Hold og dra for å starte massSelectSelectMultiple: Velg flere områder massSelectCopy: Kopier Område - massSelectCut: Kutt ut Område + massSelectCut: Klipp ut Område placementDisableAutoOrientation: Deaktiver automatisk orientering placeMultiple: Forbli i plasseringsmodus - placeInverse: Inverter automatisk transportbånd orientering - lockBeltDirection: Enable belt planner + placeInverse: Inverter automatisk samlebåndsorientering + lockBeltDirection: Aktiver samlebåndplanlegger switchDirectionLockSide: "Planlegger: Bytt side" pipette: Pipette - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire + menuClose: Lukk meny + switchLayers: Bytt lag + advanced_processor: Fargeinverterer + energy_generator: Energigenerator + wire: Energikabel about: title: Om dette spillet @@ -836,11 +843,11 @@ about: Hvis du ønsker å bidra, sjekk ut shapez.io på github.

- Spillet ville ikke vært mulig uten det fantastidke discord samfunnet rundt spillet mitt - Du burde virkelig bli med på discord serveren!

+ Spillet ville ikke vært mulig uten det fantastiske Discord-samfunnet rundt spillet mitt - Du burde virkelig bli med på Discord-serveren!

Lydsporet er laget av Peppsen - Han er rå.

- Til slutt, stor takk til min beste venn Niklas - Uten våre factorio økter ville ikke dette spillet ha eksistert. + Til slutt, en stor takk til min beste venn Niklas - Uten våre factorio-økter ville ikke dette spillet ha eksistert. changelog: title: Endringshistorikk @@ -851,6 +858,6 @@ demo: importingGames: Importer lagringsfiler oneGameLimit: Begrenset til en lagringsfil customizeKeybindings: Forandre Hurtigtaster - exportingBase: Eksporter hele basen som bile + exportingBase: Eksporter hele basen som bilde settingNotAvailable: Ikke tilgjengelig i demoversjonen. diff --git a/translations/base-pl.yaml b/translations/base-pl.yaml index f60fede8..cb5f56de 100644 --- a/translations/base-pl.yaml +++ b/translations/base-pl.yaml @@ -15,10 +15,11 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io to gra polegająca na budowaniu fabryki automatyzującej tworzenie i łączenie ze sobą coraz bardziej skomplikowanych kształtów na mapie, która nie ma końca. @@ -30,59 +31,59 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.io to gra o budowie fabryk, która automatyzuje tworzenie i przetwarzanie coraz bardziej złożonych kształtów na nieskończenie powiększającej się mapie. + Po dostarczeniu wymaganych kształtów będziesz postępować w grze i odblokowywać ulepszenia, aby przyspieszyć fabrykę. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Wraz ze wzrostem zapotrzebowania na kształty, będziesz musiał powiększyć swoją fabrykę, aby zaspokoić popyt - Nie zapominaj jednak o zasobach, będziesz musiał rozwinąć się na [b] nieskończonej mapie [/ b]! - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Wkrótce będziesz musiał mieszać kolory i malować nimi kształty - Połącz zasoby kolorów czerwonego, zielonego i niebieskiego, aby uzyskać różne kolory i pomalować kształty, aby zaspokoić popyt. - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Ta gra oferuje 18 poziomów progresywnych (które powinny być zajęte przez wiele godzin!), Ale ciągle dodam nowe treści - Wiele jest zaplanowanych! - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + Zakup gry daje dostęp do samodzielnej wersji, która ma dodatkowe funkcje, a także dostęp do nowo opracowanych funkcji. - [b]Standalone Advantages[/b] + [b]Samodzielne zalety[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Tryb ciemny + [*] Nieograniczone punkty trasy + [*] Nieograniczona liczba zapisanych gier + [*] Dodatkowe ustawienia + [*] Wkrótce: przewody i energia! Dążenie do (z grubsza) końca lipca 2020 r. + [*] Wkrótce: Więcej poziomów + [*] Pozwala mi dalej rozwijać shapez.io ❤️ [/list] - [b]Future Updates[/b] + [b]Przyszłe aktualizacje[/b] - I am updating the game very often and trying to push an update at least every week! + Aktualizuję grę bardzo często i staram się przesyłać aktualizacje przynajmniej co tydzień! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Różne mapy i wyzwania (np. Mapy z przeszkodami) + [*] Puzzle (Dostarcz żądany kształt z ograniczonym obszarem / zestawem budynków) + [*] Tryb fabularny, w którym budynki kosztują + [*] Konfigurowalny generator map (Konfiguruj rozmiar / gęstość zasobu / kształtu, ziarno i więcej) + [*] Dodatkowe typy kształtów + [*] Ulepszenia wydajności (gra działa już całkiem dobrze!) + [*] I wiele więcej! [/list] - [b]This game is open source![/b] + [b]Ta gra jest open source![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Każdy może się przyłączyć, jestem aktywnie zaangażowany w społeczność i staram się przejrzeć wszystkie sugestie i wziąć pod uwagę opinie tam, gdzie to możliwe. + Zapoznaj się z moją tablicą trello, aby zobaczyć pełną mapę drogową! - [b]Links[/b] + [b]Linki[/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Oficjalna Discord[/url] [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://github.com/tobspr/shapez.io]Kod źródłowy (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Pomóż w tłumaczeniu[/url] [/list] - discordLink: Official Discord - Chat with me! + discordLink: Oficjalny serwer Discord - Porozmawiaj ze mną! global: loading: Ładowanie @@ -91,6 +92,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: " " + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. # Translator note: We don't use SI size units for common speak, but if you want to keep it SI # ...also, Polish has wierd nature of diffrent number naming, we have "million" and "milliard"-thing wich actually is billion in English @@ -153,7 +157,6 @@ mainMenu: savegameLevel: Poziom savegameLevelUnknown: Nieznany poziom - madeBy: Gra wykonana przez subreddit: Reddit @@ -254,8 +257,7 @@ dialogs: createMarker: title: Nowy Znacznik desc: Podaj nazwę znacznika. Możesz w niej zawrzeć kod kształtu, który możesz wygenerować tutaj. - titleEdit: Edit Marker - + titleEdit: Edytuj Znacznik markerDemoLimit: desc: Możesz stworzyć tylko dwa własne znaczniki w wersji demo. Zakup pełną wersję gry dla nielimitowanych znaczników! @@ -272,8 +274,8 @@ dialogs: Czy na pewno chcesz kontynuować? massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + title: Potwierdź wycinanie + desc: Nie posiadasz wystarczająco kształtów schematów na wklejenie tego obszaru! Czy na pewno chcesz go wyciąć? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -297,7 +299,7 @@ ingame: copySelection: Skopiuj clearSelection: Wyczyść zaznaczenie pipette: Wybierz obiekt z mapy - switchLayers: Switch layers + switchLayers: Przełącz warstwy # Names of the colors, used for the color blind mode colors: @@ -309,7 +311,7 @@ ingame: cyan: Cyjanowy white: Biały uncolored: Brak koloru - black: Black + black: Czarny # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -355,7 +357,7 @@ ingame: # 2nd translator's note: I think translating this to "level" is better (and that's how Google Translate translates it :)) tier: Poziom - # The roman number for each tier + # The roman numeral for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] maximumLevel: POZIOM MAKSYMALNY (Szybkość x) @@ -412,7 +414,7 @@ ingame: shapeViewer: title: Poziomy empty: Puste - copyKey: Copy Key + copyKey: Skopiuj kod # Interactive tutorial interactiveTutorial: @@ -498,6 +500,9 @@ buildings: ccw: name: Obracacz (Przeciwny kierunek) description: Obraca kształt przeciwnie do ruchu wskazówek zegara o 90 stopni. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -534,25 +539,25 @@ buildings: description: Magazynuje obiekty, do określonego limitu. Może zostać użyty jako bramka przepełnienia. wire: default: - name: Energy Wire - description: Allows you to transport energy. + name: Przewód energetyczny + description: Pozwala na transportowanie energii. advanced_processor: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + name: Odwracacz kolorów + description: Przyjmuje barwnik lub kształt i odwraca jego kolory. energy_generator: - deliver: Deliver - toGenerateEnergy: For + deliver: Dostarcz + toGenerateEnergy: Za default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: Generator energii + description: Generuje energię poprzez zużywanie kształtów. wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Rozdzielacz przewodów + description: Rozdziela przewód energetyczny na dwa. merger: - name: Wire Merger - description: Merges two energy wires into one. + name: Łącznik przewodów + description: Łączy dwa przewody energetyczne w jeden. storyRewards: # Those are the rewards gained from completing the store @@ -651,8 +656,9 @@ storyRewards: settings: title: Ustawienia categories: - game: Gra - app: Aplikacja + general: Ogólne + userInterface: Interfejs + advanced: Zaawansowane versionBadges: dev: Wersja Rozwojowa @@ -774,14 +780,14 @@ settings: 100 budynków. enableColorBlindHelper: - title: Color Blind Mode - description: Enables various tools which allow to play the game if you are color blind. + title: Tryb dla daltonistów + description: Włącza różne narzędzia, które pozwalają ci grać, jeśli jesteś daltonistą. rotationByBuilding: - title: Rotation by building type + title: Obrót według typu budynku description: >- - Each building type remembers the rotation you last set it to individually. - This may be more comfortable if you frequently switch between placing - different building types. + Każdy typ budynku pamięta obrót, który ostatnio ustawiłeś indywidualnie. + Może to być wygodniejsze, jeśli często przełączasz się między umieszczaniem + różne typy budynków. keybindings: title: Klawiszologia @@ -817,6 +823,7 @@ keybindings: toggleHud: Przełącz widoczność interfejsu toggleFPSInfo: Pokaż Licznik FPS i informacje do debugowania + belt: *belt splitter: *splitter underground_belt: *underground_belt @@ -841,7 +848,7 @@ keybindings: placementDisableAutoOrientation: Wyłącz automatyczną orientację placeMultiple: Pozostań w trybie stawiania - placeInverse: Odwróć automatyczną orientację pasów + placeInverse: Odwróć automatyczną orientację taśmociągów pasteLastBlueprint: Wklej ostatnio skopiowany obszar massSelectCut: Wytnij obszar exportScreenshot: Wyeksportuj całą fabrykę jako zrzut ekranu @@ -849,11 +856,11 @@ keybindings: switchDirectionLockSide: >- Planowanie taśmociągu: Zmień stronę pipette: Wybieranie obiektów z mapy - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire + menuClose: Zamknij Menu + switchLayers: Przełącz warstwy + advanced_processor: Kolor Falownika + energy_generator: Generator Energii + wire: Przewód Energetyczny about: title: O Grze diff --git a/translations/base-pt-BR.yaml b/translations/base-pt-BR.yaml index b4ce97a4..bf269558 100644 --- a/translations/base-pt-BR.yaml +++ b/translations/base-pt-BR.yaml @@ -15,14 +15,18 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io é um jogo sobre construir fábricas, automatizando a criação e combinação de formas cada vez mais complexas num mapa infinito. + # This is the text shown above the Discord link + discordLink: Discord Oficial - Converse comigo! + # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: # - Do not translate the first line (This is the gif image at the start of the store) @@ -30,60 +34,59 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.io é um jogo sobre construir fábricas, automatizando a criação e combinação de formas cada vez mais complexas num mapa infinito. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Após a entrega das formas requisitadas você progredirá no jogo e desbloqueará melhorias para acelerar sua fábrica. - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Conforme sua demanda por formas aumenta, você irá que aumentar sua fábrica para alcançar-la - Mas não se esqueça dos recursos, você precisará expandir pelo [b]mapa infinito[/b]! - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Rapidamente você vai ter que misturar cores e pintar suas formas com elas - Combine recursos vermelhos, verdes e azuis para produzir cores diferentes e pintar formas com elas para satisfazer a demanda. - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + O jogo contém 18 níveis progressivos (Que já devem manter você ocupado por horas!) mas eu adiciono novo contéudo constantemente - Tem bastante coisa já planejada! - [b]Standalone Advantages[/b] + Comprando o jogo você terá acesso à versão completa, que contém recursos adicionais, e além disso você também terá acesso aos recursos que seram desenvolvidos. + + [b]Vantagens da versão completa[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Modo Escuro + [*] Pontos de Referência Ilimitados + [*] Quantidade de Saves Ilimitada + [*] Configurações adicionais + [*] Em Breve: Fios e Energia! Previsto para (mais ou menos) o fim de Julho de 2020. + [*] Em Breve: Mais Níveis + [*] Me permite desenvolver shapez.io ❤️ [/list] - [b]Future Updates[/b] + [b]Atualizações Futuras[/b] - I am updating the game very often and trying to push an update at least every week! + Eu lanço atualizações frequentemente e estou tentando lançar pelo menos um por semana! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Mapas diferentes e desafios (por exemplo mapas com obstáculos) + [*] Puzzles (Entregue a forma pedida com uma área restringida ou um certo conjunto de construções) + [*] Um modo história onde as construções têm um custo + [*] Um geredor de mapa customizável (Configure recursos, forma, tamanho, densidade, semente e mais) + [*] Mais tipos de formas + [*] Melhorias de desempenho (O jogo já roda bem!) + [*] E muito mais! [/list] - [b]This game is open source![/b] + [b]Esse jogo tem código aberto![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Qualquer um pode contribuir, eu estou ativamente envolvido com a comunidade e tento ler todas as sugestões e levar o feedback em consideração quando possível. + Para uma lista completa dos planos para o futuro, não se esqueça de dar uma olhada no meu quadro do Trello! [b]Links[/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Discord oficial[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Planos para o futuro[/url] [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://github.com/tobspr/shapez.io]Código fonte(GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Ajude a traduzir[/url] [/list] - discordLink: Official Discord - Chat with me! - global: loading: Carregando error: Erro @@ -91,6 +94,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "." + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "," + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: K @@ -131,14 +137,19 @@ demoBanners: # This is the "advertisement" shown in the main menu and other various places title: Versão Demo intro: >- - Pegue a versão completa para desbloquear todas os recursos + Pegue a versão completa para desbloquear todas os recursos! mainMenu: play: Jogar + continue: Continuar + newGame: Novo jogo changelog: Changelog + subreddit: Reddit importSavegame: Importar openSourceHint: Esse jogo tem código aberto! discordLink: Discord oficial + helpTranslate: Ajude a traduzir! + madeBy: Feito por # This is shown when using firefox and other browsers which are not supported. browserWarning: >- @@ -147,13 +158,6 @@ mainMenu: savegameLevel: Nível savegameLevelUnknown: Nível desconhecido - - helpTranslate: Ajude a traduzir! - continue: Continuar - newGame: Novo jogo - madeBy: Feito por - subreddit: Reddit - dialogs: buttons: ok: OK @@ -161,11 +165,11 @@ dialogs: cancel: Cancelar later: Voltar restart: Reiniciar - reset: Reset + reset: Resetar getStandalone: Obter versão completa - deleteGame: Sei o que faço + deleteGame: Sei o que estou fazendo viewUpdate: Atualizações - showUpgrades: Ver melhorias + showUpgrades: Melhorias showKeybindings: Controles importSavegameError: @@ -196,7 +200,7 @@ dialogs: restartRequired: title: Ação necessária text: >- - Voce precisa reiniciar o jogo para aplicar as mudanças. + Você precisa reiniciar o jogo para aplicar as mudanças. editKeybinding: title: Alterar tecla @@ -226,7 +230,7 @@ dialogs: upgradesIntroduction: title: Desbloquear melhorias desc: >- - Todas as formas que você produz podem ser usadas para desbloquear melhorias - Não destrua suas antigas fábricas!! + Todas as formas que você produz podem ser usadas para desbloquear melhorias - Não destrua suas antigas fábricas!! O guia de melhorias pode ser encontrado no canto superior direito da tela. massDeleteConfirm: @@ -234,6 +238,16 @@ dialogs: desc: >- Você está deletando vários objetos ( para ser exato)! Você quer continuar? + massCutConfirm: + title: Confirmar corte + desc: >- + Você está cortando vários objetos ( para ser exato)! Você quer continuar? + + massCutInsufficientConfirm: + title: Confirmar Corte + desc: >- + You can not afford to paste this area! Are you sure you want to cut it? + blueprintsNotUnlocked: title: Não desbloqueado ainda desc: >- @@ -243,41 +257,31 @@ dialogs: title: Teclas úteis desc: >- Este jogo possui muitas combinações de teclas que facilitam a construção de grandes fábricas - Aqui estão algumas, certifique-se de verificar as combinações de teclas !

- CTRL + Arrastar: Seleciona área para copiar / delete.
- SHIFT: Mantenha pressionado para colocar vária construções.
+ Aqui estão algumas, certifique-se de verificar as combinações de teclas!

+ CTRL + Arrastar: Seleciona área para copiar/deletar.
+ SHIFT: Mantenha pressionado para colocar várias construções.
ALT: Inverte as posições.
createMarker: title: Nova Marcação - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) - titleEdit: Edit Marker - markerDemoLimit: - desc: >- - Você só pode criar dois marcadores na versão demo. Adquira a versão completa para marcadores ilimitados! + titleEdit: Editar Marcador + desc: Dê um nome com significado, também pode adicionar um pequeno código de uma forma. (Pode ser gerado aqui) - massCutConfirm: - title: Confirm cut - desc: >- - Você está cortando vários objetos ( para ser exato)! Você quer continuar? + markerDemoLimit: + desc: Você só pode criar dois marcadores na versão demo. Adquira a versão completa para marcadores ilimitados! exportScreenshotWarning: title: Exportar captura de tela - desc: >- - Você está prestes a exportar uma captura de tela da sua base. Note que isso pode ser bastante lento para uma base grande, e até mesmo pode travar o jogo! - - massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + desc: Você está prestes a exportar uma captura de tela da sua base. Note que isso pode ser bastante lento para uma base grande, e até mesmo pode travar o jogo! ingame: # This is shown in the top left corner and displays useful keybindings in # every situation keybindingsOverlay: moveMap: Mover - + selectBuildings: Selecionar área stopPlacement: Parar - rotateBuilding: Rotação + rotateBuilding: Rotacionar placeMultiple: Colocar vários reverseOrientation: Inverter orientação disableAutoOrientation: Desligar orientação automática @@ -285,15 +289,26 @@ ingame: placeBuilding: Construir objeto createMarker: Criar marcador delete: Destruir - selectBuildings: Selecionar área pasteLastBlueprint: Colar último projeto - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side - cutSelection: Cut - copySelection: Copy - clearSelection: Clear Selection - pipette: Pipette - switchLayers: Switch layers + lockBeltDirection: Ativar Planejador de Esteiras + plannerSwitchSide: Girar Planejador + cutSelection: Cortar + copySelection: Copiar + clearSelection: Limpar Seleção + pipette: Conta-Gotas + switchLayers: Trocar Camadas + + # Names of the colors, used for the color blind mode + colors: + red: Vermelho + green: Verde + blue: Azul + yellow: Amarelo + purple: Roxo + cyan: Ciano + white: Branco + black: Preto + uncolored: Sem cor # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -320,7 +335,7 @@ ingame: levelCompleteNotification: # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Nível - completed: Completado + completed: Concluído unlockText: Desbloqueado ! buttonNextLevel: Próximo Nível @@ -332,13 +347,14 @@ ingame: # The "Upgrades" window shop: title: Melhorias - buttonUnlock: Comprar + buttonUnlock: Melhorar # Gets replaced to e.g. "Tier IX" tier: Nível # The roman number for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] + maximumLevel: NÍVEL MÁXIMO (Velocidade x) # The "Statistics" window @@ -347,13 +363,13 @@ ingame: dataSources: stored: title: Estoque - description: Exibindo a quantidade de formas armazenadas em seu edifício central. + description: Exibindo a quantidade de formas armazenadas em sua construção central. produced: title: Produção description: Exibindo todas as formas que toda a sua fábrica produz, incluindo produtos intermediários.. delivered: title: Entregue - description: Exibindo formas entregues ao seu edifício central.. + description: Exibindo formas entregues na sua construção central. noShapesProduced: Nenhuma forma foi produzida até o momento. # Displays the shapes per minute, e.g. '523 / m' @@ -385,98 +401,101 @@ ingame: waypoints: waypoints: Marcadores hub: HUB - description: Clique com o botão esquerdo do mouse em um marcador para pular, clique com o botão direito do mouse para excluí-lo.

Pressione para criar um marcador a partir da exibição atual ou clique com o botão direito do mouse para criar um marcador no local selecionado. + description: Clique com o botão esquerdo do mouse em um marcador para pular, clique com o botão direito do mouse para excluí-lo.

Pressione para criar um marcador a partir da exibição atual ou clique com o botão direito do mouse para criar um marcador no local selecionado. creationSuccessNotification: Marcador criado. - # Interactive tutorial + # Shape viewer + shapeViewer: + title: Camadas + empty: Vazio + copyKey: Copiar Chave + + # Interactive tutorial interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Coloque um extrator em cima de uma fonte de círculo para extraí-lo! + 1_1_extractor: Coloque um extrator em cima de uma fonte de círculo para extraí-lo! 1_2_conveyor: >- - Conecte o extrator com uma esteira transportadora até a sua base!

Dica, clique e arraste a esteira com o mouse! + Conecte o extrator com uma esteira transportadora até a sua base!

Dica, clique e arraste a esteira com o mouse! 1_3_expand: >- - Este NÃO é um jogo inativo! Construa mais extratores e esteiras para concluir o objetivo mais rapidamente.

Dica, segure SHIFT para colocar vários extratores e use R para girá-los. - - colors: - red: Red - green: Green - blue: Blue - yellow: Yellow - purple: Purple - cyan: Cyan - white: White - uncolored: No color - black: Black - shapeViewer: - title: Layers - empty: Empty - copyKey: Copy Key + Este NÃO é um jogo inativo! Construa mais extratores e esteiras para concluir o objetivo mais rapidamente.

Dica, segure SHIFT para colocar vários extratores e use R para girá-los. # All shop upgrades shopUpgrades: belt: name: Esteiras, Distribuidores e Túneis description: Velocidade x → x - miner: name: Extração description: Velocidade x → x - processors: - name: Corte, Rotação e Empilhamento + name: Corte, Rotação e Montagem description: Velocidade x → x - painting: - name: Mistura de cores e pintura + name: Mistura e Pintura description: Velocidade x → x # Buildings and their name / description buildings: + hub: + deliver: Entregue + toUnlock: para desbloquear + levelShortcut: LVL + belt: default: name: &belt Esteira Transportadora description: Transporta itens; mantenha pressionado e arraste para colocar vários. + wire: + default: + name: &wire Fio de Energia + description: Permite transportar energia. + miner: # Internal name for the Extractor default: name: &miner Extrator description: Coloque sobre uma forma ou cor para extraí-la. chainable: - name: Extrator em Cadeia + name: Extrator (em Cadeia) description: Coloque sobre uma forma ou cor para extraí-la. Pode ser ligado a outros extratores. underground_belt: # Internal name for the Tunnel default: name: &underground_belt Túnel - description: Permite transportar recursos sob construções. + description: Permite transportar recursos por baixo de construções e esteiras. tier2: name: Túnel Classe II - description: Permite transportar recursos sob construções. + description: Permite transportar recursos por baixo de construções e esteiras. splitter: # Internal name for the Balancer default: - name: &splitter Balanceador + name: &splitter Distribuidor description: Multifuncional - Distribui uniformemente todas as entradas em todas as saídas. compact: - name: Balanceador (compacto) - description: Mescla duas esteiras transportadoras em uma. + name: Misturador (compacto) + description: Une duas esteiras transportadoras em uma. compact-inverse: - name: Balanceador (compacto) - description: Mescla duas esteiras transportadoras em uma. + name: Misturador (compacto) + description: Une duas esteiras transportadoras em uma. cutter: default: name: &cutter Cortador - description: Corta as formas verticalmente e produz as duas metades. Se você usar apenas uma parte, não se esqueça de destruir a outra parte, ou ela irá parar a produção! + description: Corta as formas verticalmente e produz as duas metades. Se você usar apenas uma parte, não se esqueça de destruir a outra parte, ou ela irá parar a produção! quad: name: Cortador (Quádruplo) - description: Corta as formas em quatro partes. Se você usar apenas uma parte, não se esqueça de destruir as outras, ou ela irá parar a produção! + description: Corta as formas em quatro partes. Se você usar apenas uma parte, não se esqueça de destruir as outras, ou ela irá parar a produção! + + advanced_processor: + default: + name: &advanced_processor Inversor de Cor + description: Aceita uma cor ou forma e a inverte. rotater: default: @@ -485,11 +504,14 @@ buildings: ccw: name: Rotacionador (Anti-horário) description: Gira as formas no sentido anti-horário em 90 graus. + fl: + name: Rotacionador (180) + description: Gira as formas em 180 graus. stacker: default: name: &stacker Empilhador - description: Empilha os dois itens. Se eles não puderem ser mesclados, o item direito será colocado acima do item esquerdo. + description: Empilha os dois itens. Se eles não puderem ser unidos, o item direito será colocado acima do item esquerdo. mixer: default: @@ -500,16 +522,18 @@ buildings: default: name: &painter Pintor description: &painter_desc Colore a forma inteira na entrada esquerda com a cor da entrada direita. - double: - name: Pintor (Duplo) - description: Colore as duas formas na entrada esquerda com a cor da entrada direita. - quad: - name: Pintor (Quádruplo) - description: Permite colorir cada quadrante da forma com uma cor diferente. + mirrored: name: *painter description: *painter_desc + double: + name: Pintor (Duplo) + description: Colore as formas na entrada esquerda com a cor da entrada superior. + quad: + name: Pintor (Quádruplo) + description: Permite colorir cada quadrante da forma com uma cor diferente. + trash: default: name: &trash Lixo @@ -518,58 +542,52 @@ buildings: storage: name: Estoque description: Armazena itens em excesso, até uma determinada capacidade. Pode ser usado como uma porta de transbordamento. - hub: - deliver: Entregue - toUnlock: para desbloquear - levelShortcut: LVL - wire: - default: - name: Energy Wire - description: Allows you to transport energy. - advanced_processor: - default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + energy_generator: - deliver: Deliver - toGenerateEnergy: For + deliver: Entregar + + # This will be shown before the amount, so for example 'For 123 Energy' + toGenerateEnergy: Para + default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: &energy_generator Gerador de Energia + description: Consome formas para gerar energia. + wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: &wire_crossings Divisor de Fios + description: Divide um fio de energia em dois. + merger: - name: Wire Merger - description: Merges two energy wires into one. + name: Misturador de Fios + description: Une dois fios de energia em um. storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Cortando formas - desc: Voce desbloqueou cortador - corte de formas pela metade verticalmente independentemente de sua orientação!

Certifique-se de se livrar do lixo, ou então ele irá parar a produção - Para esse propósito, eu lhe dei um lixo, que destrói tudo o que você coloca nele. + desc: Você desbloqueou cortador - corte de formas pela metade verticalmente independentemente de sua orientação!

Certifique-se de se livrar do lixo, ou então ele irá parar a produção - Para esse propósito, eu lhe dei uma lixeira, que destrói tudo o que você coloca nela! reward_rotater: title: Rotação - desc: O rotacionador foi desbloqueado! Gira as formas no sentido horário em 90 graus. + desc: O rotacionador foi desbloqueado! Gira as formas no sentido horário em 90 graus. reward_painter: title: Pintura desc: >- - The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, there is a color blind mode in the settings! + O Pintor foi desbloqueado - Extrai alguns pigmentos coloridos (assim como você fez com as formas) e combina-os com uma forma no pintor para os colorir!

PS: Se for daltônico, existe um modo daltônico nas definições! reward_mixer: title: Misturando cores - desc: O misturador foi desbloqueado - combine duas cores usando mistura aditiva com esta construção! + desc: O misturador foi desbloqueado - combine duas cores usando mistura aditiva com esta construção! reward_stacker: title: Empilhador - desc: Agora você pode combinar formas com o empilhador! Ambas as entradas são combinadas e, se puderem ser colocadas próximas uma da outra, serão fundidas . Caso contrário, a entrada direita é empilhada em cima da entrada esquerda! + desc: Agora você pode combinar formas com o empilhador! Ambas as entradas são combinadas e, se puderem ser colocadas próximas uma da outra, serão fundidas. Caso contrário, a entrada direita é empilhada em cima da entrada esquerda! reward_splitter: - title: Balanceador - desc: O balanceador multifuncional foi desbloqueado - pode ser usado para construir fábricas maiores dividindo e unindo itens em múltiplas esteiras!

+ title: Distribuidor + desc: O Distribuidor multifuncional foi desbloqueado - pode ser usado para construir fábricas maiores dividindo e unindo itens em múltiplas esteiras!

reward_tunnel: title: Túnel @@ -588,8 +606,9 @@ storyRewards: desc: Você desbloqueou uma nova variante do túnel - ele tem um maior alcance, e também pode atravessar outros túneis na mesma linha! reward_splitter_compact: - title: Balanceador compacto - desc: Você desbloqueou uma variante compacta do balanceador - ele aceita duas entradas e as mescla em uma! + title: Distribuidor compacto + desc: >- + Você desbloqueou uma variante compacta do Distribuidor - ele aceita duas entradas e as une em uma! reward_cutter_quad: title: Cortador quádruplo @@ -597,7 +616,7 @@ storyRewards: reward_painter_double: title: Pintura dupla - desc: Você desbloqueou uma variante do pintor - funciona como o pintor regular, mas processa duas formas ao mesmo tempo , consumindo apenas uma cor em vez de duas! + desc: Você desbloqueou uma variante do pintor - funciona como o pintor regular, mas processa duas formas ao mesmo tempo, consumindo apenas uma cor em vez de duas! reward_painter_quad: title: Pintura quádrupla @@ -613,7 +632,7 @@ storyRewards: reward_blueprints: title: Projetos - desc: Agora você pode copiar e colar partes de sua fábrica! Selecione uma área (mantenha pressionada a tecla CTRL e arraste com o mouse) e pressione 'C' para copiá-la.

Colar não é de graça, é necessário produzir formas de projeto para pagar! (Aquelas que você acabou de entregar). + desc: Agora você pode copiar e colar partes de sua fábrica! Selecione uma área (mantenha pressionada a tecla CTRL e arraste com o mouse) e pressione 'C' para copiá-la.

Colar não é de graça, é necessário produzir formas do projeto para pagar! (Aquelas que você acabou de entregar). # Special reward, which is shown when there is no reward actually no_reward: @@ -624,13 +643,14 @@ storyRewards: no_reward_freeplay: title: Próximo nível desc: >- - Parabéns! Não se esqueça, existe muita coisa planejada para a versão completa. + Parabéns! Aliás, mais conteúdo vindo na versão completa! settings: title: opções categories: - game: Jogo - app: Aplicação + general: Geral + userInterface: Interface de Usuário + advanced: Avançado versionBadges: dev: Desenvolvedor @@ -644,23 +664,58 @@ settings: description: >- Altera o tamanho da fonte do usuário. A interface ainda será dimensionada com base na resolução do dispositivo, mas essa configuração controla a escala do texto. scales: - super_small: Super pequeno + super_small: Super Pequeno small: Pequeno regular: Normal large: Grande huge: Gigante + autosaveInterval: + title: Intervalo de gravação automática + description: >- + Controla a frequência com que o jogo salva automaticamente. Você também pode desativá-lo totalmente aqui. + + intervals: + one_minute: 1 Minuto + two_minutes: 2 Minutos + five_minutes: 5 Minutos + ten_minutes: 10 Minutos + twenty_minutes: 20 Minutos + disabled: Desativado + scrollWheelSensitivity: title: Sensibilidade do zoom description: >- Altera a sensibilidade do zoom (roda do mouse ou touchpad). sensitivity: - super_slow: Super lento + super_slow: Super Lento slow: Lento regular: Normal fast: Rápido super_fast: Super Rápido + movementSpeed: + title: Velocidade da câmera + description: >- + Altera a velocidade com que a câmera se move com o teclado. + speeds: + super_slow: Super Lento + slow: Lento + regular: Normal + fast: Rápido + super_fast: Super Rápido + extremely_fast: Extremamente Rápido + + language: + title: Idioma + description: >- + Altera o idioma. Todas as traduções são contribuições de usuários e podem estar incompletas! + + enableColorBlindHelper: + title: Modo daltônico. + description: >- + Permite várias ferramentas que permitem jogar se você é daltônico. + fullscreen: title: Tela Cheia description: >- @@ -669,18 +724,17 @@ settings: soundsMuted: title: Som description: >- - Se ligado o jogo fica mudo + Se ligado, o jogo fica mudo. musicMuted: - title: Musica + title: Música description: >- - Se ligado, a musica fica muda. + Se ligado, a música fica muda. theme: title: Tema description: >- Escolha o tema entre (Claro / Escuro). - themes: dark: Escuro light: Claro @@ -693,70 +747,37 @@ settings: alwaysMultiplace: title: Multiplicidade description: >- - Se ativado, todos os edifícios permanecerão selecionados após o posicionamento até que você o cancele. Isso é equivalente a manter SHIFT permanentemente. + Se ativado, todas as construções permanecerão selecionadas após o posicionamento até que você a cancele. Isso é equivalente a pressionar SHIFT permanentemente. offerHints: title: Dicas e tutoriais description: >- - Se serão oferecidas dicas e tutoriais enquanto estiver jogando. + Se ativado, oferece dicas e tutoriais enquanto se joga. Além disso, esconde certos elementos da interface até certo ponto, para facilitar o começo do jogo. - language: - title: Idioma - description: >- - Altera o idioma. Todas as traduções são contribuições de usuários e podem estar incompletas! - - movementSpeed: - title: Velocidade da câmera - description: Altera a velocidade com que a câmera se move com o teclado. - speeds: - super_slow: Super Lento - slow: Lento - regular: Normal - fast: Rápido - super_fast: Super Rápido - extremely_fast: Extremamente Rápido enableTunnelSmartplace: title: Túneis inteligentes description: >- - Quando colocados, irão remover automaticamente esteiras desnecessárias. - Isso também permite arrastar túneis e túneis em excesso serão removidos. + Quando colocados, irão remover automaticamente esteiras desnecessárias. Isso também permite arrastar túneis e túneis em excesso serão removidos. + vignette: - title: Vignette + title: Vinheta description: >- - Permite o modo vinheta que escurece os cantos da tela e facilita a - leitura do texto. + Permite o modo vinheta que escurece os cantos da tela e facilita a leitura do texto. - autosaveInterval: - title: Intervalo de gravação automática - description: >- - Controla a frequência com que o jogo salva automaticamente. - Você também pode desativá-lo totalmente aqui. - intervals: - one_minute: 1 Minuto - two_minutes: 2 Minutos - five_minutes: 5 Minutos - ten_minutes: 10 Minutos - twenty_minutes: 20 Minutos - disabled: Desativado - compactBuildingInfo: - title: Informações compactas sobre edifícios - description: >- - Reduz as caixas de informações dos edifícios, mostrando apenas suas proporções. - Caso contrário, uma descrição e imagem são mostradas. - disableCutDeleteWarnings: - title: Desativar avisos de recorte / exclusão - description: >- - Desative as caixas de diálogo de aviso exibidas ao cortar / excluir - mais de 100 entidades. - - enableColorBlindHelper: - title: Modo daltônico. - description: Permite várias ferramentas que permitem jogar se você é daltônico. rotationByBuilding: title: Rotação por tipo de construção description: >- - Cada tipo de construção lembra a rotação que você definiu pela última vez individualmente. - Isso pode ser mais confortável se você alternar frequentemente entre a colocação de diferentes tipos de construção. + Cada tipo de construção lembra a rotação que você definiu pela última vez individualmente. Isso pode ser mais confortável se você alternar frequentemente entre a colocação de diferentes tipos de construção. + + compactBuildingInfo: + title: Informações compactas sobre construções + description: >- + Reduz as caixas de informações dos construções, mostrando apenas suas proporções. Caso contrário, uma descrição e imagem são mostradas. + + disableCutDeleteWarnings: + title: Desativar avisos de recorte / exclusão + description: >- + Desative as caixas de diálogo de aviso exibidas ao cortar / excluir mais de 100 entidades. keybindings: title: Controles @@ -781,6 +802,7 @@ keybindings: mapMoveRight: Mover para direita mapMoveDown: Mover para baixo mapMoveLeft: Mover para a esquerda + mapMoveFaster: Mover mais rápido centerMap: Centralizar mapa mapZoomIn: Aproximar @@ -789,66 +811,59 @@ keybindings: menuOpenShop: Melhorias menuOpenStats: Estatísticas + menuClose: Fechar Menu toggleHud: Ocultar Interface - toggleFPSInfo: Mostar FPS + toggleFPSInfo: Mostrar FPS e Debug Info + switchLayers: Alternar Camadas + exportScreenshot: Exportar Base Inteira como Imagem belt: *belt splitter: *splitter underground_belt: *underground_belt miner: *miner cutter: *cutter + advanced_processor: *advanced_processor rotater: *rotater stacker: *stacker mixer: *mixer + energy_generator: *energy_generator painter: *painter trash: *trash + wire: *wire + pipette: Conta-Gotas rotateWhilePlacing: Rotacionar rotateInverseModifier: >- Modifier: Rotação anti-horária cycleBuildingVariants: Variações confirmMassDelete: Confirmar exclusão em massa + pasteLastBlueprint: Colar último projeto cycleBuildings: Trocar de construção + lockBeltDirection: Ativar planejador de correia + switchDirectionLockSide: >- + Planejador: Mudar de lado massSelectStart: Segure e arraste para começar massSelectSelectMultiple: Selecionar mais áreas massSelectCopy: Copiar área + massSelectCut: Cortar área placementDisableAutoOrientation: Desligar orientação automática placeMultiple: Permanecer no modo de construção placeInverse: Inverter orientação de esteira - pasteLastBlueprint: Colar último projeto - massSelectCut: Cortar área - exportScreenshot: Exportar base inteira como imagem - mapMoveFaster: Mover mais rápido - lockBeltDirection: Ativar planejador de correia - switchDirectionLockSide: "Planejador: Mudar de lado" - pipette: Pipeta - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire about: title: Sobre o jogo body: >- - Esse jogo tem código aberto e é desenvolvido por Tobias Springer (esse sou eu).

+ Esse jogo tem código aberto e é desenvolvido por Tobias Springer (esse sou eu).

- Se quiser contribuir, confira shapez.io no github.

+ Se quiser contribuir, confira shapez.io no github.

- O jogo não seria possível sem a comunidade incrível do discord sobre - os meus jogos - Junte-se à comunidade no servidor do discord!

+ O jogo não seria possível sem a comunidade incrível do Discord sobre os meus jogos - Junte-se à comunidade no servidor do Discord!

- A trilha sonora foi feita por Peppsen - Ele é demais.

+ A trilha sonora foi feita por Peppsen - Ele é demais.

- Finalmente, agradeço muito ao meu melhor amigo - Niklas - Sem nossas sessões de Factorio, - esse jogo nunca teria existido. + Finalmente, agradeço muito ao meu melhor amigo Niklas - Sem nossas sessões de Factorio, esse jogo nunca teria existido. changelog: title: Alterações @@ -857,8 +872,8 @@ demo: features: restoringGames: Restaurar jogos salvos importingGames: Carregar jogos salvos - oneGameLimit: Limitado para um jogo salvo + oneGameLimit: Limitado a um jogo salvo customizeKeybindings: Modificar Teclas - exportingBase: Exportar base inteira como imagem + exportingBase: Exportar Base inteira como Imagem settingNotAvailable: Não disponível na versão demo. diff --git a/translations/base-pt-PT.yaml b/translations/base-pt-PT.yaml index f952bcf0..4f16e0a9 100644 --- a/translations/base-pt-PT.yaml +++ b/translations/base-pt-PT.yaml @@ -15,10 +15,11 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io é um jogo cujo objetivo é construir fábricas para automatizar a criação e fusão de formas geométricas cada vez mais complexas num mapa infinito. @@ -30,59 +31,59 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.io é um jogo cujo objetivo é construir fábricas para automatizar a criação e fusão de formas geométricas num mapa infinito. + Ao entregar as formas pedidas, irás progredir no jogo e irás desbloquear melhorias para acelerar a produção da tua fábrica. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Uma vez que a procura aumenta a cada nível, terás de aumentar a tua fábrica para fazer face às necessidades - Para isso, terás de explorar o [b]mapa infinito[/b] para encontrar todos os recursos! - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Rapidamente irás precisar de misturar cores e pintar as formas com elas - Combina os recursos de cores vermelha, verde e azul para produzires mais cores e usá-las para pintar as formas geométricas com o intuito de satisfazer a procura. - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Este jogo conta com 18 níveis (Que deverão manter-te ocupado durante horas!) mas estou constantemente a adicionar novos conteúdos - Há muitas coisas planeadas! - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + Ao comprares o jogo, terás acesso à versão completa, que contém funcionalidades adicionais, e também a conteúdos desenvolvidos recentemente. - [b]Standalone Advantages[/b] + [b]Vantagens do jogo completo[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Modo escuro + [*] Marcos ilimitados + [*] Savegames infinitos + [*] Mais definições + [*] Brevemente: Fios & Energia! Previsto para o final de Julho 2020 (aproximadamente). + [*] Brevemente: Mais níveis + [*] Possibilita-me desenvolver ainda mais o shapez.io ❤️ [/list] - [b]Future Updates[/b] + [b]Atualizações futuras[/b] - I am updating the game very often and trying to push an update at least every week! + Atualizo o jogo frequentemente e tento lançar uma atualização pelo menos todas as semanas! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Mapas diferentes e desafios (por exemplo mapas com obstáculos) + [*] Puzzles (Entrega a forma pedida numa área restrita e/ou com um número limitado de construções) + [*] Modo história onde as construções têm um custo + [*] Criação de mapas configuráveis (Editar o número e tamanho das minas, semente, e mais) + [*] Mais tipos de formas geométricas + [*] Mais melhorias de performance (Apesar do jogo já correr bastante bem!) + [*] E muito mais! [/list] - [b]This game is open source![/b] + [b]Este jogo é open source (código aberto)![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Qualquer pessoa pode contribuir! Adicionalmente, Eu ouço [b]muito[/b] a comunidade! Eu tento ler todas as sugestões e retirar delas tanto feedback quanto possível. + Segue o meu trello board para veres todo o roteiro de desenvolvimento! - [b]Links[/b] + [b]Ligações[/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Discord oficial[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roteiro de desenvolvimento[/url] [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://github.com/tobspr/shapez.io]Código fonte (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Ajuda a traduzir[/url] [/list] - discordLink: Official Discord - Chat with me! + discordLink: Discord oficial - Conversa comigo! global: loading: A carregar @@ -91,6 +92,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -148,7 +152,6 @@ mainMenu: savegameLevel: Nível savegameLevelUnknown: Nível desconhecido - continue: Continuar newGame: Novo Jogo madeBy: Criado por @@ -249,9 +252,9 @@ dialogs: ALT: Inverte as posições.
createMarker: - title: Novo marco + title: Novo Marco desc: Dá-lhe um nome com significado, também poderás adicionar um pequeno código de uma forma. (Pode ser gerado aqui) - titleEdit: Edit Marker + titleEdit: Editar Marco markerDemoLimit: desc: Apenas podes criar dois marcos na versão Demo. Adquire o jogo completo para colocar marcos infinitos! @@ -267,8 +270,8 @@ dialogs: ser um pouco lento para uma base muito grande até mesmo bloquear o teu jogo! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + title: Confirma o corte + desc: Não consegues pagar para colar esta área! Tens a certeza que pretendes cortá-la? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -292,7 +295,7 @@ ingame: copySelection: Copiar clearSelection: Cancelar pipette: Pipeta - switchLayers: Switch layers + switchLayers: Troca de camadas # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -408,11 +411,11 @@ ingame: cyan: Ciano white: Branco uncolored: Sem cor - black: Black + black: Preto shapeViewer: title: Camadas empty: Vazio - copyKey: Copy Key + copyKey: Chave de cópia # All shop upgrades shopUpgrades: @@ -482,6 +485,9 @@ buildings: ccw: name: Rodar (CCW) description: Roda as formas 90º no sentido contrário ao dos ponteiros do relógio. + fl: + name: Rodar (180) + description: Roda as formas 180º. stacker: default: @@ -521,25 +527,25 @@ buildings: levelShortcut: NVL wire: default: - name: Energy Wire - description: Allows you to transport energy. + name: Fio Elétrico + description: Permite o transporte de energia. advanced_processor: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + name: Inversor de Cor + description: Aceita uma cor ou forma e inverte-a. energy_generator: - deliver: Deliver - toGenerateEnergy: For + deliver: Entrega + toGenerateEnergy: Para default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: Gerador de energia + description: Gera energia consumindo formas. wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Repartidor de fios + description: Divide um fio elétrico em dois. merger: - name: Wire Merger - description: Merges two energy wires into one. + name: Conector de fios + description: Junta dois fios elétricos num só. storyRewards: # Those are the rewards gained from completing the store @@ -627,8 +633,9 @@ storyRewards: settings: title: Definições categories: - game: Jogo - app: Aplicação + general: Geral + userInterface: Interface de Utilizador + advanced: Avançado versionBadges: dev: Desenvolvimento @@ -823,11 +830,11 @@ keybindings: lockBeltDirection: Ativa o planeamento de tapetes switchDirectionLockSide: "Planeador: Troca o lado" pipette: Pipeta - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire + menuClose: Fechar Menu + switchLayers: Troca de camadas + advanced_processor: Inversor de Cor + energy_generator: Gerador de energia + wire: Fio Elétrico about: title: Sobre o jogo body: >- @@ -837,9 +844,9 @@ about: Se quiseres contribuir, dá uma olhadela em shapez.io no github.

- Este Jogo não seria possível sem a excelente comunidade do discord + Este Jogo não seria possível sem a excelente comunidade do Discord em torno dos meus jogos - Devias mesmo juntar-te ao servidor no discord!

+ target="_blank">servidor no Discord!

A banda sonora foi feita por Peppsen - Ele é Fantástico.

diff --git a/translations/base-ro.yaml b/translations/base-ro.yaml index 9986f8d6..15d3ff4b 100644 --- a/translations/base-ro.yaml +++ b/translations/base-ro.yaml @@ -15,10 +15,11 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io este un joc despre construirea fabricilor pentru a automatiza crearea și combinarea a din ce in ce mai complexe forme într-o hartă infinită. @@ -91,6 +92,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -148,7 +152,6 @@ mainMenu: savegameLevel: Nivelul savegameLevelUnknown: Nivel necunoscut - continue: Continuă newGame: Joc nou madeBy: Făcut de @@ -481,6 +484,9 @@ buildings: ccw: name: Rotate (CCW) description: Rotește formele în inversul sensului acelor de ceasornic la 90 de grade. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -626,8 +632,9 @@ storyRewards: settings: title: Setări categories: - game: Joc - app: Aplicație + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: Dezvoltare @@ -831,9 +838,9 @@ about: Dacă vrei să contribui, verifică shapez.io pe github.

- Acest joc nu ar fi fost posibil fără minunata comunitate de pe discord + Acest joc nu ar fi fost posibil fără minunata comunitate de pe Discord pe lângă jocurile mele - Chiar ar trebui să te alături server-ului de discord!

+ target="_blank">server-ului de Discord!

Coloana sonoră a fost făcută de Peppsen - Este uimitor.

diff --git a/translations/base-ru.yaml b/translations/base-ru.yaml index 102ccdd8..2e1657aa 100644 --- a/translations/base-ru.yaml +++ b/translations/base-ru.yaml @@ -15,10 +15,11 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io — это игра о строительстве фабрик для автоматизации создания и объединения все более сложных фигур на бесконечной карте. @@ -30,66 +31,69 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.io — это игра о строительстве фабрик для автоматизации создания и объединения все более сложных фигур на бесконечной карте. + Развивайтесь в игре и открывайте улучшения для ускорения фабрики, после доставки запрошенных ресурсов. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + По мере увеличения спроса на фигуры вам придется увеличивать свою фабрику, чтобы удовлетворить спрос. Однако, не забывайте о ресурсах, несмотря на то что вы будете расширятся на [b]бесконечной карте[/b]! - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Вскоре вам придется смешивать цвета и красить ими фигуры. Комбинируйте красный, зеленый и синий красители для получения разных цветов и красьте ими фигуры, чтобы удовлетворить спрос. - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Эта игра имеет 18 уровней развития (но и они займут вас на часы!), но я постоянно добавляю новый контент - там многое запланировано! - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + Покупка игры даст доступ к полной версии, которая имеет дополнительные функции, а также вы получите доступ к недавно разработанным функциям. - [b]Standalone Advantages[/b] + [b]Преимущества полной версии[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Темный Режим + [*] Неограниченные Метки + [*] Неограниченные Сохранения + [*] Дополнительные настройки + [*] Скоро: Провода & Энергия! Запланировано (примерно) на конец июля 2020 года. + [*] Скоро: Больше уровней + [*] Позволит мне дальше разрабатывать shapez.io ❤️ [/list] - [b]Future Updates[/b] + [b]Будущие обновления[/b] - I am updating the game very often and trying to push an update at least every week! + Я очень часто обновляю игру и пытаюсь обновлять ее как минимум каждую неделю! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Различные карты и испытания (например, карты с препятствиями) + [*] Пазлы (Доставить запрошенную фигуру с ограничением пространства / набора зданий) + [*] Режим истории, где здания стоят фигуры + [*] Настраиваемый генератор карт (настройка ресурса / размера фигуры / плотности, семя и т.д.) + [*] Дополнительные типы фигур + [*] Улучшения производительности (игра уже работает довольно хорошо!) + [*] И многое другое! [/list] - [b]This game is open source![/b] + [b]Это игра с открытым исходным кодом![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Любой может внести свой вклад, я активно участвую в жизни сообщества и пытаюсь рассмотреть все предложения и по возможности принять во внимание отзывы. + Не забудьте проверить мою доску Trello со всеми планами! - [b]Links[/b] + [b]Ссылки[/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] - [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Официальный Discord[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Планы[/url] + [*] [url=https://www.reddit.com/r/shapezio]Сабреддит[/url] + [*] [url=https://github.com/tobspr/shapez.io]Исходный код (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Помочь с переводом[/url] [/list] - discordLink: Official Discord - Chat with me! + discordLink: Официальный Discord - Общайся со мной! global: loading: Загрузка error: Ошибка # How big numbers are rendered, e.g. "10,000" - thousandsDivider: "," + thousandsDivider: " " + + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: @@ -139,7 +143,7 @@ mainMenu: changelog: Список изменений importSavegame: Импорт openSourceHint: Это игра с открытым исходным кодом! - discordLink: Оффициальный Дискорд Сервер + discordLink: Офици- альный Дискорд helpTranslate: Помоги с переводом! # This is shown when using firefox and other browsers which are not supported. @@ -149,7 +153,6 @@ mainMenu: savegameLevel: Уровень savegameLevelUnknown: Неизвестный уровень - continue: Продолжить newGame: Новая Игра madeBy: Создал @@ -205,7 +208,7 @@ dialogs: resetKeybindingsConfirmation: title: Сброс управления - desc: Это сбросит все настройки управления к их значениям по умолчанию. Пожалуйста подтвердите. + desc: Это сбросит все настройки управления к их значениям по умолчанию. Подтвердите это действие. keybindingsResetOk: title: Сброс управления @@ -233,12 +236,12 @@ dialogs: massDeleteConfirm: title: Подтвердить удаление desc: >- - Вы удаляете много построек (точнее: )! Вы действительно хотите сделать это? + Вы собираетесь удалить много построек (точнее: )! Вы действительно хотите сделать это? blueprintsNotUnlocked: title: Еще не открыто desc: >- - Чертежи еще не открыты! Завершите больше уровней, что-бы открыть их. + Чертежи еще не открыты! Завершите больше уровней, чтобы открыть их. keybindingsIntroduction: title: Полезные горячие клавиши @@ -252,26 +255,26 @@ dialogs: createMarker: title: Новый маркер desc: Дайте ему содержательное имя, также можно добавить сокращение в виде фигуры (Которое можно сгенерировать здесь) - titleEdit: Edit Marker + titleEdit: Редактирование маркера markerDemoLimit: desc: Вы можете создать только 2 своих маркера в демо-версии. Приобретите полную версию для безлимитных маркеров. massCutConfirm: title: Подтвердите вырезку desc: >- - Вы вырезаете много зданий (точнее: )! Вы уверены, + Вы собираетесь вырезать много зданий (точнее: )! Вы уверены, что хотите это сделать? exportScreenshotWarning: title: Экспорт скриншота desc: >- - Вы запросили экспортировать вашу базу в виде скриншота. Обратите внимание, + Вы собираетесь экспортировать вашу базу в виде скриншота. Обратите внимание, что это может быть довольно медленным процессом для большой базы и даже привести к аварийному завершению игры! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + title: Подтвердите вырезку + desc: Вы не можете позволить себе вставить эту область! Вы уверены, что хотите вырезать ее? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -295,7 +298,7 @@ ingame: copySelection: Копировать clearSelection: Отменить pipette: Пипетка - switchLayers: Switch layers + switchLayers: Переключить слои # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -355,7 +358,7 @@ ingame: title: Производится description: Показывает производящиеся фигуры, включая промежуточное производство. delivered: - title: Доставлено + title: Доставляется description: Показывает фигуры, которые доставляются в хаб. noShapesProduced: Фигуры еще не произведены. @@ -388,8 +391,8 @@ ingame: waypoints: waypoints: Маркеры hub: ХАБ - description: ЛКМ по маркеру, чтобы переместится к нему, ПКМ что-бы удалить.

Нажмите чтобы создать маркер в текущей позиции или ПКМ чтобы выбрать другое место для сождания маркера. - creationSuccessNotification: Маркер был создан. + description: ЛКМ по маркеру, чтобы переместиться к нему, ПКМ, чтобы удалить.

Нажмите чтобы создать маркер в текущей позиции или ПКМ, чтобы выбрать другое место для создания маркера. + creationSuccessNotification: Маркер создан. # Interactive tutorial interactiveTutorial: @@ -411,11 +414,11 @@ ingame: cyan: Бирюзовый white: Белый uncolored: Бесцветный - black: Black + black: Черный shapeViewer: title: Слои empty: Пусто - copyKey: Copy Key + copyKey: Копировать # All shop upgrades shopUpgrades: @@ -437,7 +440,7 @@ buildings: belt: default: name: &belt Конвейер - description: Транспортирует предметы, держите и тащите, чтобы разместить несколько. + description: Транспортирует предметы. Держите и тащите, чтобы разместить несколько. miner: # Internal name for the Extractor default: @@ -445,7 +448,7 @@ buildings: description: Поместите над жилой с фигурами или красителями, чтобы добыть ресурс. chainable: - name: Экстрактор(Цеп.) + name: Цеп. экстрактор description: Поместите над жилой с фигурами или красителями, чтобы добыть ресурс. Может последовательно соединяться в цепь. underground_belt: # Internal name for the Tunnel @@ -472,11 +475,11 @@ buildings: cutter: default: - name: &cutter Резчик - description: Разрезает фигуры сверху вниз и выводит обе половины. Используя только одну часть - уничтожьте другую, иначе производство остановится! + name: &cutter Резак + description: Разрезает фигуры сверху вниз и выводит обе половины. Если Вы собираетесь использовать только одну часть, уничтожьте другую, иначе производство остановится! quad: - name: Резчик (4Вых.) - description: Разрезает фигуры на четыре части. Используя не все части - уничтожьте оставшиеся, иначе производство остановится! + name: Резак (4Вых.) + description: Разрезает фигуры на четыре части. Если Вы собираетесь использовать не все части - уничтожьте оставшиеся, иначе производство остановится! rotater: default: @@ -485,6 +488,9 @@ buildings: ccw: name: Вращатель (Обр.) description: Поворачивает фигуры против часовой стрелки на 90 градусов. + fl: + name: Вращатель (180) + description: Вращает фигуры на 180 градусов. stacker: default: @@ -513,42 +519,42 @@ buildings: trash: default: name: &trash Мусорка - description: Имеет входы со всех сторон. Уничтожает все что принимает, навсегда. + description: Имеет входы со всех сторон. Уничтожает все принимаемые ресурсы. storage: name: Хранилище - description: Хранит лишние предметы, до заданной вместимости. Может использоваться в качестве ворот для пропускания излишков. + description: Хранит лишние предметы до заданной вместимости. Может использоваться в качестве ворот для пропускания излишков. hub: deliver: Доставить toUnlock: чтобы открыть levelShortcut: Ур. wire: default: - name: Energy Wire - description: Allows you to transport energy. + name: Энерг. провод + description: Позволяет транспортировать энергию. advanced_processor: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + name: Инвертор цвета + description: Инвертирует цвета красителей или фигур. energy_generator: - deliver: Deliver - toGenerateEnergy: For + deliver: Доставить + toGenerateEnergy: Для default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: Генератор энергии + description: Производит энергию из фигур. wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Разделитель провода + description: Разделяет энергетический провод на два. merger: - name: Wire Merger - description: Merges two energy wires into one. + name: Соединитель проводов + description: Соединяет два энергетических провода в один. storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Разрезание Фигур - desc: Вы только что открыли резчик - он разрезает фигуры пополам сверху вниз независимо от их ориентации!

Обязательно избавьтесь от отходов, иначе он остановится - для этого я дал вам мусорку, которая уничтожит все, что в нее поместить! + desc: Вы только что открыли резак - он разрезает фигуры пополам сверху вниз независимо от их ориентации!

Обязательно избавьтесь от отходов, иначе он остановится - для этого я дал вам мусорку, которая уничтожит все, что в нее поместить! reward_rotater: title: Вращение @@ -557,7 +563,7 @@ storyRewards: reward_painter: title: Покраска desc: >- - Разблокирован покрасчик! Добудьте краситель из жилы (так же как и фигуры) и объедините его с фигурой в покрасчике, чтобы раскрасить ее!

PS: Если вы дальтоник, то в настройках есть Режим Дальтоника! + Разблокирован покрасчик! Добудьте краситель из жилы (так же, как и фигуры) и объедините его с фигурой в покрасчике, чтобы раскрасить ее!

PS: Если вы дальтоник, то в настройках есть Режим Дальтоника! reward_mixer: title: Смешивание Цветов @@ -573,11 +579,11 @@ storyRewards: reward_tunnel: title: Туннель - desc: Разблокирован туннель! Теперь вы можете транспортировать предметы сквозь конвейеры и здания! + desc: Разблокирован туннель! Теперь вы можете транспортировать предметы под другими конвейерами и зданиями! reward_rotater_ccw: title: Вращатель (обратный) - desc: Разблокирован вариант вращателя, он позволяет вращать фигуры против часовой стрелки! Чтобы построить его, выберите вращатель и нажмите 'T' чтобы переключаться между вариантами! + desc: Разблокирован вариант вращателя, вращающий фигуры против часовой стрелки! Чтобы построить его, выберите вращатель и нажмите 'T', чтобы переключить вариант! reward_miner_chainable: title: Цепной Экстрактор @@ -589,12 +595,11 @@ storyRewards: reward_splitter_compact: title: Компактный Соединитель - desc: >- - Разблокирован компактный вариант разделителя, он объединяет воедино потоки предметов из двух входов! + desc: Разблокирован компактный вариант разделителя, объединяющий потоки предметов из двух входов! reward_cutter_quad: - title: Резчик (4 Выхода) - desc: Разблокирован вариант резчика - он позволяет разрезать фигуры на четыре части вместо, всего лишь двух! + title: Резак (4 Выхода) + desc: Разблокирован вариант резака, разрезающий фигуры на четыре части вместо двух! reward_painter_double: title: Двойной Покрасчик @@ -602,7 +607,7 @@ storyRewards: reward_painter_quad: title: Покрасчик (4 Входа) - desc: Разблокирован вариант покрасчика - он позволяет отдельно раскрашивать каждую часть фигуры! + desc: Разблокирован вариант покрасчика - он позволяет отдельно раскрашивать каждую четверть фигуры! reward_storage: title: Буферное Хранилище @@ -614,13 +619,13 @@ storyRewards: reward_blueprints: title: Чертежи - desc: Теперь вы можете копировать и вставлять части вашей фабрики! Выберите область (Удерживая CTRL, перетащите мышь) и нажмите 'C' чтобы скопировать ее.

Вставка не бесплатна, чтобы позволить себе это вам необходимо произвести фигуры для чертежей! (Которые вы только что доставили). + desc: Теперь вы можете копировать и вставлять части вашей фабрики! Выберите область (Удерживая CTRL, перетащите мышь) и нажмите 'C', чтобы скопировать ее.

Вставка не бесплатна, для этого необходимо произвести фигуры для чертежей! (Которые вы только что доставили). # Special reward, which is shown when there is no reward actually no_reward: title: Следующий уровень desc: >- - Этот уровень не дал вам награды, но следующий даст!

PS: Лучше не разрушайте вашу существующую фабрику - Вам понадобятся все эти фигуры позже, чтобы разблокировать улучшения! + Этот уровень не дал вам награды, но следующий даст!

PS: Лучше не разрушайте вашу существующую фабрику - Вам понадобятся все эти фигуры позже, чтобы разблокировать улучшения! no_reward_freeplay: title: Следующий уровень @@ -630,8 +635,9 @@ storyRewards: settings: title: Настройки categories: - game: Игровые - app: Основные + general: Основные + userInterface: Интерфейс + advanced: Продвинутые versionBadges: dev: Разработчик @@ -730,7 +736,7 @@ settings: title: Интервал авто-сохранения description: >- Управляет тем, как часто игра автоматически сохраняется. - А также здесь можно полностью отключить авто-сохранение. + Также здесь можно полностью отключить авто-сохранение. intervals: one_minute: 1 Минута two_minutes: 2 Минуты @@ -744,7 +750,7 @@ settings: Сокращает отображаемую информацию о зданиях, показывая только их множители. Иначе информация отображается с описанием и изображением. disableCutDeleteWarnings: - title: Отключить Предупреждение о Вырезании\Удалении + title: Отключить Предупреждение о Вырезании/Удалении description: >- Отключает диалоговые окна с предупреждениями, появляющиеся при вырезании/удалении более 100 объектов. @@ -825,11 +831,11 @@ keybindings: lockBeltDirection: Включает конвейерный планировщик switchDirectionLockSide: "Планировщик: Переключение сторон" pipette: Пипетка - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire + menuClose: Закрыть меню + switchLayers: Переключить слои + advanced_processor: Инвертор цвета + energy_generator: Генератор энергии + wire: Энергетический провод about: title: Об игре @@ -837,19 +843,19 @@ about: Эта игра с открытым исходным кодом, разработана Тобиасом Спрингером (это я).

- Если вы хотите внести свой вклад то вам сюда - shapez.io в github.

Эта игра не была бы возможна без большого сообщества в дискорде, которое собралось - вокруг моих игр - Вы действительно должны присоединиться к серверу в дискорде!

+ вокруг моих игр - Вам действительно стоит присоединиться к серверу Discord!!

Саундтрек сделал Peppsen - Он потрясающий.

Наконец, огромное спасибо моему лучшему другу Niklas - Без наших - игровых сессий в factorio эта игра никогда не существовала бы. + игровых сессий в Factorio эта игра никогда не существовала бы. changelog: title: Список изменений diff --git a/translations/base-sl.yaml b/translations/base-sl.yaml index 6d3b6fee..ad084b9d 100644 --- a/translations/base-sl.yaml +++ b/translations/base-sl.yaml @@ -15,16 +15,17 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page - shortText: shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. + shortText: shapez.io je igra grajenja tovarne katere cilj je avtomatiziranje kreiranja in procesiranja vse bolj zapletenih oblik na neskončni ravnini. - # This is the text shown above the discord link - discordLink: Official Discord - Chat with me! + # This is the text shown above the Discord link + discordLink: Uradni Discord - Pridruži se klepetu! # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: @@ -33,56 +34,55 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.io je igra grajenja tovarne katere cilj je avtomatiziranje kreiranja in procesiranja vse bolj zapletenih oblik na neskončni ravnini. + Ob dostavi zahtevanih oblik boste napredovali v igri in odklenili nadgradnje, da boste pospešili tovarno. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Ko se bo povpraševanje po oblikah povečalo, boste morali prilagoditi svojo tovarno, da bo zadostilo povpraševanju. Ne pozabite na vire, morali pa se boste razširiti čez [b]neskončno ravnino[/b]! - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Kmalu boste morali mešati barve in z njimi barvati svoje oblike - Združite rdeče, zelene in modre barvne vire, da ustvarite različne barve in z njimi barvate oblike, da zadostite povpraševanju. - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! - - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + V tej igri je 18 progresivnih stopenj (ki vas bodo zaposlile za več ur!), Vendar nenehno dodajam novo vsebino - načrtovanih novosti je veliko! + Nakup igre vam omogoča dostop do samostojne različice, ki ima dodatne funkcije, prav tako pa boste imeli dostop do novo razvitih funkcij. [img]{STEAM_APP_IMAGE}/extras/header_standalone_advantages.png[/img] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Temna tema + [*] Neomejeno označb + [*] Neomejeno shranjenih tovarn + [*] Dodatne nastavitve + [*] Prihaja kmalu: Žice in energija! Prihajajo (približno) konec julija 2020. + [*] Prihaja kmalu: Več stopenj + [*] Omogoča mi nadaljni razvoj shapez.io ❤️ [/list] [img]{STEAM_APP_IMAGE}/extras/header_future_updates.png[/img] - I am updating the game very often and trying to push an update at least every week! + Igro posodabljam zelo pogosto in poskušam dodati novosti vsaj vsak teden! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Različni zemljevidi in izzivi (npr. Zemljevidi z ovirami) + [*] Izzivi (vnesite želeno obliko z omejenim območjem / nizom zgradb) + [*] Način zgodbe, kjer imajo stavbe stroške/cene + [*] Nastavljiv generator zemljevidov (konfigurirajte velikost / gostoto oblik /, seme in več) + [*] Dodatne vrste oblik + [*] Izboljšanje zmogljivosti (igra že sedaj deluje zelo dobro!) + [*] In veliko več! [/list] [img]{STEAM_APP_IMAGE}/extras/header_open_source.png[/img] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Vsakdo lahko prispeva, aktivno sem vključen v skupnost in poskušam pregledati vse predloge in upoštevati povratne informacije, kjer je to mogoče. + Bodite prepričani, da si oglejte mojo Trello ploščo za celoten načrt! [img]{STEAM_APP_IMAGE}/extras/header_links.png[/img] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Uradni Discord[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Načrtovane posodobitve[/url] [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://github.com/tobspr/shapez.io]Izvorna Koda (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Pomagaj pri prevodu[/url] [/list] global: @@ -92,6 +92,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -153,8 +156,6 @@ mainMenu: savegameLevel: Level savegameLevelUnknown: Unknown Level - - dialogs: buttons: ok: OK @@ -501,6 +502,9 @@ buildings: ccw: name: Rotate (CCW) description: Rotates shapes counter-clockwise by 90 degrees. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -547,12 +551,12 @@ buildings: name: &energy_generator Energy Generator description: Generates energy by consuming shapes. Each energy generator requires a different shape. wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. - merger: - name: Wire Merger - description: Merges two energy wires into one. + default: + name: Wire Splitter + description: Splits a energy wire into two. + merger: + name: Wire Merger + description: Merges two energy wires into one. storyRewards: # Those are the rewards gained from completing the store @@ -632,8 +636,6 @@ storyRewards: desc: >- This level gave you no reward, but the next one will!

PS: Better don't destroy your existing factory - You need all those shapes later again to unlock upgrades! - - no_reward_freeplay: title: Next level desc: >- @@ -642,8 +644,9 @@ storyRewards: settings: title: Settings categories: - game: Game - app: Application + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: Development @@ -852,7 +855,7 @@ about: If you want to contribute, check out shapez.io on github.

- This game wouldn't have been possible without the great discord community around my games - You should really join the discord server!

+ This game wouldn't have been possible without the great Discord community around my games - You should really join the Discord server!

The soundtrack was made by Peppsen - He's awesome.

diff --git a/translations/base-sr.yaml b/translations/base-sr.yaml new file mode 100644 index 00000000..953c024a --- /dev/null +++ b/translations/base-sr.yaml @@ -0,0 +1,897 @@ +# +# GAME TRANSLATIONS +# +# Contributing: +# +# If you want to contribute, please make a pull request on this respository +# and I will have a look. +# +# Placeholders: +# +# Do *not* replace placeholders! Placeholders have a special syntax like +# `Hotkey: `. They are encapsulated within angle brackets. The correct +# translation for this one in German for example would be: `Taste: ` (notice +# how the placeholder stayed '' and was not replaced!) +# +# Adding a new language: +# +# If you want to add a new language, ask me in the Discord and I will setup +# the basic structure so the game also detects it. +# +# +# +# Hvala https://github.com/ivanbratovic na idejama za prevod. Alal ti vera na prevodu :) +# +# + HUB = Središte +# + Area = Oblast +# + Shape = Oblik +# + Upgrade = Nadogradnja +# + Waypoint/Marker = Putokaz +# + Blueprint = Nacrt +# + Extractor = Rudar +# + Extractor (chain) = Rudar (lančani) +# + Conveyor Belt = Pokretna Traka +# + Belt = Traka +# + Tunnel = Tunel +# + Merger = Spajač +# + Rotator = Obrtač + +--- +steamPage: + # This is the short text appearing on the steam page + shortText: shapez.io je igra o pravljenju fabrika za automatizaciju stvaranja i spajanja sve složenijih oblika na beskonačno velikoj mapi. + + # This is the text shown above the Discord link + discordLink: Oficijalni Discord server + # TODO + # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. + # NOTICE: + # - Do not translate the first line (This is the gif image at the start of the store) + # - Please keep the markup (Stuff like [b], [list] etc) in the same format + longText: >- + [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] + + shapez.io je igra o pravljenju fabrika za automatizaciju stvaranja i spajanja sve složenijih oblika na beskonačno velikoj mapi. + + Nakon dostavljanja zahtevanog oblika napredovaćete u igri i oključaćete nadogradnje za bržu fabriku. + + Kako potražnja za oblicima raste, da bi zadovoljili potražnju, moraćete da uvećate fabriku - Ne zaboravite na resurse, proširićete se na [b]beskonačnoj mapi[/b]! + + Vrlo brzo moraćete da mešate boje i farbate oblike - Pomešajte crvenu, zelenu i plavu rudu boje da biste dobili različite boje i ofarbajte oblik kako bi ispunili zahteve potražnje. + + Igra sadrži 18 progresivnih nivoa (Koji će vas zaokupirati satima!) i stalno dodajem nove stvari - Mnogo toga je planirano! + + Kupovinom igre dobijate pristup samostalnoj verziji koja poseduje dodatne funkcije, a dobićete i pristup novorazvijenim funkcijama. + + [b]Prednosti samostalne igre[/b] + + [list] + [*] Tamna tema + [*] Neobraničen broj putokaza + [*] Neograničen broj sačuvanih igara + [*] Dodatna podešavanja + [*] Uskoro: Žice i Energija! Predviđeno (otprilike) za kraj Jula 2020. + [*] Uskoro: Više nivoa + [*] Omogućavate mi da dalje radim na shapez.io ❤️ + [/list] + + [b]Buduća ažuriranja[/b] + + Trudim se da stalno ažuriram igru i da dostavim ažuriranje makar jednom nedeljno! + + [list] + [*] Različite mape i izazovi (npr. mapa sa preprekama) + [*] Slagalice (Dostavite odgovaraćuji oblik, ali uz ograničen broj građevina / oblasti) + [*] Način igre u kojem građevine imaju cenu + [*] Podesiv generator mapa (Prilagođena veličina/gustina oblika/resursa, i još.) + [*] Dodatne vrste oblika + [*] Poboljšanje performansi (Igra je već prilično fluidna!) + [*] I još mnogo toga! + [/list] + + [b]Ovo je igra otvorenog koda![/b] + + + Svako može da doprinese igri, Aktivno interagujem sa zajednicom i, kad god je to moguće, pokušavam i uzmem u obzir sve predloge i povratne informacije. + Obavezno posetite potpuni plan koji se nalazi na trello tabli! + + [b]Links[/b] + + [list] + [*] [url=https://discord.com/invite/HN7EVzV]Oficijalni Discord server[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Plan[/url] + [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] + [*] [url=https://github.com/tobspr/shapez.io]Izvorni kod (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Pomozite sa prevođenjem[/url] + [/list] + +global: + loading: Učitavanje + error: Greška + + # How big numbers are rendered, e.g. "10,000" + thousandsDivider: " " + + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. + suffix: + thousands: hilj. + millions: mil. + billions: mlrd. + trillions: tril. + + # Shown for infinitely big numbers + infinite: beskonačno + + time: + # Used for formatting past time dates + oneSecondAgo: pre jedne sekunde + xSecondsAgo: pre sekundi + oneMinuteAgo: pre jednog minuta + xMinutesAgo: pre minuta + oneHourAgo: pre jednog sata + xHoursAgo: pre sati + oneDayAgo: pre jednog dana + xDaysAgo: pre dana + + # Short formats for times, e.g. '5h 23m' + secondsShort: s + minutesAndSecondsShort: m s + hoursAndMinutesShort: h m + + xMinutes: min + + keys: + tab: TAB + control: CTRL + alt: ALT + escape: ESC + shift: SHIFT + space: SPACE + +demoBanners: + # This is the "advertisement" shown in the main menu and other various places + title: Demo Verzija + intro: >- + Nabavite punu igru kako biste otključali sve funkcije! + +mainMenu: + play: Igraj + continue: Nastavi + newGame: Nova Igra + changelog: Promene + subreddit: Reddit + importSavegame: Uvezi + openSourceHint: Ova igra je otvorenog koda! + discordLink: Oficijalni Diskord server + helpTranslate: Pomozite sa prevođenjem! + madeBy: Napravio + + # This is shown when using firefox and other browsers which are not supported. + browserWarning: >- + Izvinjavamo se, pošto je poznato da se ova igra koči u pretraživaču! Za puno iskustvo nabavite samostalnu verziju ili koristite chrome. + + savegameLevel: Nivo + savegameLevelUnknown: Nepoznat Nivo + +dialogs: + buttons: + ok: OK + delete: Izbriši + cancel: Poništi + later: Kasnije + restart: Ponovo pokreni + reset: Resetuj + getStandalone: Nabavite samostalnu igru + deleteGame: Znam šta radim + viewUpdate: Pogledajte ažuriranje + showUpgrades: Prikaži Nadogradnje + showKeybindings: Prikaži podešavanje tastera + + importSavegameError: + title: Greška prilikom uvoza + text: >- + Neuspešan uvoz sačuvane igre: + + importSavegameSuccess: + title: Uvoz sačuvane igre + text: >- + Uspešno uvezena sačuvana igra. + + gameLoadFailure: + title: Igra je pukla + text: >- + Neuspešno učitavanje sačuvane igre: + + confirmSavegameDelete: + title: Potrvrdi brisanje + text: >- + Da li ste sigurni da želite da obrišete sačuvanu igru? + + savegameDeletionError: + title: Greška prilikom brisanja + text: >- + Neuspešno brisanje sačuvane igre: + + restartRequired: + title: Potrebno je ponovno pokretanje + text: >- + Da bi primenili podešavanja, potrebno je da ponovo pokrenute igru. + + editKeybinding: + title: Promeni podešavanja tastera + desc: Pritisnite taster ili dugme na mišu koje žeite da dodelite, ili Escape za otkazivanje. + + resetKeybindingsConfirmation: + title: Resetuj podešavanja tastera + desc: Ovo će resetovati sve tastere na njihove početne vrednosti. Potrebno je potvrditi. + + keybindingsResetOk: + title: Podešavanja tastera su resetovana + desc: Podešavanja tastera su resetovana na njihove početne vrednosti! + + featureRestriction: + title: Demo Verzija + desc: Pokušali ste da pristupite funkciji () koja nije dostupna u demo verziji. Za puno iskustvo, nabavite samostalnu igru! + + oneSavegameLimit: + title: Ograničen broj sačuvanih igara + desc: Možete imati samo jednu sačuvanu igru u demo verziji. Izbrišite postojeću ili nabavite samostalnu igru! + + updateSummary: + title: Novo ažuriranje! + desc: >- + OVo su promene od zadnjeg igranja: + + upgradesIntroduction: + title: Oktključaj Nadogradnje + desc: >- + Svi oblici koje napravite mogu se iskoristiti za oktljučavanje nadogradnji - Ne uništavajte stare fabrike! + Karticu za nadogradnje možete pronaći u gornjem desnom uglu ekrana. + + massDeleteConfirm: + title: Potvrdi brisanje + desc: >- + građevina će biti obrisano! Da li ste sigurni da to želite? + + massCutConfirm: + title: Potvrdi rezanje + desc: >- + građevina će biti izrezano! Da li ste sigurni da to želite? + + massCutInsufficientConfirm: + title: Potvrdi rezanje + desc: >- + Ne možete da priuštite nalepljivanje ove oblasti! Da li ste sigurni da želite da je izrežete? + + blueprintsNotUnlocked: + title: Zaključano + desc: >- + Završite nivo 12 kako bi otključali Nacrte! + + keybindingsIntroduction: + title: Korisne kombinacije tastera + desc: >- + Ova igra ima dosta kombinacija tastera koji olakšavaju izgradnju velikih fabrika. + Ovo su neki, ali se preporučuje da pogledate sve kombinacije!

+ CTRL + Miš: Biranje oblasti.
+ SHIFT: Držato za postavljanje više istih zgrada odjednom.
+ ALT: Okrenite smer postavljenh pokretnih traka.
+ + createMarker: + title: Novi Putokaz + titleEdit: Uredi Putokaz + desc: Dajte mu smisleno ime. Možete koristiti i kod oblika (Koji možete napraviti ovde) + + markerDemoLimit: + desc: U demo verziji možete imati samo dva putokaza istovremeno. Nabavite samostalnu igru za beskonačno mnogo putokaza! + + exportScreenshotWarning: + title: Izvezi sliku ekrana + desc: Hoćete da izvezete sliku cele fabrike kao snimak ekrana. Ovaj proces može biti prilično spor za velike fabrike, može se desiti i pucanje igre! + +ingame: + # This is shown in the top left corner and displays useful keybindings in + # every situation + keybindingsOverlay: + moveMap: Kretanje + selectBuildings: Odaberi oblast + stopPlacement: Prekini postavljanje + rotateBuilding: Okreni građevinu + placeMultiple: Postavi više građevina odjednom + reverseOrientation: Obrni orijentaciju + disableAutoOrientation: Onemogući automatsku orijentaciju + toggleHud: Uključi/Isključi Interfejs + placeBuilding: Postavi građevinu + createMarker: Napravi Putokaz + delete: Brisanje + pasteLastBlueprint: Nalepi zadnji nacrt + lockBeltDirection: Omogući planiranje traka + plannerSwitchSide: Okreni stranu planera + cutSelection: Izreži + copySelection: Kopiraj + clearSelection: Očisti odabir + pipette: Pipeta + switchLayers: Promeni sloj + + # Names of the colors, used for the color blind mode + colors: + red: Crvena + green: Zelena + blue: Plava + yellow: Žuta + purple: Ljubičasta + cyan: Cijan + white: Bela + black: Crna + uncolored: Bez boje + + # Everything related to placing buildings (I.e. as soon as you selected a building + # from the toolbar) + buildingPlacement: + # Buildings can have different variants which are unlocked at later levels, + # and this is the hint shown when there are multiple variants available. + cycleBuildingVariants: Pritisni za različite varijacije građevine. + + # Shows the hotkey in the ui, e.g. "Hotkey: Q" + hotkeyLabel: >- + Taster: + + infoTexts: + speed: Brzina + range: Domet + storage: Skladište + oneItemPerSecond: 1 premet / sekundi + itemsPerSecond: predmeta / s + itemsPerSecondDouble: (x2) + + tiles: polja + + # The notification when completing a level + levelCompleteNotification: + # is replaced by the actual level, so this gets 'Level 03' for example. + levelTitle: Nivo + completed: Završen + unlockText: Otključali ste ! + buttonNextLevel: Sledeći nivo + + # Notifications on the lower right + notifications: + newUpgrade: Nova nadogradnja je dostupna! + gameSaved: Igra je sačuvana. + + # The "Upgrades" window + shop: + title: Nadogradnje + buttonUnlock: Nadogradi + + # Gets replaced to e.g. "Tier IX" + tier: red + + # The roman number for each tier + tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] + + maximumLevel: MAKSIMALNI LEVEL (Brzina x) + + # The "Statistics" window + statistics: + title: Statistika + dataSources: + stored: + title: Skladišteno + description: Količina skladištenih oblika u središtu. + produced: + title: Proizvedeno + description: Svi oblici koje proizvodi cela fabrika, uključujući i međuproizvode. + delivered: + title: Dostavljeno + description: Oblici koji su dostavljeni središtu. + noShapesProduced: Za sada nema proizvedenih oblika. + + # Displays the shapes per minute, e.g. '523 / m' + shapesPerMinute: / min + + # Settings menu, when you press "ESC" + settingsMenu: + playtime: Vreme igranja + + buildingsPlaced: Građevine + beltsPlaced: Trake + + buttons: + continue: Nastavi + settings: Podešavanja + menu: Povratak na glavni meni + + # Bottom left tutorial hints + tutorialHints: + title: Potrebna pomoć? + showHint: Prikaži savet + hideHint: Zatvori + + # When placing a blueprint + blueprintPlacer: + cost: Cena + + # Map markers + waypoints: + waypoints: Putokazi + hub: Središte + description: Klikni levim klikom na putokaz kako bi skočio na njegovu lokaciju, a izbriši ga desnim klikom.

Za stvaranje putokaza pritisni , ili desnim klikom napravi putokaz na odabranoj lokaciji. + creationSuccessNotification: Putokaz kreiran. + + # Shape viewer + shapeViewer: + title: Slojevi + empty: Prazno + copyKey: Kopiraj kod oblika + + # Interactive tutorial + interactiveTutorial: + title: Tutorijal + hints: + 1_1_extractor: Postavi Rudara na oblik kruga kako bi ga iskopao! + 1_2_conveyor: >- + Spoji rudara na središte koristeći pokretnu traku.

Savet: Pritisni i prevuci traku mišem! + + 1_3_expand: >- + Ovo NIJE pasivna igra čekanja! Više rudara i pokretnih traka će ubrzati napredak do cilja.

Savet: Drži SHIFT za postavljanje više rudara istovremeno, a pritisni R za okretanje. + +# All shop upgrades +shopUpgrades: + belt: + name: Trake, Delioci i Tuneli + description: Brzina x → x + miner: + name: Rudarenje + description: Brzina x → x + processors: + name: Rezanje, Okretanje i Slaganje + description: Brzina x → x + painting: + name: Mešanje i Farbanje + description: Brzina x → x + +# Buildings and their name / description +buildings: + hub: + deliver: Dostavite + toUnlock: kako bi otključali + levelShortcut: LVL + + belt: + default: + name: &belt Pokretna traka + description: Prenosi predmete, drži i prevuci za postavku više njih. + + wire: + default: + name: &wire Žica + description: Omogućava prenos energije. + + miner: # Internal name for the Extractor + default: + name: &miner Rudar + description: Postavite ga na oblik koji želite da iskopate. + + chainable: + name: Rudar (Lančani) + description: Postavite ga na oblik koji želite da iskopate. Mogu se ređati jedan u drugi. + + underground_belt: # Internal name for the Tunnel + default: + name: &underground_belt Tunel + description: Omogućava prenos predmeta ispod građevina i traka. + + tier2: + name: Tunel II Reda + description: Omogućava prenos predmeta ispod građevina i traka. + + splitter: # Internal name for the Balancer + default: + name: &splitter Balanser + description: Multifunkcionalan - Jednako raspoređuje sve ulaze na sve izlaze. + + compact: + name: Spajač (kompaktni) + description: Spaja dve pokretne trake u jednu. + + compact-inverse: + name: Spajač (kompaktni) + description: Spaja dve pokretne trake u jednu. + + cutter: + default: + name: &cutter Rezač + description: Reže oblike od vrha prema dnu i na izlaze daje obe polovine. Ako se koristi samo jedan deo, drugi se mora uništiti da bi se sprečio zastoj! + quad: + name: Rezač (četvorostruki) + description: Reže oblike na četiri dela. Ako se koristi samo jedan deo, ostali se moraju uništiti da bi se sprečio zastoj! + #TODO + advanced_processor: + default: + name: &advanced_processor Okretač boje + description: Prihvata boju ili oblik i izokreće je. + + rotater: + default: + name: &rotater Obrtač (↻) + description: Okreće oblike za 90 stepeni u smeru kazaljke na satu. + ccw: + name: Obrtač (↺) + description: Okreće oblike za 90 stepeni u smeru suprotnom od kazaljke na satu. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. + + stacker: + default: + name: &stacker Slagač + description: Slaže jedan oblik na drugi. Ako se oblici ne mogu spojiti, desni oblik se postavlja na vrh levog. + + mixer: + default: + name: &mixer Mešalica boja + description: Spaja dve boje koristeći aditivno mešanje boja. + + painter: + default: + name: &painter Farbač + description: &painter_desc Farba ceo oblik na levom ulazu bojom sa gornjeg ulaza. + + mirrored: + name: *painter + description: *painter_desc + + double: + name: Farbač (dupli) + description: Farba ceo oblik na levom ulazu bojom sa gornjeg ulaza. + quad: + name: Farbač (četvorostruki) + description: Omogućava farbanje svake četvrtine oblika različitom bojom. + + trash: + default: + name: &trash Smeće + description: Prima stvar sa svih strana i zauvek ih uništava. + + storage: + name: Skladište + description: Skladišti višak predmeta do određenog kapaciteta. Može se koristiti kao zaštita od prelivanja. + + energy_generator: + deliver: Dostavi + + # This will be shown before the amount, so for example 'For 123 Energy' + toGenerateEnergy: Za + + default: + name: &energy_generator Generator + description: Pretvara oblike u energiju. + #TODO + wire_crossings: + default: + name: &wire_crossings Razdelnik žica + description: Deli žicu na dva dela. + + merger: + name: Spajač žica + description: Spaja dve žice u jednu. + +storyRewards: + # Those are the rewards gained from completing the store + reward_cutter_and_trash: + title: Rezanje Oblika + desc: Rezač je otključan! On reže oblike od vrha prema dnu bez obzira na orijentaciju građevine!

Višak se mora odbaciti kako bi se izbegao zastoj. - Za tu svrhu postoji smeće, koje uništava sve što uđe u njega. + + reward_rotater: + title: Obrtanje + desc: Obrtač je otključan! On okreće oblike za 90 stepeni u smeru kazaljke na satu. + + reward_painter: + title: Farbanje + desc: >- + Farbač je otključan - Boja se (kao i oblici) može rudariti i spojiti s oblikom u farbaču!

PS: Postoji opcija za daltonizam u podešavanjima! + + reward_mixer: + title: Mešalica boja + desc: Mešalica boja je otključana - Ona spaja dve boje koristeći aditivno mešanje! + + reward_stacker: + title: Slagač + desc: Dva oblika mogu spojiti slagačem! Oblici sa oba ulaza se spajaju - ako se mogu staviti jedan kraj drugoga, biće spojeni. Ako ne, desni ulaz se slaže na vrh levog! + + reward_splitter: + title: Deljenje/Spajanje + desc: Multifunkcionalni balanser je otključan! Može ga se iskoristiti za deljenje i spajanje oblika na više pokretnih traka!

+ + reward_tunnel: + title: Tunel + desc: Tunel je otključan - Omogućava prenos stvari ispod traka i ostalih građevina! + + reward_rotater_ccw: + title: Rotacija u smeru suprotnom od kazaljke na satu + desc: Varijacija obrtača je otključana - Omogućuje okretanje u smeru suprotnom od kazaljke na satu! Odaberi obrtač i pritisni 'T' za menjanje njegove varijacije! + + reward_miner_chainable: + title: Lančani rudar + desc: Otključan je lančani rudar! On može da prosledi svoje resurse drugim rudarima radi efikasnijeg rudarenja! + + reward_underground_belt_tier_2: + title: Tunel II Reda + desc: Otključana je nova varijacija tunela - On ima veći domet, a uz to se sada mogu kombinovati vrste tunela. + + reward_splitter_compact: + title: Kompaktni Balanser + desc: >- + Varijacija balansera je otključana - On prihvata dva ulaza i spaja ih u jednu traku! + + reward_cutter_quad: + title: Četvorostruki Rezač + desc: Varijacija rezača je otključana - Omogućava rezanje oblika na četiri dela umesto na samo dva! + + reward_painter_double: + title: Dupli Farbač + desc: Varijacija farbača je otključana - Radi isti posao kao običan farbač, ali može ofarbati dva oblika odjednom po ceni jedne boje umesto dve! + + reward_painter_quad: + title: Četvorostruki Farbač + desc: Varijacija farbača je otključana - Omogućava farbanje pojedinačnih delova oblika! + + reward_storage: + title: Skladište + desc: Varijacija smeća je otključana - Omogućava skladištenje predmeta do određenog kapaciteta! + + reward_freeplay: + title: Slobodna Igra + desc: Uspeli ste! Otključali ste mod slobodne igre! Oblici su od sada nasumično generisani! (Bez brige, više sadržaja je planirano za samostalnu igru!) + + reward_blueprints: + title: Nacrti + desc: Sada možete da kopirate i nalepljujete delove fabrike! Odaberite oblast (držite CTRL, prevucite mišem), i pritisnite 'C' da biste kopirali.

Nalepljivanje nije besplatno, potrebno je da napravite oblike za nacrte da biste ga priuštili! (To su oblici koje ste do malopre dostavljali). + + # Special reward, which is shown when there is no reward actually + no_reward: + title: Sledeći Nivo + desc: >- + Ovaj nivo je bio bez nagrade, ali sledeći neće!

PS: Nemojte uništavati stare fabrike - Svi ti oblici će vam biti potrebni kasnije da biste otključali nadogradnje! + + no_reward_freeplay: + title: Sledeći Nivo + desc: >- + Svaka čast! Više sadržaja je u planu za samostalnu igru! + +settings: + title: Podešavanja + categories: + general: General + userInterface: User Interface + advanced: Advanced + + versionBadges: + dev: Razvoj + staging: Skela #TODO + prod: produkcija + buildDate: Izgrađeno + + labels: + uiScale: + title: Veličina interfejsa + description: >- + Menja veličinu korisničkog interfejsa. Veličina interfejsa će i dalje zavisiti od vaše rezolucije uređaja.Ova opcija kontroliše tu veličinu interfejsa. + scales: + super_small: Maleno + small: Malo + regular: Normalno + large: Veliko + huge: Ogromno + + autosaveInterval: + title: Interval Automatskog Čuvanja Igre + description: >- + Kontroliše koliko često će se igra automatski čuvati. Ovu opciju možete i da onemogućite. + + intervals: + one_minute: 1 minut + two_minutes: 2 minuta + five_minutes: 5 minuta + ten_minutes: 10 minuta + twenty_minutes: 20 minuta + disabled: Onemogućeno + + scrollWheelSensitivity: + title: Osetljivost zumiranja + description: >- + Kontroliše koliko je zumiranje osetljivo (Točkić na mišu ili trackpad). + sensitivity: + super_slow: Najsporije + slow: Sporo + regular: Normalno + fast: Brzo + super_fast: Najbrže + + movementSpeed: + title: Brzina kretanja + description: >- + Menja brzinu kretanja kamere pri korišćenju tastature. + speeds: + super_slow: Najsporije + slow: Sporo + regular: Normalno + fast: Brzo + super_fast: Najbrže + extremely_fast: Brže od najbržeg + + language: + title: Jezik + description: >- + Promenite jezik igre. Svi prevodi su delo volontera i mogu biti nezavršeni! + + enableColorBlindHelper: + title: Opcija za daltonizam + description: >- + Omogućuje razne alate koji pomažu pri igranju igre sa nekim oblikom daltonizma. + + fullscreen: + title: Ceo ekran + description: >- + Preporučljivo je, radi najboljeg iskustva, da igrate ovu igru na celom ekranu. Opcija dostupna samo u samostalnoj igri. + + soundsMuted: + title: Utišajte Zvukove + description: >- + Ako je odabrana, ova opcija isključuje sve zvučne efekte. + + musicMuted: + title: Utišajte Muziku + description: >- + Ako je odabrana, ova opcija isključuje svu muziku. + + theme: + title: Tema Igre + description: >- + Odaberite temu igre (svetla / tamna). + themes: + dark: Tamna + light: Svetla + + refreshRate: + title: Simulacija na 144 Hz + description: >- + Opcija za monitore visoke frekvencije osvežavanja. Ovo može smanjiti FPS ako je vaš računar prespor. + + alwaysMultiplace: + title: Višestruko Postavljanje + description: >- + Ako je omogućeno, sve građevine će ostati odabrane nakon što su postavljene. Ova opcija je ekvivalenta stalnom držanju dugmeta SHIFT. + + offerHints: + title: Saveti i Tutorijali + description: >- + Opcija za prikazivanje saveta i tutorijala za vreme igre. Dodatno krije određene elemente interfejsa, dok ih ne budete otključali, radi lakše igre. + + enableTunnelSmartplace: + title: Pametni Tuneli + description: >- + Ako je omogućeno, postavljanje tunela automatski briše nepotrebne pokretne trake. Takođe omogućuje prevlačenje tunela i brisanje višak tunela. + + vignette: + title: Vinjeta + description: >- + Omogućeva vinjetu - zatamnjuje ivice ekrana da bi tekst bio čitljiviji. + + rotationByBuilding: #TODO + title: Okretanje prema vrsti građevine + description: >- + Svaka građevina pamti smer na koji je bila okrenuta. Ova opcija je preporučuje ako često menjate vrste građevina koje postavljate. + + compactBuildingInfo: + title: Skraćene Informacije o Građevinama + description: >- + Skraćuje deo sa informacijama građevine tako da prikazuje samo njihove odnose. U suptornom prikazuje opis i sliku građevine. + + disableCutDeleteWarnings: + title: Onemogući upozorenje za Rezanje/Brisanje + description: >- + Onemogućuje upozorenje koje se javlja kada režete/brišete više od 100 stvari. + +keybindings: + title: Tasteri + hint: >- + Savet: Koristite CTRL, SHIFT i ALT! Oni omogućuju razne opcije postavljanja građevina. + + resetKeybindings: Resetuj podešavanja tastera + + categoryLabels: + general: Aplikacija + ingame: Igra + navigation: Navigacija + placement: Postavljanje + massSelect: Masovno Odabiranje + buildings: Prečice za građevine + placementModifiers: Modifikatori Postavljanja + + mappings: + confirm: Potvrdi + back: Nazad + mapMoveUp: Idi Gore + mapMoveRight: Idi Desno + mapMoveDown: Idi Dole + mapMoveLeft: Idi Levo + mapMoveFaster: Brže kretanje + centerMap: Centar mape + + mapZoomIn: Zumiraj + mapZoomOut: Odzumiraj + createMarker: Napravi Putokaz + + menuOpenShop: Nadogradnje + menuOpenStats: Statistika + menuClose: Zatvori Meni + + toggleHud: Uključi/Isključi Interfejs + toggleFPSInfo: Uključi/Isključi FPS i infomacije o traženju grešaka u kodu + switchLayers: Promeni Sloj + exportScreenshot: Izvoz slike cele fabrike kao snimak ekrana + belt: *belt + splitter: *splitter + underground_belt: *underground_belt + miner: *miner + cutter: *cutter + advanced_processor: *advanced_processor + rotater: *rotater + stacker: *stacker + mixer: *mixer + energy_generator: *energy_generator + painter: *painter + trash: *trash + wire: *wire + + pipette: Pipeta + rotateWhilePlacing: Okreni građevinu + rotateInverseModifier: >- + Modifikator: Rotiraj u smeru suprotnom od kazaljke na satu + cycleBuildingVariants: Promena Varijacije + confirmMassDelete: Uništite Oblast + pasteLastBlueprint: Nalepite posledji nacrt + cycleBuildings: Promena Građevine + lockBeltDirection: Omogući planer pokretnih traka + switchDirectionLockSide: >- + Planer: Okreni stranu + + massSelectStart: Pritisni i zadrži za za početak + massSelectSelectMultiple: Odabir više oblasti + massSelectCopy: Kopiranje oblasti + massSelectCut: Izrezivanje oblasti + + placementDisableAutoOrientation: Onemogućite automatsku orijentaciju + placeMultiple: Ostanite u modu za postavljanje + placeInverse: Automatski okreni orijentaciju pokretnih traka + +about: + title: O Igri + body: >- + Ova igra je otvorenog koda i napravljena je od strane Tobias Springer (to sam ja).

+ + Ako želite da doprinesete razvoju, bacite pogled na shapez.io github.

+ + Bez odlične Discord zajednice ova igra, kao ni druge, ne bi postojala - Pridružite se Discord serveru!

+ + Peppsen je komponovao muziku za igru - On je super.

+ + Na kraju svega, veliko hvala mom najboljem prijatelju Niklas-u - Bez naših factorio sesija, ova igra nikad ne bi postojala. + +changelog: + title: Promene + +demo: + features: + restoringGames: Obnavljanje sačuvanih igara + importingGames: Uvoz sačuvanih igara + oneGameLimit: Ograničenje od jedne sačuvane igre + customizeKeybindings: Prilagođena Podešavanja Tastera + exportingBase: Izvoz slike cele fabrike kao snimak ekrana + + settingNotAvailable: Nije dostupno u demo verziji. diff --git a/translations/base-sv.yaml b/translations/base-sv.yaml index 442ada69..ab302368 100644 --- a/translations/base-sv.yaml +++ b/translations/base-sv.yaml @@ -15,10 +15,11 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io är ett spel som går ut på att automatisera skapandet av former med ökande komplexitet inom den oändligt stora världen. @@ -91,6 +92,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "." + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "," + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k @@ -115,7 +119,7 @@ global: # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s - hoursAndMinutesShort: t s + hoursAndMinutesShort: t m xMinutes: minuter @@ -135,20 +139,19 @@ demoBanners: mainMenu: play: Spela - changelog: Changelog + changelog: Ändringslogg importSavegame: Importera - openSourceHint: Detta spel är open source! + openSourceHint: Detta spelet har öppen kod! discordLink: Officiell Discord Server helpTranslate: Hjälp till att översätta! # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - Förlåt, men det är känt att spelet spelar långsamt på din browser! Skaffa den fristående versionen eller ladda ner chrome för den fulla upplevelsen. + Förlåt, men det är känt att spelet spelar långsamt på din browser! Skaffa den fristående versionen eller ladda ner Chrome för en bättre upplevelse. savegameLevel: Nivå savegameLevelUnknown: Okänd Nivå - continue: Fortsätt newGame: Nytt spel madeBy: Skapad av @@ -200,7 +203,7 @@ dialogs: editKeybinding: title: Ändra snabbtangenter - desc: Tryck ned tangenten eller musknappen du vill tillsätta, eller escape för att avbryta. + desc: Tryck ned tangenten eller musknappen du vill använda, eller escape för att avbryta. resetKeybindingsConfirmation: title: Återställ snabbtangenter @@ -216,34 +219,34 @@ dialogs: oneSavegameLimit: title: Begränsad mängd sparfiler - desc: Du kan bara ha en sparfil åt gången i demoversionen. Var snäll och ta bort det existerande eller skaffa den fristående versionen! + desc: Du kan bara ha en sparfil åt gången i demoversionen. Var snäll och ta bort den nuvarande eller skaffa den fristående versionen! updateSummary: title: Ny uppdatering! desc: >- - Här är ändringarna sen du sist spelade: + Här är ändringarna sen du senast spelade: upgradesIntroduction: title: Lås upp Uppgraderingar desc: >- - Alla former du producerar kan användas för att låsa upp uppgraderingar - Förstör inte dina gamla fabriker! + Alla former du producerar kan användas för att låsa upp uppgraderingar - Förstör inte dina gamla fabriker! Uppgraderingsmenyn finns i det övre högra hörnet på skärmen. massDeleteConfirm: title: Bekräfta borttagning desc: >- - Du tar nu bort ganska många byggnader ( för att vara exakt)! Är du säker på att du vill göra detta? + Du tar bort ganska många byggnader ( för att vara exakt)! Är du säker på att du vill göra detta? blueprintsNotUnlocked: title: Inte upplåst än desc: >- - Ritningar är inte än upplåsta! Klara fler nivåer för att låsa upp dem. + Nå level 12 för att låsa upp Ritningar. keybindingsIntroduction: title: Användbara tangentbindningar desc: >- Detta spel använder en stor mängd tangentbindningar som gör det lättare att bygga stora fabriker. - Här är några men se till att kolla in tangentbindningarna!

+ Här är några, men se till att kolla in tangentbindningarna!

CTRL + Dra: Välj en yta att kopiera / radera.
SHIFT: Håll ned för att placera flera av samma byggnad.
ALT: Invertera orientationen av placerade rullband.
@@ -251,10 +254,10 @@ dialogs: createMarker: title: Ny Markör desc: Ge den ett meningsfullt namn, du kan också inkludera en kort kod av en form (Vilket du kan generera här ) - titleEdit: Edit Marker + titleEdit: Ändra Markör markerDemoLimit: - desc: Du kan endast skapa två markörer i demoversionen. Skaffa den fristående versionen för ett oändligt antal! + desc: Du kan endast ha två markörer i demoversionen. Skaffa den fristående versionen för ett obegränsat antal! massCutConfirm: title: Bekräfta Klipp desc: >- @@ -265,11 +268,11 @@ dialogs: title: Exportera skärmdump desc: >- Du efterfrågade att exportera din fabrik som en skärmdump. - Vänligen notera att detta kan ta ett tag för en stor bas och i vissa fall till och med krascha ditt spel + Vänligen notera att detta kan ta ett tag för en stor bas och i vissa fall till och med krascha ditt spel! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + title: Bekräfta Klipp + desc: Du har inte råd att placera detta område! Är du säker att du vill klippa det? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -282,10 +285,10 @@ ingame: placeMultiple: Placera flera reverseOrientation: Vänd orientation disableAutoOrientation: Stäng av automatisk orientation - toggleHud: Toggle HUD + toggleHud: Växla HUD placeBuilding: Placera Byggnad createMarker: Skapa Markör - delete: Förstör + delete: Ta bort pasteLastBlueprint: Klistra in ritning lockBeltDirection: Aktivera rullbandsplanerare plannerSwitchSide: Vänd planerarsidan @@ -293,7 +296,7 @@ ingame: copySelection: Kopiera clearSelection: Rensa vald pipette: Pipett - switchLayers: Switch layers + switchLayers: Byt lager # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -483,6 +486,9 @@ buildings: ccw: name: Roterare (CCW) description: Roterar former 90 motsols. + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -628,8 +634,9 @@ storyRewards: settings: title: Inställningar categories: - game: Spelinställningar - app: Applikation + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: Utveckling @@ -840,7 +847,7 @@ about: Spelet hade inte varit möjligt utan den fantastiska discordgemenskapen runt mina spel - Du borde gå med i den discord server!

+ target="_blank">Discord server!

Musiken skapades av Peppsen - Han är grym!

diff --git a/translations/base-tr.yaml b/translations/base-tr.yaml index c4a6dbbc..26b95e35 100644 --- a/translations/base-tr.yaml +++ b/translations/base-tr.yaml @@ -15,13 +15,14 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page - shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. + shortText: shapez.io giderek karmaşıklaşan şekillerin sonsuz bir harita üzerinde üretimi ve birleştirilmesi hakında bir oyundur. # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: @@ -30,67 +31,71 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.io giderek karmaşıklaşan şekillerin sonsuz bir harita üzerinde üretimi ve birleştirilmesi hakında bir oyundur. + Talep edilen şekilleri verdikten sonra oyundaki geliştirmeleri açıp fabrikanızı hızlandırabilirsiniz. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Şekiller için talep artınca fabrikanı büyütüp talebi karşılamalısın - Kaynakları unutma! Sonsuz [b]sonsuz haritada[/b] genişlemen gerekecek! - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Yakında renkleri karıştırman ve şekileri boyaman gerekecek - Talebi karşılamak için kırmızı, mavi ve yeşili karıştırıp şekilleri boyacaksın - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Bu oyun 18 kademeli seviye içerir (Seni saatlerce meşgul tutumalı) ama sürekli yeni şeyler ekliyorum - Ekleyecek çok şey var! - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + Bu oyunu satın almak indirilebilir versiyonuna (Ek özellikler var) ve yeni özeliklerine erişebileceksiniz. - [b]Standalone Advantages[/b] + [b]İndirebilir versiyonun avantajları[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Karanlık mod + [*] Sonsuz işaret + [*] Sonsuz kayıt alanı + [*] Ek ayarlar + [*] Yakında geliyor: Kablo ve enerji! Temmuz sonunu hedefliyorum. + [*] Yakında geliyor: Daha fazla seviyeler + [*] Shapez.io'yu geliştirmeme izin veriyor ❤️ [/list] - [b]Future Updates[/b] + [b]Gelecek güncellemeler[/b] - I am updating the game very often and trying to push an update at least every week! + Oyunu sık sık güncelliyorum ve en az haftada bir güncellemeye çalışıyorum! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Farklı haritalar ve görevler (Örneğin engelli haritalar) + [*] Yapbozlar (İstenen şekilleri kısıtlı bir alanda / belli yapılar ile) + [*] Hikaye modu ile yapıların maliyeti olacak. + [*] Ayarlanabilir harita yapımı(Ayarlanabilir kaynak/şekil boyut/sıklığı, seedler ve daha fazlası) + [*] Ek şekiller + [*] Performans optimizasyonları (oyun zaten iyi çalışıyor) + [*] Ve daha fazlası [/list] - [b]This game is open source![/b] + [b]Bu oyun açık kaynaklı![/b] + + Bu oyuna herkes katkıda bulunabilir! Aktif olarak toplulukğa katkıda bulunuyorum ve bütün önerileri gözden geçirmeye çalışıyorum. + Yol planıma Trello'dan bakmayı unutmayın! - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! [b]Links[/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Dİscord'umuz[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]yol planı[/url] [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://github.com/tobspr/shapez.io]KAynak kodu (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Çevirmeye yardımcı olun[/url] [/list] discordLink: Official Discord - Chat with me! global: - loading: yükleniyor + loading: Yüklenİyor error: Hata # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: b @@ -113,9 +118,9 @@ global: xDaysAgo: gün önce # Short formats for times, e.g. '5h 23m' - secondsShort: s - minutesAndSecondsShort: d s - hoursAndMinutesShort: S m + secondsShort: sn + minutesAndSecondsShort: dk sn + hoursAndMinutesShort: sa dk xMinutes: dakika @@ -129,586 +134,588 @@ global: demoBanners: # This is the "advertisement" shown in the main menu and other various places - title: Demo Version + title: Deneme Sürümü intro: >- - Get the standalone to unlock all features! + Bütün özellikleri açmak için tam sürümü satın alın! mainMenu: play: Oyna - changelog: Changelog - importSavegame: Yükle + changelog: Değİşİklİk Günlüğü + importSavegame: Kayıt Yükle openSourceHint: Bu oyun açık kaynak kodlu! - discordLink: Resmi Discord Sunucusu - helpTranslate: Çeviriye yardım et! + discordLink: Resmİ Discord Sunucusu + helpTranslate: Çevİrİye yardım et! # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - Sorry, but the game is known to run slow on your browser! Get the standalone version or download chrome for the full experience. + Üzgünüz, bu oyunun tarayıcınızda yavaş çalıştığı biliniyor! Tam sürümü satın alın veya iyi performans için Chrome tarayıcısını kullanın. savegameLevel: Seviye savegameLevelUnknown: Bilinmeyen seviye - continue: Devam et - newGame: Yeni Oyun - madeBy: Made by + newGame: YENİ OYUN + madeBy: tarafından yapıldı subreddit: Reddit dialogs: buttons: ok: OK - delete: Sil + delete: SİL cancel: İptal later: Sonra restart: Yeniden başla reset: Sıfırla - getStandalone: Tam versiyona eriş + getStandalone: Tam sürüme eriş deleteGame: Ne yaptığımi biliyorum - viewUpdate: View Update - showUpgrades: Show Upgrades - showKeybindings: Show Keybindings + viewUpdate: Güncellemeleri Görüntüle + showUpgrades: Geliştirmeleri Göster + showKeybindings: Tuş Kısayollarını Göster importSavegameError: - title: Import Error + title: Kayıt yükleme hatası text: >- - Failed to import your savegame: + Oyun kaydı yükleme başarısız: importSavegameSuccess: - title: Savegame Imported + title: Oyun Kaydı Yüklendi text: >- - Kayıtlı oyun başarıyla yüklendi. + Oyun kaydı başarıyla yüklendi. gameLoadFailure: - title: Game is broken + title: Oyun bozuk text: >- - Failed to load your savegame: + Oyun yükleme başarısız: confirmSavegameDelete: - title: Confirm deletion + title: Silme işlemini onayla text: >- Oyunu silmek istediğinizden emin misiniz? savegameDeletionError: - title: Failed to delete + title: Silme başarısız text: >- - Failed to delete the savegame: + Oyun kaydını silme başarısız: restartRequired: - title: Restart required + title: Yeniden başlatma gerekiyor text: >- - You need to restart the game to apply the settings. + Değişiklikleri uygulamak için oyunu yeniden başlatılmalı. editKeybinding: - title: Change Keybinding - desc: Press the key or mouse button you want to assign, or escape to cancel. + title: Tuş Atamasını Değiştir + desc: Atamak isteğiniz tuşa veya fare butonun basın, veya iptal etmek için Esc tuşuna basın. resetKeybindingsConfirmation: - title: Reset keybindings - desc: This will reset all keybindings to their default values. Please confirm. + title: Tuş Atamasını Sıfırla + desc: Bu işlem bütün tuş atamalarını varsayılan durumuna sıfırlayacak. Lütfen onaylayın. keybindingsResetOk: - title: Keybindings reset - desc: The keybindings have been reset to their respective defaults! + title: Tuş Atamaları sıfırlandı + desc: Tuş atamaları varsayılan duruma sıfırlandı! featureRestriction: - title: Demo Version - desc: You tried to access a feature () which is not available in the demo. Consider to get the standalone for the full experience! + title: Deneme Sürümü + desc: Demoda olmayan bir özelliğe () erişmeye çalıştınız. Tam deneyim için tam versiyonu satın alın. oneSavegameLimit: - title: Limited savegames - desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone! + title: Sınırlı Oyun Kaydı + desc: Deneme sürümünde sadece tek bir oyun kaydınız olabilir. Lütfen varolanı silin veya tam sürümü satın alın! updateSummary: - title: New update! + title: Yeni güncelleme! desc: >- - Here are the changes since you last played: + Son oynadığınızdan bu yana gelen değişikler: upgradesIntroduction: - title: Unlock Upgrades + title: Geliştirmeleri Aç desc: >- - All shapes you produce can be used to unlock upgrades - Don't destroy your old factories! - The upgrades tab can be found on the top right corner of the screen. + Ürettiğiniz her şekil geliştirmeler için kullanılabilir - Eski fabrikalarınızı silmeyin! + Güncellemeler sekmesini ekranınızın sağ üst köşesinde bulabilirsiniz. massDeleteConfirm: - title: Confirm delete + title: Silmeyi onayla desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? + Çok fazla yapı siliyorsunuz (tam olarak adet)! Bunu yapmak istediğinize emin misiniz? blueprintsNotUnlocked: - title: Not unlocked yet + title: Henüz açılmadı desc: >- - Complete level 12 to unlock Blueprints! + Taslakları açmak için 12. seviyeyi tamamlamalısınız! keybindingsIntroduction: - title: Useful keybindings + title: Kullanışlı tuş atamaları desc: >- - This game has a lot of keybindings which make it easier to build big factories. - Here are a few, but be sure to check out the keybindings!

- CTRL + Drag: Select area to delete.
- SHIFT: Hold to place multiple of one building.
- ALT: Invert orientation of placed belts.
+ Bu oyunda büyük fabrikalar inşa etmeyi kolaylaştıran çok fazla tuş ataması var. + Bunlardan bazıları şunlar, ama emin olmak için tuş atamalarını kontrol edin!

+ CTRL + Sürükle: Silmek için alan seç.
+ SHIFT: Çoklu yapı inşa etmek için basılı tutun
+ ALT: Yerleştirilen taşıma bantlarının yönünü ters çevirir.
createMarker: - title: New Marker - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) - titleEdit: Edit Marker + title: Yeni Konum İşareti + desc: İşarete anlamlı bir isim verin, aynı zamanda (buradan oluşturabileceğiniz) bir şeklin sembolünü ekleyebilirsiniz. + titleEdit: Konum İşaretini Düzenle markerDemoLimit: - desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! + desc: Deneme sürümünde sadece iki adet yer imi oluşturabilirsiniz. Sınırsız yer imi için tam sürümü alın! massCutConfirm: - title: Confirm cut + title: Kesmeyi onayla desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you - want to do this? + Çok fazla yapı kesiyorsunuz (tam olarak adet)! Bunu yapmak istediğinize emin misiniz? exportScreenshotWarning: - title: Export screenshot + title: Ekran görüntüsünü dışa aktar desc: >- - You requested to export your base as a screenshot. Please note that this can - be quite slow for a big base and even crash your game! + Fabrikanızın ekran görüntüsünü dışarı aktarmak istiyorsunuz. Lütfen dikkat edin, + büyük bir fabrika için bu işlem oldukça yavaş olabilir ve hatta oyununuz kapanabilir. massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + title: Kesmeyi onayla + desc: Seçili yapıları yapıştırmak için yeterli kaynağınız yok! Kesmek istediğinize emin misiniz? ingame: # This is shown in the top left corner and displays useful keybindings in # every situation keybindingsOverlay: - moveMap: Move - selectBuildings: Select area - stopPlacement: Stop placement - rotateBuilding: Rotate building - placeMultiple: Place multiple - reverseOrientation: Reverse orientation - disableAutoOrientation: Disable auto orientation - toggleHud: Toggle HUD - placeBuilding: Place building - createMarker: Create Marker - delete: Destroy - pasteLastBlueprint: Paste last blueprint - lockBeltDirection: Enable belt planner + moveMap: Hareket Et + selectBuildings: Alan seç + stopPlacement: Yerleştİrmeyİ durdur + rotateBuilding: Yapıyı döndür + placeMultiple: Çoklu yerleştİr + reverseOrientation: Yönünü ters çevİr + disableAutoOrientation: Otomatik yönü devre dışı bırak + toggleHud: Kullanıcı arayüzünü aç/kapa + placeBuilding: Yapı yerleştİr + createMarker: Yer İmi oluştur + delete: SİL + pasteLastBlueprint: Son taslağı yapıştır + lockBeltDirection: Taşıma bandı planlayıcısını kullan plannerSwitchSide: Flip planner side - cutSelection: Cut - copySelection: Copy - clearSelection: Clear Selection - pipette: Pipette - switchLayers: Switch layers + cutSelection: Kes + copySelection: Kopyala + clearSelection: Seçİmİ temİzle + pipette: Pİpet + switchLayers: Katman değİştİr # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) buildingPlacement: # Buildings can have different variants which are unlocked at later levels, # and this is the hint shown when there are multiple variants available. - cycleBuildingVariants: Press to cycle variants. + cycleBuildingVariants: Yapının farklı türlerine geçmek için tuşuna bas. # Shows the hotkey in the ui, e.g. "Hotkey: Q" hotkeyLabel: >- - Hotkey: + Kısayol: infoTexts: - speed: Speed - range: Range - storage: Storage - oneItemPerSecond: 1 item / second - itemsPerSecond: items / s + Hız: Hız + range: Menzil + storage: Depo + oneItemPerSecond: 1 eşya / saniye + itemsPerSecond: eşya / sn itemsPerSecondDouble: (x2) - tiles: tiles + tiles: karo # The notification when completing a level levelCompleteNotification: # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: Level - completed: Completed - unlockText: Unlocked ! - buttonNextLevel: Next Level + levelTitle: SEVİYE + completed: Tamamlandı + unlockText: Açıldı ! + buttonNextLevel: Sonrakİ Sevİye # Notifications on the lower right notifications: - newUpgrade: A new upgrade is available! - gameSaved: Your game has been saved. + newUpgrade: Yeni geliştirme mevcut! + gameSaved: Oyun kaydedildi. # The "Upgrades" window shop: - title: Upgrades - buttonUnlock: Upgrade + title: Geliştirmeler + buttonUnlock: Geliştir # Gets replaced to e.g. "Tier IX" - tier: Tier + tier: Aşama # The roman number for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXIMUM LEVEL (Speed x) + maximumLevel: SON SEVİYE (Hız x) # The "Statistics" window statistics: - title: Statistics + title: İstatistikler dataSources: stored: - title: Stored - description: Displaying amount of stored shapes in your central building. + title: Mevcut + description: Merkez yapınızda bulunan şekillerin miktarını gösterir. + produced: - title: Produced - description: Displaying all shapes your whole factory produces, including intermediate products. + title: Üretilen + description: Fabrikanızın ürettiği bütün şekilleri gösterir, ara ürünler dahil. delivered: - title: Delivered - description: Displaying shapes which are delivered to your central building. - noShapesProduced: No shapes have been produced so far. + title: Teslim Edilen + description: Merkez binanıza giden bütün şekilleri gösterir. + noShapesProduced: Henüz hiçbir şekil üretilmedi. # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m + shapesPerMinute: / dk # Settings menu, when you press "ESC" settingsMenu: playtime: Oynama zamani buildingsPlaced: Yapılar - beltsPlaced: Belts + beltsPlaced: Taşıma bantları buttons: - continue: Continue - settings: Settings - menu: Return to menu + continue: Devam + settings: Ayarlar + menu: Ana Menüye Dön # Bottom left tutorial hints tutorialHints: - title: Need help? - showHint: Show hint - hideHint: Close + title: Yardım? + showHint: İpucu Göster + hideHint: Kapat # When placing a blueprint blueprintPlacer: - cost: Cost + cost: Bedel # Map markers waypoints: - waypoints: Markers - hub: HUB - description: Left-click a marker to jump to it, right-click to delete it.

Press to create a marker from the current view, or right-click to create a marker at the selected location. - creationSuccessNotification: Marker has been created. + waypoints: Yer İmi + hub: MERKEZ + description: Sol-tık ile Yer İmlerine git, sağ-tık ile yer imini sil.

Mevcut konumdan yer imi oluşturmak için 'a bas, sağ-tık ile mevcut konumda yer imi oluştur. + creationSuccessNotification: Yer İmi oluşturuldu. # Interactive tutorial interactiveTutorial: - title: Tutorial + title: Eğİtİm hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! + 1_1_extractor: Daire üretmek için daire şekli üzerine bir üretici yerleştir! 1_2_conveyor: >- - Connect the extractor with a conveyor belt to your hub!

Tip: Click and drag the belt with your mouse! - + Üreticiyi taşıma bandı ile merkezine bağla!

İpucu: Taşıma bandı nı seç ve taşıma bandını farenin sol tuşu ile tıkla ve sürükle! 1_3_expand: >- - This is NOT an idle game! Build more extractors and belts to finish the goal quicker.

Tip: Hold SHIFT to place multiple extractors, and use R to rotate them. + Bu bir boşta kalma oyunu (idle game) değil! Hedefe ulaşmak için daha fazla üretici ve taşıma bandı yerleştir.

İpucu: Birden fazla üretici yerleştirmek için SHIFT tuşuna basılı tut, ve R tuşuyla taşıma bandının yönünü döndür. colors: red: Kırmızı - green: Yesil + green: Yeşil blue: Mavi yellow: Sarı purple: Mor - cyan: Cyan + cyan: Turkuaz white: Beyaz uncolored: Renksiz - black: Black + black: Siyah shapeViewer: - title: Layers - empty: Bos - copyKey: Copy Key + title: Katmanlar + empty: Boş + copyKey: Şekil Kodunu Kopyala # All shop upgrades shopUpgrades: belt: - name: Belts, Distributor & Tunnels - description: Speed x → x + name: Taşıma Bandı, Dağıtıcılar & Tüneller + description: Hız x → x miner: - name: Extraction - description: Speed x → x + name: Üretme + description: Hız x → x processors: - name: Cutting, Rotating & Stacking - description: Speed x → x + name: Kesme, Döndürme & Kaynaştırıcı + description: Hız x → x painting: - name: Mixing & Painting - description: Speed x → x + name: Karıştırma & Boyama + description: Hız x → x # Buildings and their name / description buildings: hub: - deliver: Deliver - toUnlock: to unlock - levelShortcut: LVL + deliver: "Teslİm et" + toUnlock: "Açılacak" + levelShortcut: SVY belt: default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. + name: &belt Taşıma Bandı + description: Eşyaları taşır, basılı birden fazla yerleştirmek için tutup sürükle. miner: # Internal name for the Extractor default: - name: &miner Extractor - description: Place over a shape or color to extract it. + name: &miner Üretİcİ + description: Bir şekli veya rengi üretmek için üzerlerini yerleştir. chainable: - name: Extractor (Chain) + name: Üretİcİ (Zİncİrleme) description: Place over a shape or color to extract it. Can be chained. underground_belt: # Internal name for the Tunnel default: - name: &underground_belt Tunnel - description: Allows to tunnel resources under buildings and belts. + name: &underground_belt Tünel + description: Yapıların ve taşıma bantlarının altından kaynak aktarımı sağlar. tier2: - name: Tunnel Tier II - description: Allows to tunnel resources under buildings and belts. + name: Tünel Aşama II + description: Yapıların, taşıma bantlarının ve normal tünellerin altından kaynak aktarımı sağlar. splitter: # Internal name for the Balancer default: - name: &splitter Balancer - description: Multifunctional - Evenly distributes all inputs onto all outputs. + name: &splitter Dengeleyici + description: Çok işlevli - bütün girdileri eşit olarak bütün çıkışlara dağıtır. compact: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: Bİrleştİrİcİ (tekİl) + description: İki taşıma bandını bir çıktı verecek şekilde birleştirir. compact-inverse: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: Birleştİrİcİ (tekİl) + description: İki taşıma bandını bir çıktı verecek şekilde birleştirir. cutter: default: - name: &cutter Cutter - description: Cuts shapes from top to bottom and outputs both halfs. If you use only one part, be sure to destroy the other part or it will stall! + name: &cutter Kesİcİ + description: Şekilleri yukarıdan aşağıya böler ve iki yarım parçayı çıktı olarak verir. Eğer sadece bir çıktıyı kullanıyorsanız diğer çıkan parçayı yok etmeyi unutmayın, yoksa kesim durur! quad: - name: Cutter (Quad) - description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other part or it will stall! + name: Kesİcİ (Dörtlü) + description: Şekilleri dört parçaya böler. Eğer sadece bir çıktıyı kullanıyorsanız diğer çıkan parçaları yok etmeyi unutmayın, yoksa kesim durur! rotater: default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. + name: &rotater Döndürücü + description: Şekilleri saat yönünde 90 derece döndürür. ccw: - name: Rotate (CCW) - description: Rotates shapes counter clockwise by 90 degrees. + name: Döndürücü (Saat Yönünün Tersİ) + description: Şekilleri saat yönünün tersinde 90 derece döndürür. + fl: + name: Döndürücü (180) + description: Şekilleri 180 derece döndürür. stacker: default: - name: &stacker Stacker - description: Stacks both items. If they can not be merged, the right item is placed above the left item. + name: &stacker Kaynaştırıcı + description: İki eşyayı kaynaştırır. Eğer eşyalar kaynaştırılamazsa sağdaki eşya soldaki eşyanın üzerine kaynaştırılır. mixer: default: - name: &mixer Color Mixer - description: Mixes two colors using additive blending. + name: &mixer Renk Karıştırıcısı + description: Mixes two colors using additive blending. İki rengi eklemeli renk metoduyla birleştirir. painter: default: - name: &painter Painter - description: &painter_desc Colors the whole shape on the left input with the color from the right input. + name: &painter Boyayıcı + description: &painter_desc Sol girdideki bütün şekli sağ girdideki renk ile boyar. double: - name: Painter (Double) - description: Colors the shapes on the left inputs with the color from the top input. + name: Boyayıcı (Çİft) + description: Sol girdideki şekilleri yukarı girdideki renk ile boyar. quad: - name: Painter (Quad) - description: Allows to color each quadrant of the shape with a different color. + name: Boyayıcı (Dörtlü) + description: Şeklin her çeyreğinin farklı bir renkle boyanmasını sağlar. mirrored: name: *painter description: *painter_desc trash: default: - name: &trash Trash - description: Accepts inputs from all sides and destroys them. Forever. + name: &trash Çöp + description: Her yönden giren girdileri yok eder. Tamamen. storage: - name: Storage - description: Stores excess items, up to a given capacity. Can be used as an overflow gate. + name: Depo + description: Belirli bir sınıra kadar fazla eşyaları depolar. Taşırma kapısı olarak kullanıla bilir. wire: default: - name: Energy Wire - description: Allows you to transport energy. + name: Enerji Kablosu + description: Enerji aktarmayı sağlar. advanced_processor: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. + name: Renk Ters Dönüştürücü + description: Bir rengi veya şeklin rengini ters dönüştürür. energy_generator: - deliver: Deliver - toGenerateEnergy: For + deliver: Teslİm et + toGenerateEnergy: İçİn default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: Enerjİ Üretİcİ + description: Şekilleri tüketerek enerji üretir. wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Kablo Çoklayıcı + description: Bir kablo çıkışını ikiye çoğaltır. merger: - name: Wire Merger - description: Merges two energy wires into one. + name: Kablo Bİrleştİrİcİ + description: İki enerji kablosunu birleştirir storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: - title: Cutting Shapes - desc: You just unlocked the cutter - it cuts shapes half from top to bottom regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will stall - For this purpose I gave you a trash, which destroys everything you put into it! + title: Şekİllerİ Kesmek + desc: Az önce kesici açıldı - kesici şekilleri yukarıdan aşağıya ikiye böler konumu ne olursa olsun!

Kullanılmayan çıktılardan kurtulmayı unutma, yoksa kesim durur. Bu sepeble size, herşeyi yok eden bir çöp verdim! reward_rotater: - title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. + title: Döndürme + desc: Döndürücü açıldı! Döndürücü şekilleri saat yönüne 90 derece döndürür. reward_painter: - title: Painting + title: Boyama desc: >- - The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, there is a color blind mode in the settings! + Boyayıcı açıldı - Biraz renk üretin (tıpkı şekiller gibi) ve şekil boyamak için rengi boyayıcıda bir şekille birleştirin!

NOT: Renkleri daha kolay ayırt etmek için ayarlardan renk körü modunu kullanabilirsiniz! reward_mixer: - title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! + title: Renk Karıştırma + desc: Karıştırıcı açıldı - Bu yapıyla iki rengi eklemeli renk metodu ile karıştırın! reward_stacker: - title: Combiner - desc: You can now combine shapes with the combiner! Both inputs are combined, and if they can be put next to each other, they will be fused. If not, the right input is stacked on top of the left input! + title: Kaynaştırıcı + desc: Artık kaynaştırıcı ile şekilleri birleştirebilirsiniz! İki şekil eğer yanyana koyulabilirse şekiller birleştirilir, yoksa sol girişteki şeklin üzerine kaynaştırılır! reward_splitter: - title: Splitter/Merger - desc: The multifunctional balancer has been unlocked - It can be used to build bigger factories by splitting and merging items onto multiple belts!

+ title: Ayırıcı/Bİrleştİrİcİ + desc: Çok fonksiyonlu dengeleyici açıldı - Eşyaları birden fazla taşıma bandı üzerinde ayırarak ve birleştirerek daha büyük fabrikalar kurabilmek için kullanılabilir!

reward_tunnel: - title: Tunnel - desc: The tunnel has been unlocked - You can now pipe items through belts and buildings with it! + title: Tünel + desc: Tünel açıldı - Artık eşyaları taşıma bantları ve yapılar altından geçirebilirsiniz! reward_rotater_ccw: - title: CCW Rotating - desc: You have unlocked a variant of the rotater - It allows to rotate counter clockwise! To build it, select the rotater and press 'T' to cycle its variants! + title: Saat yönünün tersİnde Döndürme + desc: Döndürücünün farklı bir türünü açtın - Şekiller artık saat yönünün tersinde döndürülebilir! İnşa etmek için döndürücüyü seç ve türler arası geçiş yapmak için 'T' tuşuna bas! reward_miner_chainable: - title: Chaining Extractor - desc: You have unlocked the chaining extractor! It can forward its resources to other extractors so you can more efficiently extract resources! + title: Zincirleme Üretİm + desc: Zincirleme üretici açıldı! Zincirleme üretici kendi kaynaklarını diğer üreticilere aktarabilir. Böylece daha etkili üretim sağlayabilirsin! reward_underground_belt_tier_2: - title: Tunnel Tier II - desc: You have unlocked a new variant of the tunnel - It has a bigger range, and you can also mix-n-match those tunnels now! + title: Tünel Aşama II + desc: You have unlocked a new variant of the tunnel - It has a bigger range, and you can also mix-n-match those tunnels now! Tünelin başka bir türünü açtın - Bu tünelin menzili daha yüksek ve tünel türlerini artık içiçe kullanabilirsin! reward_splitter_compact: - title: Compact Balancer + title: Tekİl Dengeleyİcİ desc: >- - You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one! + Dengeleyecinin daha küçük bir türünü açtın - İki taşıma bandından gelen eşyaları tek hatta birleştirir! reward_cutter_quad: - title: Quad Cutting - desc: You have unlocked a variant of the cutter - It allows you to cut shapes in four parts instead of just two! + title: Çeyreğİnİ Kesme + desc: Kesicinin yeni bir türünü açtın - Bu tür şekilleri iki parça yerine dört parçaya ayırabilir! reward_painter_double: - title: Double Painting - desc: You have unlocked a variant of the painter - It works as the regular painter but processes two shapes at once consuming just one color instead of two! + title: Çİfte Boyama + desc: Boyayıcının başka bir türünü açtın - Sıradan bir boyayıcı gibi çalışır, fakat iki şekli birden boyayarak iki boya yerine sadece bir boya harcar! reward_painter_quad: - title: Quad Painting - desc: You have unlocked a variant of the painter - It allows to paint each part of the shape individually! + title: Dörtlü Boyama + desc: Boyayıcının başka bir türünü açtın - Şeklin her parçasının bağımsız olarak boyanmasını sağlar! reward_storage: - title: Storage Buffer - desc: You have unlocked a variant of the trash - It allows to store items up to a given capacity! + title: Depo Sağlayıcı + desc: Çöpün farklı bir türünü açtın - Bu tür belirli bir sınıra kadar eşyaları depolamanı sağlar! reward_freeplay: - title: Freeplay - desc: You did it! You unlocked the free-play mode! This means that shapes are now randomly generated! (No worries, more content is planned for the standalone!) + title: Özgür Mod + desc: Başardın! Özgür mod açıldı! Merkeze istenilen şekiller artık rastgele oluşturulacak! (Merak etme, yeni içerikler planlanıyor!) - reward_blueprints: - title: Blueprints - desc: You can now copy and paste parts of your factory! Select an area (Hold CTRL, then drag with your mouse), and press 'C' to copy it.

Pasting it is not free, you need to produce blueprint shapes to afford it! (Those you just delivered). + reward_blueprints: # 'Taslaklar' yerine 'planlar' da kullanılabilir. + title: Taslaklar + desc: Fabrikanın bölümlerini artık kopyalayıp yapıştırabilirsin! Bir alan seç (CTRL tuşuna bas ve fareyi sol-tık tuşuna basarak sürükle), ve kopyalamak için 'C' tuşuna bas.

Kopyaladığın taslağı bedel karşılığı yapıştırabilmek için taslak şekilleri üretmelisin! (Az önce teslim ettiğin şekiller). # Special reward, which is shown when there is no reward actually no_reward: - title: Next level + title: Sonrakİ Sevİye desc: >- - This level gave you no reward, but the next one will!

PS: Better don't destroy your existing factory - You need all those shapes later again to unlock upgrades! + Bu seviyede ödül yok, ama sonrakinde var!

NOT: En iyisi eski fabrikalarını yok etme - Ürettiğin bütün
şekillere geliştirmeleri açmak için- - Congratulations! By the way, more content is planned for the standalone! + Tebrikler! Bu arada, yeni içerikler planlanıyor! settings: - title: Settings + title: Ayarlar categories: - game: Game - app: Application + general: Genel + userInterface: Kullanıcı Arayüzü + advanced: Gelİşmİş - versionBadges: - dev: Development - staging: Staging - prod: Production - buildDate: Built + versionBadges: # Development, Staging, Production + dev: Geliştirme + staging: Yükseltme + prod: Üretim + buildDate: derlendi labels: uiScale: - title: Interface scale + title: Arayüz Ölçeğİ description: >- - Changes the size of the user interface. The interface will still scale based on your device resolution, but this setting controls the amount of scale. + Kullanıcı arayüzünün boyutunu değiştirir. Arayüz cihazınızın çözünürlüğüne göre ölçeklendirilir, ama ölçeğin miktarı burada ayarlanabilir. scales: - super_small: Super small - small: Small - regular: Regular - large: Large - huge: Huge + super_small: Çok Küçük + small: Küçük + regular: Normal + large: Büyük + huge: Çok Büyük scrollWheelSensitivity: - title: Zoom sensitivity + title: Yakınlaştırma Hassasİyeti description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + Yakınlaştırmanın ne kadar hassas olduğunu ayarlar (Fare tekerleği veya dokunmatik farketmez). sensitivity: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super fast + super_slow: Çok Yavaş + slow: Yavaş + regular: Normal + fast: Hızlı + super_fast: Çok Hızlı language: - title: Language + title: Dİl description: >- - Change the language. All translations are user contributed and might be incomplete! + Dili değiştirir. Bütün çevirmeler kullanıcı katkılarıyla oluşturulmuştur ve tam olmayabilir! fullscreen: - title: Fullscreen + title: Tam Ekran description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. + En iyi oyun tecrübesi için oyunun tam ekranda oynanması tavsiye edilir. Sadece tam sürümde mevcut. soundsMuted: - title: Mute Sounds + title: Ses Efektlerİnİ Sustur description: >- - If enabled, mutes all sound effects. + Aktif edildiğinde bütün ses efektleri susturulur. musicMuted: - title: Mute Music + title: Müzİğİ Sustur description: >- - If enabled, mutes all music. + Aktif edildiğinde bütün müzikler susturulur. theme: - title: Game theme + title: Renk Teması description: >- - Choose the game theme (light / dark). + Renk temasını seçin (aydınlık / karanlık). themes: - dark: Dark - light: Light + dark: Karanlık + light: Aydınlık refreshRate: - title: Simulation Target + title: Sİmülasyon Hızı description: >- - If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. + Eğer mönitörünüzün yenileme hızı (Hz) yüksekse oyunun akıcı bir şekilde çalışması için yenileme hızını buradan değiştirin. Eğer bilgisayarınız yavaşsa bu ayar oyunun gösterdiği kare hızını (FPS) düşürebilir. alwaysMultiplace: - title: Multiplace + title: Çoklu Yerleştirme description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. + Aktif edildiğinde bir yapı seçilip yerleştirildiğinde, yapıyı yerleştirmeye siz iptal edene kadar devam edebilirsiniz. Bu özellik SHIFT tuşuna sürekli basılı tutup yapı yerleştirmeyle aynıdır. offerHints: - title: Hints & Tutorials + title: İpuçları ve Eğİtİmler description: >- - Whether to offer hints and tutorials while playing. Also hides certain UI elements onto a given level to make it easier to get into the game. + İpuçları ve eğitimleri açar. Ayrıca bazı arayüz elemanlarını oyunun daha kolay öğrenilebilmesi için gizler. - movementSpeed: - title: Movement speed + movementHız: + title: Hareket hızı description: Changes how fast the view moves when using the keyboard. - speeds: + Hızs: super_slow: Super slow slow: Slow regular: Regular @@ -721,78 +728,73 @@ settings: When enabled, placing tunnels will automatically remove unnecessary belts. This also enables to drag tunnels and excess tunnels will get removed. vignette: - title: Vignette + title: Gölgelendİrme description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. + Gölgelendirmeyi açar. Gölgelendirme ekranın köşelerini karartır ve yazıları daha kolay okuyabilmeinizi sağlar. autosaveInterval: - title: Autosave Interval + title: Otomatik Kayıt Sıklığı description: >- - Controls how often the game saves automatically. You can also disable it - entirely here. + Oyunun hangi sıklıkta kaydedileceğini belirler. Ayrıca otomatik kayıt tamamen kapatılabilir. intervals: - one_minute: 1 Minute - two_minutes: 2 Minutes - five_minutes: 5 Minutes - ten_minutes: 10 Minutes - twenty_minutes: 20 Minutes - disabled: Disabled + one_minute: 1 Dakika + two_minutes: 2 Dakika + five_minutes: 5 Dakika + ten_minutes: 10 Dakika + twenty_minutes: 20 Dakika + disabled: Devredışı compactBuildingInfo: - title: Compact Building Infos + title: Derlİ Toplu Yapı Bilgileri description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a - description and image is shown. + Yapıların bilgi kutularını sadece oranlarını göstecek şekilde kısaltır. Aksi taktirde yapının açıklaması ve resmi gösterilir. disableCutDeleteWarnings: - title: Disable Cut/Delete Warnings + title: Kes/Sİl Uyarılarını Devredışı Bırak description: >- - Disable the warning dialogs brought up when cutting/deleting more than 100 - entities. + 100 birimden fazla parçayı kesme/silme işlemlerinde beliren uyarı pencerelerini devredışı bırakır. enableColorBlindHelper: - title: Color Blind Mode - description: Enables various tools which allow to play the game if you are color blind. + title: Renk Körü Modu + description: Eğer renkleri seçemiyorsanız oyunu ayarlamak için çeşitli araç gereçleri aktif eder. rotationByBuilding: title: Rotation by building type description: >- - Each building type remembers the rotation you last set it to individually. - This may be more comfortable if you frequently switch between placing - different building types. + Her yapı türü en son kullanıldığı yönü hatırlar. + Yerleştirdiğiniz yapıları sıklıkla değiştiriyorsanız bu ayar oynanyışınızı rahatlatabilir. keybindings: - title: Keybindings + title: Tuş Atamaları hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. + İpucu: CTRL, SHIFT ve ALT tuşlarından yararlanın! Farklı yerleştirme seçeneklerini kullanmanızı sağlarlar. - resetKeybindings: Reset Keyinbindings + resetKeybindings: Tuş Atamalarını Sıfırla categoryLabels: - general: Application - ingame: Game - navigation: Navigating - placement: Placement - massSelect: Mass Select - buildings: Building Shortcuts - placementModifiers: Placement Modifiers + general: Uygulama + ingame: Oyun + navigation: Hareket + placement: Yerleştİrme + massSelect: Çoklu Seçim + buildings: Yapı Kısayolları + placementModifiers: Yerleştİrme Özellİklerİ mappings: - confirm: Confirm - back: Back - mapMoveUp: Move Up - mapMoveRight: Move Right - mapMoveDown: Move Down - mapMoveLeft: Move Left - centerMap: Center Map + confirm: Kabul + back: Geri + mapMoveUp: Yukarı Git + mapMoveRight: Sağa Git + mapMoveDown: Aşagı Git + mapMoveLeft: Sola Git + centerMap: Haritayı Ortala - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker + mapZoomIn: Yakınlaş + mapZoomOut: Uzaklaş + createMarker: Yer İmi Oluştur - menuOpenShop: Upgrades - menuOpenStats: Statistics + menuOpenShop: Geliştirmeler + menuOpenStats: İstatistikler - toggleHud: Toggle HUD - toggleFPSInfo: Toggle FPS and Debug Info + toggleHud: Arayüzü Aç/Kapat + toggleFPSInfo: FPS ve Debug Bilgisini Aç/Kapat belt: *belt splitter: *splitter underground_belt: *underground_belt @@ -804,35 +806,35 @@ keybindings: painter: *painter trash: *trash - rotateWhilePlacing: Rotate + rotateWhilePlacing: Döndür rotateInverseModifier: >- - Modifier: Rotate CCW instead - cycleBuildingVariants: Cycle Variants - confirmMassDelete: Confirm Mass Delete - cycleBuildings: Cycle Buildings + Basılı Tut: Saat yönünün tersinde döndür + cycleBuildingVariants: Yapı türünü değiştir + confirmMassDelete: Çoklu Silme + cycleBuildings: Yapıyı değiştir - massSelectStart: Hold and drag to start - massSelectSelectMultiple: Select multiple areas - massSelectCopy: Copy area + massSelectStart: Basılı tutup seçme + massSelectSelectMultiple: Birden fazla alanı seçme + massSelectCopy: Alanı kopyala - placementDisableAutoOrientation: Disable automatic orientation - placeMultiple: Stay in placement mode - placeInverse: Invert automatic belt orientation - pasteLastBlueprint: Paste last blueprint - massSelectCut: Cut area - exportScreenshot: Export whole Base as Image - mapMoveFaster: Move Faster - lockBeltDirection: Enable belt planner - switchDirectionLockSide: "Planner: Switch side" - pipette: Pipette - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire + placementDisableAutoOrientation: Otomatik Yönü devredışı bırak + placeMultiple: Yerleştirme modunda kal + placeInverse: Taşıma bandı yönünü ters çevir + pasteLastBlueprint: Son taslağı yapıştır + massSelectCut: Alanı yapıştır + exportScreenshot: Bütün merkezi resim olarak dışarı aktar + mapMoveFaster: Hızlı Hareket + lockBeltDirection: Taşıma bandı planlayıcısını akfitleştir + switchDirectionLockSide: "Planlayıcı: Taraf değiştir" + pipette: Pipet + menuClose: Menüyü Kapat + switchLayers: Katman değiştir + advanced_processor: Renk Ters Çevirici + energy_generator: Enerji Üretici + wire: Enerji Kablosu about: - title: About this Game + title: Oyun Hakkında body: >- This game is open source and developed by Tobias Springer (this is me).

@@ -840,9 +842,9 @@ about: If you want to contribute, check out shapez.io on github.

- This game wouldn't have been possible without the great discord community + This game wouldn't have been possible without the great Discord community around my games - You should really join the discord server!

+ target="_blank">Discord server!

The soundtrack was made by Peppsen - He's awesome.

@@ -852,14 +854,14 @@ about: factorio sessions this game would never have existed. changelog: - title: Changelog + title: Değİşİklİk Günlüğü demo: features: - restoringGames: Restoring savegames - importingGames: Importing savegames - oneGameLimit: Limited to one savegame - customizeKeybindings: Customizing Keybindings - exportingBase: Exporting whole Base as Image + restoringGames: Oyun kayıtlarını yükleme + importingGames: Oyun kayıtlarını indirme + oneGameLimit: Bir oyun kaydıyla sınırlı + customizeKeybindings: Tuş Atamalarını Değiştirme + exportingBase: Bütün merkezi resim olarak dışa aktarma - settingNotAvailable: Not available in the demo. + settingNotAvailable: Demo sürümünde mevcut değil diff --git a/translations/base-uk.yaml b/translations/base-uk.yaml index a2658070..885fd477 100644 --- a/translations/base-uk.yaml +++ b/translations/base-uk.yaml @@ -1,6 +1,10 @@ # # GAME TRANSLATIONS # +# Translators: +# +# Prosta4ok_ua 07.07.2020 — 05.09.2020 +# # Contributing: # # If you want to contribute, please make a pull request on this respository @@ -15,16 +19,27 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. -# +# Ґлосарій: +# map мапа +# keybinds гарячі клавіши +# upgrade поліпшення +# marker позначка +# area ділянка +# hub центр +# range дальність +# storage сховище +# shape форма +# layer шар +--- steamPage: # This is the short text appearing on the steam page - shortText: shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. + shortText: shapez.io — це гра про будування фабрик для автоматизації створення та обробки все більш складних форм на нескінченно розширюваній мапі. - # This is the text shown above the discord link - discordLink: Official Discord - Chat with me! + # This is the text shown above the Discord link + discordLink: Офіційний Discord сервер — поговори зі мною! # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: @@ -33,92 +48,95 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.io — це гра про будування фабрик для автоматизації створення та обробки все більш складних форм на нескінченно розширюваній мапі. + Після доставки потрібних форм ви просунетеся в грі та розблокуєте поліпшення, щоб пришвидшити свою фабрику. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Коли попит на форми зростає, вам доведеться збільшити масштаб своєї фабрики, щоб задовольнити попит. Однак не забувайте про ресурси, вам доведеться розширюватися на [b]нескінченній мапі[/b]! - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Незабаром ви зможете змішути кольори і з їхньою допомогою фарбувати свої форми. Поєднуйте червоний, зелений та синій ресурси кольорів, щоб виготовити різноманітні кольори і пофарувати форми як вам заманеться. - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + У цій грі є 18 передових рівнів, які повинні утримувати вас годинами. Але не турбуйтеся, я постійно додаю новий вміст — ще багато чого заплановано! - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + Купуючи гру, ви отримуєте доступ до окремої версії, яка має додаткові функції, а також ви отримаєте доступ до нещодавно розроблених функцій. [img]{STEAM_APP_IMAGE}/extras/header_standalone_advantages.png[/img] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Темний режим + [*] Необмежені позначки + [*] Необмежені збереження + [*] Додаткові налаштування + [*] Незабаром: дроти й енергія! Гадаю, оновлення вийде у кінці липня 2020 року. + [*] Незабаром: більше рівнів. + [*] Дозволяє мені розвиватися далі shapez.io ❤️ [/list] [img]{STEAM_APP_IMAGE}/extras/header_future_updates.png[/img] - I am updating the game very often and trying to push an update at least every week! + Я оновлюю гру надпрочуд часто і намагаюся випускати оновлення щотижня! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Різноманітні мапи та випробування (наприклад, мапи з перешкодами) + [*] Пазли (надайте потрібну форму з обмеженою площею/набором будівель) + [*] Режим історії, де будівлі матимуть вартість + [*] Генератор мап, який можна налаштувати (ресурс/розмір/щільність форми, зерно та багато іншого) + [*] Додаткові типи форм + [*] Поліпшення продуктивності (Гра вже працює досить добре!) + [*] Та багато чого іншого! [/list] [img]{STEAM_APP_IMAGE}/extras/header_open_source.png[/img] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Будь-хто може зробити внесок, я активно беру участь у спільноті і намагаюся оцінити всі пропозиції і відгуки, та взяти до уваги, де це можливо. + Не забудьте перевірити мою дошку Trello заради повної дорожньої карти! [img]{STEAM_APP_IMAGE}/extras/header_links.png[/img] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] - [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Офіційний Discord[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]Дорожня карта[/url] + [*] [url=https://www.reddit.com/r/shapezio]Спільнота на Reddit[/url] + [*] [url=https://github.com/tobspr/shapez.io]Вихідний код на GitHub[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Допоможіть з перекладом[/url] [/list] global: - loading: Loading - error: Error + loading: Завантаження + error: Помилка # How big numbers are rendered, e.g. "10,000" - thousandsDivider: "," + thousandsDivider: " " + + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "," # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: - thousands: k - millions: M - billions: B - trillions: T + thousands: тис. + millions: млн + billions: млрд + trillions: трлн # Shown for infinitely big numbers - infinite: inf + infinite: неск. time: # Used for formatting past time dates - oneSecondAgo: one second ago - xSecondsAgo: seconds ago - oneMinuteAgo: one minute ago - xMinutesAgo: minutes ago - oneHourAgo: one hour ago - xHoursAgo: hours ago - oneDayAgo: one day ago - xDaysAgo: days ago + oneSecondAgo: одну секунду тому + xSecondsAgo: секунд тому + oneMinuteAgo: 1 хвилину тому + xMinutesAgo: хвилин тому + oneHourAgo: одну годину тому + xHoursAgo: годин тому + oneDayAgo: один день тому + xDaysAgo: днів тому # Short formats for times, e.g. '5h 23m' - secondsShort: s - minutesAndSecondsShort: m s - hoursAndMinutesShort: h m + secondsShort: сек. + minutesAndSecondsShort: хв. сек. + hoursAndMinutesShort: год. хв. - xMinutes: minutes + xMinutes: хв. keys: tab: TAB @@ -130,688 +148,691 @@ global: demoBanners: # This is the "advertisement" shown in the main menu and other various places - title: Demo Version + title: Демоверсія intro: >- - Get the standalone to unlock all features! + Завантажте окрему версію, щоб розблокувати всі функції! mainMenu: - play: Play - continue: Continue - newGame: New Game - changelog: Changelog + play: Грати + continue: Продовжити + newGame: Нова гра + changelog: Змінопис subreddit: Reddit - importSavegame: Import - openSourceHint: This game is open source! - discordLink: Official Discord Server - helpTranslate: Help translate! - madeBy: Made by + importSavegame: Імпортувати + openSourceHint: Ця гра з відкритим вихідним кодом! + discordLink: Офіційний Discord сервер + helpTranslate: Допоможіть з перекладом! + madeBy: Зробив # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - Sorry, but the game is known to run slow on your browser! Get the standalone version or download chrome for the full experience. - - savegameLevel: Level - savegameLevelUnknown: Unknown Level - + Вибачте, але гра, як відомо, працює повільно у вашому браузері! Завантажте окрему версію чи хром, щоб отримати більше задоволення від гри. + savegameLevel: Рівень + savegameLevelUnknown: Невідомий рівень dialogs: buttons: - ok: OK - delete: Delete - cancel: Cancel - later: Later - restart: Restart - reset: Reset - getStandalone: Get Standalone - deleteGame: I know what I am doing - viewUpdate: View Update - showUpgrades: Show Upgrades - showKeybindings: Show Keybindings + ok: Гаразд + delete: Видалити + cancel: Скасувати + later: Пізніше + restart: Перезавантажити + reset: Скинути + getStandalone: Завантажити гру + deleteGame: Я знаю, що роблю + viewUpdate: Переглянути оновлення + showUpgrades: Показати поліпшення + showKeybindings: Показати прив’язки клавіш importSavegameError: - title: Import Error + title: Помилка при імпортуванні text: >- - Failed to import your savegame: + Не вдалося імпортувати вашу збережену гру: importSavegameSuccess: - title: Savegame Imported + title: Збереження імпортовано text: >- - Your savegame has been successfully imported. + Вашу збережену гру успішно імпортовано. gameLoadFailure: - title: Game is broken + title: Гра поламана text: >- - Failed to load your savegame: + Не вдалося завантажити вашу збережену гру. confirmSavegameDelete: - title: Confirm deletion + title: Підтвердження text: >- - Are you sure you want to delete the game? + Ви справді хочете видалити гру? savegameDeletionError: - title: Failed to delete + title: Виникла помилка при видаленні text: >- - Failed to delete the savegame: + Не вдалося видалити збережену гру. restartRequired: - title: Restart required + title: Потрібне перезавантаження text: >- - You need to restart the game to apply the settings. + Перезавантажте гру, щоб налаштування вступили в дію. editKeybinding: - title: Change Keybinding - desc: Press the key or mouse button you want to assign, or escape to cancel. + title: Зміна гарячої клавіши + desc: Натисніть клавішу, яку ви хочете призначити, або escape для скасування. resetKeybindingsConfirmation: - title: Reset keybindings - desc: This will reset all keybindings to their default values. Please confirm. + title: Скинути гарячу клавіші + desc: Це скине всі прив'язки клавіш до їхніх значень за замовчуванням. Будь ласка, підтвердіть. keybindingsResetOk: - title: Keybindings reset - desc: The keybindings have been reset to their respective defaults! + title: Скинути гарячі клавіші + desc: Гарячі клавіши скинемуться до їхніх початкових значень! featureRestriction: - title: Demo Version - desc: You tried to access a feature () which is not available in the demo. Consider getting the standalone version for the full experience! + title: Демоверсія + desc: Ви спробували отримати доступ до функції (), яка недоступна в демонстраційній версії. Подумайте про отримання окремої версії, щоб насолодитися грою сповна! oneSavegameLimit: - title: Limited savegames - desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone version! + title: Обмежені збереження + desc: Ви можете мати лише одне збереження одночасно в демоверсії. Будь ласка, видаліть збереження чи завантажте окрему версію гри! updateSummary: - title: New update! + title: Нове оновлення! desc: >- - Here are the changes since you last played: + Ось зміни з вашої останньої гри: upgradesIntroduction: - title: Unlock Upgrades + title: Розблокування поліпшень desc: >- - All shapes you produce can be used to unlock upgrades - Don't destroy your old factories! - The upgrades tab can be found on the top right corner of the screen. + Усі форми, що ви виробляєте, можуть використовуватися для розблокування поліпшення - Не зруйнуйте свої старі фабрики! + Вкладку з поліпшеннями можна знайти в правому верхньому куті екрана. massDeleteConfirm: - title: Confirm delete + title: Підтвердження видалення desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? + Ви видаляєте багато будівль (, якщо бути точним)! Ви справді хочете зробити це? massCutConfirm: - title: Confirm cut + title: Підтвердження вирізання desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you want to do this? + Ви вирізаєте багато будівль(, якщо бути точним)! Ви справді хочете зробити це? massCutInsufficientConfirm: - title: Confirm cut + title: Підтвердити вирізання desc: >- - You can not afford to paste this area! Are you sure you want to cut it? + Ви не можете дозволити собі вставити цю область! Ви справді хочете вирізати це? blueprintsNotUnlocked: - title: Not unlocked yet + title: Ще не розблоковано desc: >- - Complete level 12 to unlock Blueprints! + Досягніть 13-го рівня, щоб розблокувати креслення! keybindingsIntroduction: - title: Useful keybindings + title: Корисні гарячі клавіши desc: >- - This game has a lot of keybindings which make it easier to build big factories. - Here are a few, but be sure to check out the keybindings!

- CTRL + Drag: Select an area.
- SHIFT: Hold to place multiple of one building.
- ALT: Invert orientation of placed belts.
+ Гра має багато гарячих клавіш, що полегшують будівництво великих фабрик. + Ось декілька, але обов’язково ознайомтеся з прив’язками клавіш!

+ CTRL + тягніть: виділити зону.
+ SHIFT: тримайте, щоб розмістити декілька одного будинку.
+ ALT: змінити сторону розміщеної конвеєрної стрічки.
createMarker: - title: New Marker - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) - titleEdit: Edit Marker + title: Нова позначка + titleEdit: Редагувати позначку + desc: Дайте їй змістовну назву. Ви також можете додати короткий ключ форми, що можно згенерувати тут. markerDemoLimit: - desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! + desc: Ви можете створити тільки 2 позначки в демоверсії. Отримайте окрему версії для створення необмеженної кількості позначок. exportScreenshotWarning: - title: Export screenshot - desc: You requested to export your base as a screenshot. Please note that this can be quite slow for a big base and even crash your game! + title: Експортувати зняток + desc: Ви просили експортувати свою базу як знімок екрана. Зверніть увагу, що для великої бази це може бути досить повільним процесом і може навіть зруйнувати вашу гру! ingame: # This is shown in the top left corner and displays useful keybindings in # every situation keybindingsOverlay: - moveMap: Move - selectBuildings: Select area - stopPlacement: Stop placement - rotateBuilding: Rotate building - placeMultiple: Place multiple - reverseOrientation: Reverse orientation - disableAutoOrientation: Disable auto-orientation - toggleHud: Toggle HUD - placeBuilding: Place building - createMarker: Create marker - delete: Delete - pasteLastBlueprint: Paste last blueprint - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side - cutSelection: Cut - copySelection: Copy - clearSelection: Clear selection - pipette: Pipette - switchLayers: Switch layers + moveMap: Рухатися + selectBuildings: Виділити будівлі + stopPlacement: Зупинити розміщення + rotateBuilding: Повернути будівлю + placeMultiple: Розмістити декілька + reverseOrientation: Змінити орієнтацію + disableAutoOrientation: Вимкнути автоматичну орієнтацію + toggleHud: Перемкнути інтерфейс + placeBuilding: Розмістити будівлю + createMarker: Створити позначку + delete: Видалити + pasteLastBlueprint: Вставити останнє креслення + lockBeltDirection: Увімкнути стрічковий планувальник + plannerSwitchSide: Змінити сторону планувальника + cutSelection: Вирізати + copySelection: Скопіювати + clearSelection: Очистити виділене + pipette: Піпетка + switchLayers: Змінити шари # Names of the colors, used for the color blind mode colors: - red: Red - green: Green - blue: Blue - yellow: Yellow - purple: Purple - cyan: Cyan - white: White - black: Black - uncolored: No color + red: Червоний + green: Зелений + blue: Синій + yellow: Жовтий + purple: Фіолетовий + cyan: Блакитний + white: Білий + black: Чорний + uncolored: Без кольору # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) buildingPlacement: # Buildings can have different variants which are unlocked at later levels, # and this is the hint shown when there are multiple variants available. - cycleBuildingVariants: Press to cycle variants. + cycleBuildingVariants: Натисніть для циклу варіантів. # Shows the hotkey in the ui, e.g. "Hotkey: Q" hotkeyLabel: >- Hotkey: infoTexts: - speed: Speed - range: Range - storage: Storage - oneItemPerSecond: 1 item / second - itemsPerSecond: items / s + speed: Швидкість + range: Дальність + storage: Сховище + oneItemPerSecond: 1 предмет за сек. + itemsPerSecond: предмет. за сек itemsPerSecondDouble: (x2) - tiles: tiles + tiles: плиток # The notification when completing a level levelCompleteNotification: # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: Level - completed: Completed - unlockText: Unlocked ! - buttonNextLevel: Next Level + levelTitle: Рівень + completed: Завершено + unlockText: Розблоковано «»! + buttonNextLevel: Наступний рівень # Notifications on the lower right notifications: - newUpgrade: A new upgrade is available! - gameSaved: Your game has been saved. + newUpgrade: Нове оновлення розблоковано! + gameSaved: Вашу гру збережено. # The "Upgrades" window shop: - title: Upgrades - buttonUnlock: Upgrade + title: Поліпшення + buttonUnlock: Поліпшення # Gets replaced to e.g. "Tier IX" - tier: Tier + tier: Ранг # The roman number for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXIMUM LEVEL (Speed x) + maximumLevel: МАКСИМАЛЬНИЙ РІВЕНЬ (Швидкість x) # The "Statistics" window statistics: - title: Statistics + title: Статистика dataSources: stored: - title: Stored - description: Displaying amount of stored shapes in your central building. + title: Зберігається + description: Відображає кількість збережених фігур у вашому центрі. produced: - title: Produced - description: Displaying all shapes your whole factory produces, including intermediate products. + title: Виробляється + description: Відображає всі форми вашої цілої фабрики, що виробляються, включаючи проміжні продукти. delivered: - title: Delivered - description: Displaying shapes which are delivered to your central building. - noShapesProduced: No shapes have been produced so far. + title: Доставлено + description: Відображає форми, що доставляються до центру. + noShapesProduced: Жодної форми поки не випускається. # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m + shapesPerMinute: за хв. # Settings menu, when you press "ESC" settingsMenu: - playtime: Playtime + playtime: У грі - buildingsPlaced: Buildings - beltsPlaced: Belts + buildingsPlaced: Будівлі + beltsPlaced: Стрічки buttons: - continue: Continue - settings: Settings - menu: Return to menu + continue: Продовжити + settings: Налаштування + menu: Повернутися до меню # Bottom left tutorial hints tutorialHints: - title: Need help? - showHint: Show hint - hideHint: Close + title: Потрібна допомога? + showHint: Показати підказку + hideHint: Закрити # When placing a blueprint blueprintPlacer: - cost: Cost + cost: Вартість # Map markers waypoints: - waypoints: Markers - hub: HUB - description: Left-click a marker to jump to it, right-click to delete it.

Press to create a marker from the current view, or right-click to create a marker at the selected location. - creationSuccessNotification: Marker has been created. + waypoints: Позначки + hub: Центр + description: ЛКМ на позначку, щоб перейти до неї, ПКМ для видалення

Натисніть для створення позначки з поточного виду або ПКМ, щоб створити позначку в обраному місці. + creationSuccessNotification: Позначку створено. # Shape viewer shapeViewer: - title: Layers - empty: Empty - copyKey: Copy Key + title: Шари + empty: Пустий + copyKey: Копіювати ключ # Interactive tutorial interactiveTutorial: - title: Tutorial + title: Навчання hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! + 1_1_extractor: Розмістіть екстрактор поверх фігури кола, щоб отримати її! 1_2_conveyor: >- - Connect the extractor with a conveyor belt to your hub!

Tip: Click and drag the belt with your mouse! + З’єднайте екстрактор з вашим центром за допомогою конвеєрної стрічки!

Підказка: Натисніть і протягніть стрічку вашою мишею. 1_3_expand: >- - This is NOT an idle game! Build more extractors and belts to finish the goal quicker.

Tip: Hold SHIFT to place multiple extractors, and use R to rotate them. + У цій грі ВАМ НЕ ПОТРІБНО БЕЗДІЯТИ! Будуйте більше екстракторів і стрічок, щоб виконати свою мету швидше.

Підказка: Утримуйте SHIFT, щоб розмістити багато екстракторів, і використовуйте R, щоб обертати їх. # All shop upgrades shopUpgrades: belt: - name: Belts, Distributor & Tunnels - description: Speed x → x + name: Стрічки, розподілювачі і тунелі + description: Швидкість x → x miner: - name: Extraction - description: Speed x → x + name: Видобуток + description: Швидкість x → x processors: - name: Cutting, Rotating & Stacking - description: Speed x → x + name: Різання, обертання й укладання + description: Швидкість x → x painting: - name: Mixing & Painting - description: Speed x → x + name: Змішування і малювання + description: Швидкість x → x # Buildings and their name / description buildings: hub: - deliver: Deliver - toUnlock: to unlock - levelShortcut: LVL + deliver: Доставте, + toUnlock: щоб розблокувати + levelShortcut: РІВ belt: default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. + name: &belt Конвеєрна стрічка + description: Транспортує предмети, утримуйте і перетягуйте для розміщення декількох. wire: default: - name: &wire Wire - description: Allows you to transport energy + name: &wire Дріт + description: Дозволяє передавати енергію - miner: # Internal name for the Extractor + # Internal name for the Extractor + miner: default: - name: &miner Extractor - description: Place over a shape or color to extract it. + name: &miner Екстрактор + description: Розмістіть над формою чи кольором, який хочете видобути. chainable: - name: Extractor (Chain) - description: Place over a shape or color to extract it. Can be chained. + name: Екстрактор (Ланц.) + description: Розмістіть над формою чи кольором, який хочете видобути. Можна об’єднати в ланцюг. - underground_belt: # Internal name for the Tunnel + # Internal name for the Tunnel + underground_belt: default: - name: &underground_belt Tunnel - description: Allows you to tunnel resources under buildings and belts. + name: &underground_belt Тунель + description: Дозволяє транспортувати ресурси під будівлями та стрічками. tier2: - name: Tunnel Tier II - description: Allows you to tunnel resources under buildings and belts. + name: Тунель, ранг II + description: Дозволяє транспортувати ресурси під будівлями та стрічками. - splitter: # Internal name for the Balancer + # Internal name for the Balancer + splitter: default: - name: &splitter Balancer - description: Multifunctional - Evenly distributes all inputs onto all outputs. + name: &splitter Розподілювач + description: Багатофункціональний. Рівномірно розподіляє все, що входить. compact: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: З’єднувач + description: Об’єднує дві конвеєрні стрічки в одну. Займає усього на всього одну клітину. compact-inverse: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: З’єднувач + description: Об’єднує дві конвеєрні стрічки в одну. Займає усього на всього одну клітину. cutter: default: - name: &cutter Cutter - description: Cuts shapes from top to bottom and outputs both halves. If you use only one part, be sure to destroy the other part or it will stall! + name: &cutter Різчик + description: Розрізає форми зверху вниз і виводить обидві половинки. Якщо ви використовуєте лише одну частину, не забудьте знищити іншу частину, інакше вона застрягне в механізмі! quad: - name: Cutter (Quad) - description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other parts or it will stall! + name: Різчик (4 вих.) + description: Розрізає форми на 4 частини. Якщо ви використовуєте лише одну частину, не забудьте знищити інші, інакше вони застрягнуть в механізмі! advanced_processor: default: - name: &advanced_processor Advanced Processor - description: Advanced shape processing + name: &advanced_processor Передовий процесор + description: Покращена обробка форм. rotater: default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. + name: &rotater Обертач + description: Обертає форми за годинниковою стрілкою на 90 градусів. ccw: - name: Rotate (CCW) - description: Rotates shapes counter-clockwise by 90 degrees. + name: Обертач (-90) + description: Обертає форми проти годинникової стрілки на 90 градусів. + fl: + name: Обертач (180) + description: Обертає форми на 180 градусів. stacker: default: - name: &stacker Stacker - description: Stacks both items. If they can not be merged, the right item is placed above the left item. + name: &stacker Укладальник + description: Складає обидва елементи. Якщо їх неможливо об’єднати, правий елемент розміщується над лівим елементом. mixer: default: - name: &mixer Color Mixer - description: Mixes two colors using additive blending. + name: &mixer Змішувач кольорів + description: Змішує два кольори за допомогою добавки. painter: default: - name: &painter Painter - description: &painter_desc Colors the whole shape on the left input with the color from the top input. + name: &painter Фарбувач + description: &painter_desc Забирає форму з лівого входу, а колір з верхнього. mirrored: name: *painter description: *painter_desc double: - name: Painter (Double) - description: Colors the shapes on the left inputs with the color from the top input. + name: Фарбувач (подв.) + description: Фарбує фігури, що надійшла з лівого входу, кольором, що надійшов з верхнього. quad: - name: Painter (Quad) - description: Allows you to color each quadrant of the shape with a different color. + name: Фарбувач (чотири) + description: Дозволяє вам фарбувати кожну четвертину форми у різний колір. trash: default: - name: &trash Trash - description: Accepts inputs from all sides and destroys them. Forever. + name: &trash Смітник + description: Приймає форми зі всіх сторін і руйнує їх. Назавжди. storage: - name: Storage - description: Stores excess items, up to a given capacity. Can be used as an overflow gate. + name: Сховище + description: Зберігає зайві предмети до заданої місткості. Може використовуватися для зберігання надлишкових речей. energy_generator: - deliver: Deliver + deliver: Доставте # This will be shown before the amount, so for example 'For 123 Energy' - toGenerateEnergy: For + toGenerateEnergy: За default: - name: &energy_generator Energy Generator - description: Generates energy by consuming shapes. Each energy generator requires a different shape. + name: &energy_generator Енергетичний генератор + description: Створює енергію споживаючи форми. Кожний енергетичний генератор потрібує свою форму. wire_crossings: default: - name: &wire_crossings Wire Splitter - description: Splits a wire into two + name: &wire_crossings Дротовий розподілювач + description: Ділить дріт надвоє. merger: - name: Wire Merger - description: Merges two wires into one + name: Дротовий з’єднувач + description: Об’єднує два дроти в один. storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: - title: Cutting Shapes - desc: You just unlocked the cutter - it cuts shapes half from top to bottom regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will stall - For this purpose I gave you a trash, which destroys everything you put into it! + title: Різання фігур + desc: Ви тільки-но розблокували різця. Він розрізає фігури наполовину з вершини до низу незалежно від його орієнтації!

Обов’язково позбудьтесь відходів або він зупиниться. Для цього є смітник, який знищує все, що входить в нього. reward_rotater: - title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. + title: Обертання + desc: Обертач розблоковано! Він повертає форми за годинниковою стрілкою на 90 градусів. reward_painter: - title: Painting + title: Фарбування desc: >- - The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, there is a colorblind mode in the settings! + Фарбувач розблоковано. Видобудьте трохи кольорів з відповідних жилок (як ви зробили це з формами) і об’єднуйте їх з формами у фарбувачі, щоб розфарбувати форми!

До речі, якщо ви дальтонік, то в увімкніть режим високої контрастності в налаштуваннях! reward_mixer: - title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! + title: Змішування кольорів + desc: Змішування кольорів розблоковано. Об’єднуйте два кольори у цій будівлі. reward_stacker: - title: Combiner - desc: You can now combine shapes with the combiner! Both inputs are combined, and if they can be put next to each other, they will be fused. If not, the right input is stacked on top of the left input! + title: Поєднувач форм + desc: Тепер ви можете поєднувати фігури з поєднувачем форм! Форми об’єднуються з двох сторін, і якщо їх можна поставити поруч, вони будуть з’єднані. Якщо ні, то форма, що подана з правого входу, застрягне на горі лівого входу. reward_splitter: - title: Splitter/Merger - desc: The multifunctional balancer has been unlocked - It can be used to build bigger factories by splitting and merging items onto multiple belts!

+ title: Розподілювач (з’єднувач) + desc: Багатофункціональний розподілювач було розблоковано. Його можна використовувати для створення великих фабрик, розділяючи та об’єднуючи предмети на кілька стрічок!

reward_tunnel: - title: Tunnel - desc: The tunnel has been unlocked - You can now tunnel items through belts and buildings with it! + title: Тунель + desc: Тунель розблоковано. Ви можете створювати тунелі для преметів через стрічки і будівлі. reward_rotater_ccw: - title: CCW Rotating - desc: You have unlocked a variant of the rotater - It allows you to rotate shapes counter-clockwise! To build it, select the rotater and press 'T' to cycle through its variants! + title: Обертання проти годинникової стрілки + desc: Ви розблокували новий варіант обертача. Він дозволяє обертати проти годинникової стрілки! Щоб побудувати його виберіть обертач, натисніть «T», щоб переглянути всі варіанти, та оберіть потрібний! reward_miner_chainable: - title: Chaining Extractor - desc: You have unlocked the chaining extractor! It can forward its resources to other extractors so you can more efficiently extract resources! + title: Екстрактор (ланцюг.) + desc: Ви розблокували ланцюговий екстрактор! Він може пересилати свої ресурси іншим екстракторам, щоб ви могли ефективніше видобувати ресурси! reward_underground_belt_tier_2: - title: Tunnel Tier II - desc: You have unlocked a new variant of the tunnel - It has a bigger range, and you can also mix-n-match those tunnels now! + title: Тунель II + desc: Ви розблокували новий варіант тунеля. Він має більшу дальність, і ви можете також змішувати і зіставляти ці тунелі! reward_splitter_compact: - title: Compact Balancer + title: Компактний розподілювач desc: >- - You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one belt! + Ви розблокували компактний варіант розподілювача. Він приймає з двох сторін і об’єднує на одну стрічку! reward_cutter_quad: - title: Quad Cutting - desc: You have unlocked a variant of the cutter - It allows you to cut shapes in four parts instead of just two! + title: Різчик (чотири) + desc: Ви розблокували інший варіант різчика. Він може розрізати форми на чотири частини замість двох. reward_painter_double: title: Double Painting - desc: You have unlocked a variant of the painter - It works as the regular painter but processes two shapes at once consuming just one color instead of two! + desc: Ви розблокували інший варіант фарбувача. Він працює як звичайний фарбувач, але обробляє дві фігури одночасно, споживаючи лише один колір замість двох! reward_painter_quad: title: Quad Painting - desc: You have unlocked a variant of the painter - It allows you to paint each part of the shape individually! + desc: Ви розблокували інший варіант фарбувача. Він дозволяє фарбувати кожну частину форми індивідуально! reward_storage: title: Storage Buffer - desc: You have unlocked a variant of the trash - It allows you to store items up to a given capacity! + desc: Ви розблокували інший варіант trash - It allows you to store items up to a given capacity! reward_freeplay: - title: Freeplay - desc: You did it! You unlocked the free-play mode! This means that shapes are now randomly generated! (No worries, more content is planned for the standalone!) + title: Пісочниця + desc: Ви зробили це! Ви розблокували вільний режим! Це означає, що форми тут створюватимуться випадкові! Не хвилюйтеся, більше контенту планується для окремого режиму! reward_blueprints: - title: Blueprints - desc: You can now copy and paste parts of your factory! Select an area (Hold CTRL, then drag with your mouse), and press 'C' to copy it.

Pasting it is not free, you need to produce blueprint shapes to afford it! (Those you just delivered). + title: Креслення + desc: Ви вже можете копіювати і вставляти частини вашої фабрики. Виберіть зону (утримуйте CTRL, а тоді тягніть мишою), і натисніть «C», щоб скопіювати.

Вставляти креслення — річ не безкоштовна, спочатку вам потрібно створити форми креслень, щоб собі це дозволити! (ті, що ви щойно доставили). # Special reward, which is shown when there is no reward actually no_reward: - title: Next level + title: Наступний рівень desc: >- - This level gave you no reward, but the next one will!

PS: Better don't destroy your existing factory - You need all those shapes later again to unlock upgrades! - - + Цей рівень не дав нагороди, але в наступному... щось буде.

До речі, краще не руйнуйте свою поточну фабрику. Вам знадобляться всі ті форми пізніше, щоб розблокувати поліпшення! no_reward_freeplay: - title: Next level + title: Наступний рівень desc: >- - Congratulations! By the way, more content is planned for the standalone! + Вітаємо! До речі, більше контенту планується в окремій версії! settings: - title: Settings + title: Налаштування categories: - game: Game - app: Application + general: Загальне + userInterface: Користувацький інтерфейс + advanced: Передове versionBadges: - dev: Development - staging: Staging - prod: Production - buildDate: Built + dev: Розробка + staging: Тестування + prod: Виробництво + buildDate: Створено labels: uiScale: - title: Interface scale + title: Масштаб інтерфейсу description: >- - Changes the size of the user interface. The interface will still scale based on your device's resolution, but this setting controls the amount of scaling. + Змінює розмір користувацього інтерфейсу. Інтерфейс усе ще буде масштабуватися залежно від роздільної здатності вашого пристрою, але цей параметр контролює масштаб масштабування. scales: - super_small: Super small - small: Small - regular: Regular - large: Large - huge: Huge + super_small: Надзвичайно малий + small: Малий + regular: Звичайний + large: Великий + huge: Величезний autosaveInterval: - title: Autosave Interval + title: Проміжок між автозбереженнями description: >- - Controls how often the game saves automatically. You can also disable it entirely here. + Контролює, як часто гра автоматично зберігатиметься. Ви також можете повністю вимкнути його тут. intervals: - one_minute: 1 Minute - two_minutes: 2 Minutes - five_minutes: 5 Minutes - ten_minutes: 10 Minutes - twenty_minutes: 20 Minutes - disabled: Disabled + one_minute: 1 хвилина + two_minutes: 2 хвилини + five_minutes: 5 хвилин + ten_minutes: 10 хвилин + twenty_minutes: 20 хвилин + disabled: Вимкнено scrollWheelSensitivity: - title: Zoom sensitivity + title: Чутливість масштабування description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + Змінює наскільки чутливе масштабування (колесо миші або трекпад). sensitivity: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super fast + super_slow: Надзвичайно повільна + slow: Повільна + regular: Звичайна + fast: Швидка + super_fast: Надзвичайно швидка movementSpeed: - title: Movement speed + title: Швидкість руху description: >- - Changes how fast the view moves when using the keyboard. + Змінює Змінює швидкість руху бачення при використанні клавіатури. speeds: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super Fast - extremely_fast: Extremely Fast + super_slow: Надзвичайно повільна + slow: Повільна + regular: Звичайна + fast: Швидка + super_fast: Надзвичайно швидка + extremely_fast: Екстремально швидка language: - title: Language + title: Мова description: >- - Change the language. All translations are user-contributed and might be incomplete! + Зміна мови. Усі переклади зроблені користувачами і можуть бути незавершеними! enableColorBlindHelper: - title: Color Blind Mode + title: Режим високої контрастності description: >- - Enables various tools which allow you to play the game if you are color blind. + Дозволяє використовувати різні інструменти, які дозволяють грати в гру, якщо ви є дальтоніком. fullscreen: - title: Fullscreen + title: Повноекранний режим description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. + Щоб повністю насолодитися грою, рекомендується грати у повноекранному режимі. Не доступно тільки в демоверсії. soundsMuted: - title: Mute Sounds + title: Заглушити звуки description: >- - If enabled, mutes all sound effects. + Якщо увімкнено, то вимикає всі звукові ефекти. musicMuted: - title: Mute Music + title: Заглушити музику description: >- - If enabled, mutes all music. + Якщо увімкнено, то вимикає всю музику. theme: - title: Game theme + title: Тема гри description: >- - Choose the game theme (light / dark). + Оберіть тему гри (світлу чи темну). themes: - dark: Dark - light: Light + dark: Темна + light: Світла refreshRate: - title: Simulation Target + title: Частота оновлення description: >- - If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. + Якщо ви маєте 144-герцовий монітор, то змініть частоту оновлення тут, щоб гра правильно працювала при більшій швидкості оновлення. Це може фактично знизити FPS, якщо ваш комп’ютер занадто повільний. alwaysMultiplace: - title: Multiplace + title: Мультирозміщення description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. + Якщо ввімкнено, всі будівлі залишатимуться вибраними після розміщення, доки ви не скасуєте це. Це еквівалентно постійному утримуванню SHIFT. offerHints: - title: Hints & Tutorials + title: Підказки & посібники description: >- - Whether to offer hints and tutorials while playing. Also hides certain UI elements up to a given level to make it easier to get into the game. + Якщо увімкнено, то пропонує підказки та посібники під час гри. Також приховує певні елементи інтерфейсу до заданого рівня, щоб полегшити потрапляння в гру. enableTunnelSmartplace: - title: Smart Tunnels + title: Розумні тунелі description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. This also enables you to drag tunnels and excess tunnels will get removed. + Якщо увімкнено, то розміщення тунелів видалить непотрібні стрічки. Це також дозволяє вам перетягувати тунелі і видаляти автоматично зайві тунелі. vignette: - title: Vignette + title: Віньєтка description: >- - Enables the vignette, which darkens the screen corners and makes text easier to read. + Вмикає віньєтку, яка затемнює кути екрану і робить текст легшим для читання. rotationByBuilding: - title: Rotation by building type + title: Обертання за типом будівлі description: >- - Each building type remembers the rotation you last set it to individually. This may be more comfortable if you frequently switch between placing different building types. + Кожний тип будівлі запам’ятовує обертання, яке ви встановили. Це може бути зручнішим, якщо ви часто перемикаєтесь між розміщенням різних типів будівель. compactBuildingInfo: - title: Compact Building Infos + title: Компактна інформація про будівлі description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. + Скорочує інформаційні поля для будівель, лише показуючи їх співвідношення. В іншому випадку відображається опис та зображення. disableCutDeleteWarnings: - title: Disable Cut/Delete Warnings + title: Вимкнути попердження про вирізання та видалення description: >- - Disables the warning dialogs brought up when cutting/deleting more than 100 entities. + Вимикає діалогові вікна попередження, що з’являються під час вирізання/видалення більше 100 об’єктів. keybindings: - title: Keybindings + title: Гарячі клавіши hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. + Tip: Упевніться, що ви можете використовувати CTRL, SHIFT і ALT! Вони дозволяють різні варіанти розміщення. - resetKeybindings: Reset Keybindings + resetKeybindings: Скинути гарячі клавіші categoryLabels: - general: Application - ingame: Game - navigation: Navigating - placement: Placement - massSelect: Mass Select - buildings: Building Shortcuts - placementModifiers: Placement Modifiers + general: Застосунок + ingame: Гра + navigation: Навігація + placement: Розміщення + massSelect: Масовий вибір + buildings: Гарячі клавіши будівництва + placementModifiers: Модифікатори розміщення mappings: - confirm: Confirm - back: Back - mapMoveUp: Move Up - mapMoveRight: Move Right - mapMoveDown: Move Down - mapMoveLeft: Move Left - mapMoveFaster: Move Faster - centerMap: Center Map + confirm: Підтвердити + back: Назад + mapMoveUp: Угору + mapMoveRight: Праворуч + mapMoveDown: Униз + mapMoveLeft: Ліворуч + mapMoveFaster: Пришвидшитися + centerMap: Центрувати мапу - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker + mapZoomIn: Приблизити + mapZoomOut: Віддалити + createMarker: Створити позначку - menuOpenShop: Upgrades - menuOpenStats: Statistics - menuClose: Close Menu + menuOpenShop: Поліпшення + menuOpenStats: Статистика + menuClose: Закрити меню - toggleHud: Toggle HUD - toggleFPSInfo: Toggle FPS and Debug Info - switchLayers: Switch layers - exportScreenshot: Export whole Base as Image + toggleHud: Перемкнути користувацький інтерфейс + toggleFPSInfo: Перемкнути інформацію про FPS та зневадження + switchLayers: Перемкнути шари + exportScreenshot: Експортувати цілу базу у вигляді зображення belt: *belt splitter: *splitter underground_belt: *underground_belt @@ -826,49 +847,49 @@ keybindings: trash: *trash wire: *wire - pipette: Pipette - rotateWhilePlacing: Rotate + pipette: Піпетка + rotateWhilePlacing: Повернути rotateInverseModifier: >- - Modifier: Rotate CCW instead - cycleBuildingVariants: Cycle Variants - confirmMassDelete: Delete area - pasteLastBlueprint: Paste last blueprint - cycleBuildings: Cycle Buildings - lockBeltDirection: Enable belt planner + Modifier: Повернути проти годинникової стрілки натомість + cycleBuildingVariants: Повторювати варіанти циклічно + confirmMassDelete: Видалити ділянку + pasteLastBlueprint: Вставити останнє креслення + cycleBuildings: Перемикання будівль + lockBeltDirection: Увімкнути планувальник конвеєрних стрічок switchDirectionLockSide: >- - Planner: Switch side + Planner: Змінити сторону - massSelectStart: Hold and drag to start - massSelectSelectMultiple: Select multiple areas - massSelectCopy: Copy area - massSelectCut: Cut area + massSelectStart: Утримуйте і перетягуйте, щоб розпочати + massSelectSelectMultiple: + massSelectCopy: Копіювати ділянку + massSelectCut: Вирізати ділянку - placementDisableAutoOrientation: Disable automatic orientation - placeMultiple: Stay in placement mode - placeInverse: Invert automatic belt orientation + placementDisableAutoOrientation: Вимкнути автоматичну орієнтацію + placeMultiple: Залишатися у режимі розміщення + placeInverse: Перевернути автоматичну орієнтацію стрічки about: - title: About this Game + title: Про гру body: >- - This game is open source and developed by Tobias Springer (this is me).

+ Ця гра з відкритим вихідним кодом і розроблена Tobias Springer (це я).

- If you want to contribute, check out shapez.io on github.

+ Якщо ви хочете зробити внесок, то йдіть на github shapez.io.

- This game wouldn't have been possible without the great discord community around my games - You should really join the discord server!

+ Ця гра не була б можливою без великої Discord спільноти навколо моїх ігор. Гадаю, вам дійсно слід долучитися до серверу в discord!

- The soundtrack was made by Peppsen - He's awesome.

+ Звуковий трек був зроблений гравцем Peppsen — він просто приголомшливий.

- Finally, huge thanks to my best friend Niklas - Without our factorio sessions, this game would never have existed. + І нарешті, величезна подяка моєму найкращому другу Niklas, бо без наших сеансів у факторіо ця гра ніколи б не існувала. changelog: - title: Changelog + title: Змінопис demo: features: - restoringGames: Restoring savegames - importingGames: Importing savegames - oneGameLimit: Limited to one savegame - customizeKeybindings: Customizing Keybindings - exportingBase: Exporting whole Base as Image + restoringGames: Відновлення збережень + importingGames: Імпортування збережень + oneGameLimit: Обмежено одним збереженням + customizeKeybindings: Налаштування гарячих клавіш + exportingBase: Експортування цілої бази у вигляді зображення - settingNotAvailable: Not available in the demo. + settingNotAvailable: Недоступно в демоверсії. diff --git a/translations/base-zh-CN.yaml b/translations/base-zh-CN.yaml index 989751f1..225619e0 100644 --- a/translations/base-zh-CN.yaml +++ b/translations/base-zh-CN.yaml @@ -15,7 +15,7 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # @@ -45,6 +45,7 @@ # Painter:上色机 # Trash:垃圾桶 +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io 是一款在无边际的地图上建造工厂、自动化生产与组合愈加复杂的图形的游戏。 @@ -119,6 +120,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: "" + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # TODO: Chinese translation: suffix changes every 10000 in Chinese numbering system. # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: @@ -172,13 +176,11 @@ mainMenu: # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - 很抱歉, 本游戏在当前浏览器上可能运行缓慢! 使用chrome或者获取独立版以得到更好的体验。 + 很抱歉, 本游戏在当前浏览器上可能运行缓慢! 使用 Chrome 或者获取独立版以得到更好的体验。 savegameLevel: 第关 - savegameLevelUnknown: 未知关卡 - - - # contestOver: This contest has ended - Join the discord to get noticed about new contests! + savegameLevelUnknown: + 未知关卡 continue: 继续游戏 newGame: 新游戏 madeBy: 作者: @@ -230,7 +232,7 @@ dialogs: editKeybinding: title: 更改按键设置 - desc: 请按下你想要使用的按键,或者按下ESC键来取消设置。 + desc: 请按下你想要使用的按键,或者按下 ESC 键来取消设置。 resetKeybindingsConfirmation: title: 重置所有按键 @@ -242,11 +244,11 @@ dialogs: featureRestriction: title: 演示版 - desc: 你尝试使用了 功能。该功能在演示版中不可用。请考虑购买独立版以获得更好的体验。 + desc: 你尝试使用了功能。该功能在演示版中不可用。请考虑购买独立版以获得更好的体验。 oneSavegameLimit: title: 存档数量限制 - desc: 演示版中只能保存一份存档。 请删除旧存档或者获取独立版! + desc: 演示版中只能保存一份存档。请删除旧存档或者获取独立版! updateSummary: title: 更新啦! @@ -298,8 +300,8 @@ dialogs: 你将要导出你的工厂的截图。如果你的基地很大,截图过程将会很慢,且有可能导致游戏崩溃! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + title: 确认剪切 + desc: 你没有足够的图形来粘贴这个区域!你确定要剪切吗? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -312,7 +314,7 @@ ingame: placeMultiple: 放置多个 reverseOrientation: 反向放置 disableAutoOrientation: 关闭自动定向 - toggleHud: 开关HUD + toggleHud: 开关 HUD placeBuilding: 放置建筑 createMarker: 创建地图标记 delete: 销毁 @@ -330,7 +332,7 @@ ingame: buildingPlacement: # Buildings can have different variants which are unlocked at later levels, # and this is the hint shown when there are multiple variants available. - cycleBuildingVariants: 按键以选择建筑变体. + cycleBuildingVariants: 按 键以选择建筑变体. # Shows the hotkey in the ui, e.g. "Hotkey: Q" hotkeyLabel: >- @@ -389,7 +391,7 @@ ingame: noShapesProduced: 你还没有生产任何图形。 # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: 个/分钟 + shapesPerMinute: 个 / 分钟 # Settings menu, when you press "ESC" settingsMenu: @@ -417,7 +419,7 @@ ingame: waypoints: waypoints: 地图标记 hub: 基地 - description: 左键跳转到地图标记,右键删除地图标记。

在当前地点创建地图标记,或者在选定位置上右键创建地图标记. + description: 左键跳转到地图标记,右键删除地图标记。

在当前地点创建地图标记,或者在选定位置上右键创建地图标记. creationSuccessNotification: 成功创建地图标记。 # Interactive tutorial @@ -430,7 +432,7 @@ ingame: 1_3_expand: >- 这不是一个挂机游戏!建造更多的开采机和传送带来更快地完成目标。

- 提示:按住SHIFT键来放置多个开采机,用R键旋转它们。 + 提示:按住 SHIFT 键来放置多个开采机,用 R 键旋转它们。 colors: red: 红色 @@ -441,11 +443,11 @@ ingame: cyan: 青色 white: 白色 uncolored: 无色 - black: Black + black: 黑色 shapeViewer: title: 层 # TODO: find better translation empty: 空 - copyKey: Copy Key + copyKey: 复制短代码 # All shop upgrades shopUpgrades: @@ -503,10 +505,10 @@ buildings: cutter: default: name: &cutter 切割机 - description: 将图形从上到下切开并输出。 如果你只需要其中一半,记得把另一半销毁掉,否则切割机会停止工作! + description: 将图形从上到下切开并输出。如果你只需要其中一半,记得把另一半销毁掉,否则切割机会停止工作! quad: name: 切割机(四向) - description: 将输入的图形切成四块。 如果你只需要其中一块,记得把其他的销毁掉,否则切割机会停止工作! + description: 将输入的图形切成四块。如果你只需要其中一块,记得把其他的销毁掉,否则切割机会停止工作! rotater: default: @@ -515,6 +517,9 @@ buildings: ccw: name: 旋转机(逆时针) description: 将图形逆时针旋转90度。 + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -524,7 +529,7 @@ buildings: mixer: default: name: &mixer 混色机 - description: 将两个颜色混合在一起。(加法混合) + description: 用加法混色将两个颜色混合起来 painter: default: @@ -587,11 +592,11 @@ storyRewards: reward_painter: title: 上色 desc: >- - The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, there is a color blind mode in the settings! + 恭喜!你解锁了上色机。开采一些颜色 (就像你开采图形一样) 将其在上色机中与图形结合来将图形上色!

PS:如果你患有色盲,可以在设置中启用色盲模式! reward_mixer: title: 混合颜色 - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! + desc: 恭喜!你解锁了混色机。这个建筑使用加法混色将两种颜色混合起来。 reward_stacker: title: 堆叠 @@ -607,11 +612,11 @@ storyRewards: reward_rotater_ccw: title: 逆时针旋转 - desc: 恭喜!你解锁了旋转机逆时针变体。这个变体可以逆时针旋转图形。选择旋转机然后按“T”键来选取这个变体。 + desc: 恭喜!你解锁了旋转机逆时针变体。这个变体可以逆时针旋转图形。选择旋转机然后按"T"键来选取这个变体。 reward_miner_chainable: title: 链式开采机 - desc: You have unlocked the chaining extractor! It can forward its resources to other extractors so you can more efficiently extract resources! + desc: 你解锁了链式开采机! 它能够把资源传递给其他开采机,让你可以更高效率的开采资源! reward_underground_belt_tier_2: title: 二级隧道 @@ -619,7 +624,7 @@ storyRewards: reward_splitter_compact: title: 小型合流机 - desc: You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one! + desc: 恭喜!你解锁了平衡机的变体。它能够接受两个输入,合并成一个输出! reward_cutter_quad: title: 四向切割机 @@ -635,7 +640,7 @@ storyRewards: reward_storage: title: 仓库 - desc: You have unlocked a variant of the trash - It allows to store items up to a given capacity! + desc: 恭喜!你解锁了垃圾桶的变体。他可以存储一定数量的物品! reward_freeplay: title: 自由模式 @@ -643,13 +648,13 @@ storyRewards: reward_blueprints: title: 蓝图 - desc: 你现在可以复制粘贴你的工厂的一部分了!按住CTRL键并拖动鼠标来选择一块区域,然后按C键复制。

粘贴并不是免费的,你需要使用蓝图图形来粘贴你的蓝图。蓝图图形是你刚刚交付的图形。 + desc: 你现在可以复制粘贴你的工厂的一部分了!按住 CTRL 键并拖动鼠标来选择一块区域,然后按C键复制。

粘贴并不是免费的,你需要使用蓝图图形来粘贴你的蓝图。蓝图图形是你刚刚交付的图形。 # Special reward, which is shown when there is no reward actually no_reward: title: 下一关 desc: >- - 这一关没有奖励,但是下一关有!

PS: 你生产过的所有图形都会被用来升级建筑。 + 这一关没有奖励,但是下一关有!

PS:你生产过的所有图形都会被用来升级建筑。 no_reward_freeplay: title: 下一关 @@ -659,8 +664,9 @@ storyRewards: settings: title: 设置 categories: - game: 游戏内容 - app: 应用 + general: 通用 + userInterface: 用户界面 + advanced: 高级 versionBadges: dev: 开发版本 # Development @@ -723,21 +729,21 @@ settings: refreshRate: title: 模拟频率、刷新频率 description: >- - 如果你的显示器是144hz的,请在这里更改刷新频率,这样游戏可以正确地根据你的屏幕进行模拟。但是如果你的电脑性能不佳,提高刷新频率可能降低帧数。 + 如果你的显示器是 144Hz 的,请在这里更改刷新频率,这样游戏可以正确地根据你的屏幕进行模拟。但是如果你的电脑性能不佳,提高刷新频率可能降低帧数。 # description: >- # If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. alwaysMultiplace: title: 多重放置 description: >- - 开启这个选项之后放下建筑将不会取消建筑选择。等同于一直按下SHIFT键。 + 开启这个选项之后放下建筑将不会取消建筑选择。等同于一直按下 SHIFT 键。 # description: >- # If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. offerHints: title: 提示与教程 description: >- - 是否显示提示、教程以及一些其他的帮助理解游戏的UI元素。 + 是否显示提示、教程以及一些其他的帮助理解游戏的 UI 元素。 # description: >- # Whether to offer hints and tutorials while playing. Also hides certain UI elements onto a given level to make it easier to get into the game. @@ -786,16 +792,14 @@ settings: title: 色盲模式 description: 提供一些分辨颜色的工具。目前当鼠标移至颜色资源上方时,屏幕上方会显示颜色名称。 rotationByBuilding: - title: Rotation by building type + title: 记忆建筑方向 description: >- - Each building type remembers the rotation you last set it to individually. - This may be more comfortable if you frequently switch between placing - different building types. + 每一类建筑都会记住各自上一次的旋转方向。如果你经常在不同建筑类型之间切换,这个设置会让游戏更加舒适。 keybindings: title: 按键设置 hint: >- - 提示:使用CTRL、SHIFT、ALT! 这些建在放置建筑时有不同的效果。 + 提示:使用 CTRL、SHIFT、ALT!这些建在放置建筑时有不同的效果。 # hint: >- # Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. @@ -877,20 +881,20 @@ about: title: 关于游戏 # title: About this Game body: >- - 本游戏由Tobias Springer(我)开发,并且已经开源。

- 如果你想参与开发,请查看shapez.io on github

- 这个游戏的开发少不了热情的Discord社区。请加入我们的Discord 服务器

- 本游戏的音乐由Peppsen制作——他是个很棒的伙伴。

+ 本游戏的音乐由 Peppsen 制作——他是个很棒的伙伴。

- 最后,我想感谢我最好的朋友Niklas——如果没有与他的异星工厂(factorio)的游戏体验,shapez.io将不会存在。 + 最后,我想感谢我最好的朋友 Niklas ——如果没有与他的异星工厂(factorio)的游戏体验,shapez.io将不会存在。 changelog: title: 版本日志 diff --git a/translations/base-zh-TW.yaml b/translations/base-zh-TW.yaml index eb8181bf..65aef6fa 100644 --- a/translations/base-zh-TW.yaml +++ b/translations/base-zh-TW.yaml @@ -15,7 +15,7 @@ # # Adding a new language: # -# If you want to add a new language, ask me in the discord and I will setup +# If you want to add a new language, ask me in the Discord and I will setup # the basic structure so the game also detects it. # @@ -45,6 +45,7 @@ # Painter:上色機 # Trash:垃圾桶 +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io 是一款在一個無邊際的地圖上建造工廠、自動化生產與組合愈加複雜圖形的遊戲。 @@ -56,50 +57,50 @@ steamPage: # - Please keep the markup (Stuff like [b], [list] etc) in the same format longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] + shapez.io 是一款在一個無邊無際的地圖上建造工廠、將生產與組合愈加複雜圖形自動化的遊戲。 - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + 在指定圖形送達基地後,你會晉級且解鎖能加速生產的新功能。 - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + 當指定圖形的數量增加時,你必須擴充你的工廠才能應付訂單 -- 但別忘記資源,你需要在[b]無邊無際的地圖[/b]上擴充。 - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + 不久後你將需要混色並為圖形上色 -- 混和紅、綠、藍以創造新顏色再將圖形上色來達成目標。 - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + 遊戲目前有十八關(應該也夠你忙一陣子了),而我還有很多計畫,持續更新中! - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + 購買獨立版的你即擁有額外內容,也會優先接觸新開發內容。 - [b]Standalone Advantages[/b] + [b]獨立版的額外內容[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] 深色主題 + [*] 地圖標記數量無限制 + [*] 存檔數量無限制 + [*] 更多設定 + [*] 即將到來: 電線與能源! 目標在2020年七月底(左右)問世。 + [*] 即將到來: 更多新關卡 + [*] 幫助我繼續開發 shapez.io ❤️ [/list] - [b]Future Updates[/b] + [b]未來更新[/b] - I am updating the game very often and trying to push an update at least every week! + 我時常更新遊戲,希望能周更! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] 不同的地圖與挑戰(像是有障礙物的地圖) + [*] 迷宮(在地圖受限制或只能使用特定建築的情況下送達圖形) + [*] 一個蓋建築物需要成本的故事模式 + [*] 可調控的地圖生成器(資源/圖形/密度可調整、隨機生成種子等等) + [*] 更多圖形種類 + [*] 遊戲效能提升(即使目前已經不錯了) + [*] 還有更多更多! [/list] - [b]This game is open source![/b] + [b]這個遊戲是開源的![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + 任何人都可以貢獻,我在社群裡很活耀、嘗試回復所有的建議並盡量參考大家的意見。 + 欲知詳情,別忘了造訪我的 Trello 喔! - [b]Links[/b] + [b]連結[/b] [list] [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] @@ -118,6 +119,9 @@ global: # How big numbers are rendered, e.g. "10,000" thousandsDivider: " " + # What symbol to use to seperate the integer part from the fractional part of a number, e.g. "0.4" + decimalSeparator: "." + # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: 千 @@ -175,7 +179,6 @@ mainMenu: savegameLevel: Level savegameLevelUnknown: 未知關卡 - continue: 繼續 newGame: 新遊戲 madeBy: 作者: @@ -510,6 +513,9 @@ buildings: ccw: name: 旋轉機(逆時針) description: 將圖形逆時針旋轉90度。 + fl: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: @@ -655,8 +661,9 @@ storyRewards: settings: title: 設置 categories: - game: 遊戲內容 - app: 應用 + general: General + userInterface: User Interface + advanced: Advanced versionBadges: dev: 開發版本 # Development diff --git a/yarn.lock b/yarn.lock index b00004a0..7fd22674 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,9895 +1,8638 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" - integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== - dependencies: - "@babel/highlight" "^7.8.3" - -"@babel/compat-data@^7.8.6", "@babel/compat-data@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.0.tgz#04815556fc90b0c174abd2c0c1bb966faa036a6c" - integrity sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g== - dependencies: - browserslist "^4.9.1" - invariant "^2.2.4" - semver "^5.5.0" - -"@babel/core@^7.5.4": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" - integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.0" - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helpers" "^7.9.0" - "@babel/parser" "^7.9.0" - "@babel/template" "^7.8.6" - "@babel/traverse" "^7.9.0" - "@babel/types" "^7.9.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.13" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/generator@^7.9.0", "@babel/generator@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9" - integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ== - dependencies: - "@babel/types" "^7.9.5" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - -"@babel/helper-annotate-as-pure@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" - integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz#c84097a427a061ac56a1c30ebf54b7b22d241503" - integrity sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-compilation-targets@^7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz#dac1eea159c0e4bd46e309b5a1b04a66b53c1dde" - integrity sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw== - dependencies: - "@babel/compat-data" "^7.8.6" - browserslist "^4.9.1" - invariant "^2.2.4" - levenary "^1.1.1" - semver "^5.5.0" - -"@babel/helper-create-regexp-features-plugin@^7.8.3", "@babel/helper-create-regexp-features-plugin@^7.8.8": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" - integrity sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-regex" "^7.8.3" - regexpu-core "^4.7.0" - -"@babel/helper-define-map@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" - integrity sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/types" "^7.8.3" - lodash "^4.17.13" - -"@babel/helper-explode-assignable-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" - integrity sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw== - dependencies: - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-function-name@^7.8.3", "@babel/helper-function-name@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" - integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw== - dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/types" "^7.9.5" - -"@babel/helper-get-function-arity@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" - integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-hoist-variables@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" - integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-member-expression-to-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" - integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-module-imports@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" - integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-module-transforms@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5" - integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA== - dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-simple-access" "^7.8.3" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/template" "^7.8.6" - "@babel/types" "^7.9.0" - lodash "^4.17.13" - -"@babel/helper-optimise-call-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" - integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" - integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== - -"@babel/helper-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" - integrity sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ== - dependencies: - lodash "^4.17.13" - -"@babel/helper-remap-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" - integrity sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-wrap-function" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-replace-supers@^7.8.3", "@babel/helper-replace-supers@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8" - integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.8.3" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/traverse" "^7.8.6" - "@babel/types" "^7.8.6" - -"@babel/helper-simple-access@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" - integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== - dependencies: - "@babel/template" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-split-export-declaration@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" - integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-validator-identifier@^7.9.0", "@babel/helper-validator-identifier@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" - integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== - -"@babel/helper-wrap-function@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" - integrity sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helpers@^7.9.0": - version "7.9.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f" - integrity sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA== - dependencies: - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.9.0" - "@babel/types" "^7.9.0" - -"@babel/highlight@^7.8.3": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" - integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ== - dependencies: - "@babel/helper-validator-identifier" "^7.9.0" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.8.6", "@babel/parser@^7.9.0": - version "7.9.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" - integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== - -"@babel/plugin-proposal-async-generator-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" - integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" - "@babel/plugin-syntax-async-generators" "^7.8.0" - -"@babel/plugin-proposal-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" - integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - -"@babel/plugin-proposal-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" - integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.0" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" - integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - -"@babel/plugin-proposal-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" - integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - -"@babel/plugin-proposal-object-rest-spread@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz#3fd65911306d8746014ec0d0cf78f0e39a149116" - integrity sha512-VP2oXvAf7KCYTthbUHwBlewbl1Iq059f6seJGsxMizaCdgHIeczOr7FBqELhSqfkIl04Fi8okzWzl63UKbQmmg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.9.5" - -"@babel/plugin-proposal-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" - integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - -"@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" - integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - -"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" - integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.8" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-async-generators@^7.8.0": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-dynamic-import@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-json-strings@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" - integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-object-rest-spread@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" - integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-arrow-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" - integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" - integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== - dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" - -"@babel/plugin-transform-block-scoped-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" - integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-block-scoping@^7.4.4", "@babel/plugin-transform-block-scoping@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" - integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - lodash "^4.17.13" - -"@babel/plugin-transform-classes@^7.5.5", "@babel/plugin-transform-classes@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz#800597ddb8aefc2c293ed27459c1fcc935a26c2c" - integrity sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-define-map" "^7.8.3" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-split-export-declaration" "^7.8.3" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" - integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-destructuring@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz#72c97cf5f38604aea3abf3b935b0e17b1db76a50" - integrity sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" - integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-duplicate-keys@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" - integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-exponentiation-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" - integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-for-of@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" - integrity sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-function-name@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" - integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" - integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-member-expression-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" - integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-modules-amd@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz#19755ee721912cf5bb04c07d50280af3484efef4" - integrity sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q== - dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-commonjs@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz#e3e72f4cbc9b4a260e30be0ea59bdf5a39748940" - integrity sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g== - dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-simple-access" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-systemjs@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz#e9fd46a296fc91e009b64e07ddaa86d6f0edeb90" - integrity sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ== - dependencies: - "@babel/helper-hoist-variables" "^7.8.3" - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-umd@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" - integrity sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ== - dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" - integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - -"@babel/plugin-transform-new-target@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" - integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-object-super@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" - integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.3" - -"@babel/plugin-transform-parameters@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795" - integrity sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA== - dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-property-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" - integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-regenerator@^7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8" - integrity sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA== - dependencies: - regenerator-transform "^0.14.2" - -"@babel/plugin-transform-reserved-words@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" - integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-shorthand-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" - integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" - integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-sticky-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" - integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-regex" "^7.8.3" - -"@babel/plugin-transform-template-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" - integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-typeof-symbol@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" - integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-unicode-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" - integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/preset-env@^7.5.4": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.5.tgz#8ddc76039bc45b774b19e2fc548f6807d8a8919f" - integrity sha512-eWGYeADTlPJH+wq1F0wNfPbVS1w1wtmMJiYk55Td5Yu28AsdR9AsC97sZ0Qq8fHqQuslVSIYSGJMcblr345GfQ== - dependencies: - "@babel/compat-data" "^7.9.0" - "@babel/helper-compilation-targets" "^7.8.7" - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-proposal-async-generator-functions" "^7.8.3" - "@babel/plugin-proposal-dynamic-import" "^7.8.3" - "@babel/plugin-proposal-json-strings" "^7.8.3" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-proposal-numeric-separator" "^7.8.3" - "@babel/plugin-proposal-object-rest-spread" "^7.9.5" - "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" - "@babel/plugin-proposal-optional-chaining" "^7.9.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" - "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-json-strings" "^7.8.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.8.0" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - "@babel/plugin-transform-arrow-functions" "^7.8.3" - "@babel/plugin-transform-async-to-generator" "^7.8.3" - "@babel/plugin-transform-block-scoped-functions" "^7.8.3" - "@babel/plugin-transform-block-scoping" "^7.8.3" - "@babel/plugin-transform-classes" "^7.9.5" - "@babel/plugin-transform-computed-properties" "^7.8.3" - "@babel/plugin-transform-destructuring" "^7.9.5" - "@babel/plugin-transform-dotall-regex" "^7.8.3" - "@babel/plugin-transform-duplicate-keys" "^7.8.3" - "@babel/plugin-transform-exponentiation-operator" "^7.8.3" - "@babel/plugin-transform-for-of" "^7.9.0" - "@babel/plugin-transform-function-name" "^7.8.3" - "@babel/plugin-transform-literals" "^7.8.3" - "@babel/plugin-transform-member-expression-literals" "^7.8.3" - "@babel/plugin-transform-modules-amd" "^7.9.0" - "@babel/plugin-transform-modules-commonjs" "^7.9.0" - "@babel/plugin-transform-modules-systemjs" "^7.9.0" - "@babel/plugin-transform-modules-umd" "^7.9.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" - "@babel/plugin-transform-new-target" "^7.8.3" - "@babel/plugin-transform-object-super" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.9.5" - "@babel/plugin-transform-property-literals" "^7.8.3" - "@babel/plugin-transform-regenerator" "^7.8.7" - "@babel/plugin-transform-reserved-words" "^7.8.3" - "@babel/plugin-transform-shorthand-properties" "^7.8.3" - "@babel/plugin-transform-spread" "^7.8.3" - "@babel/plugin-transform-sticky-regex" "^7.8.3" - "@babel/plugin-transform-template-literals" "^7.8.3" - "@babel/plugin-transform-typeof-symbol" "^7.8.4" - "@babel/plugin-transform-unicode-regex" "^7.8.3" - "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.9.5" - browserslist "^4.9.1" - core-js-compat "^3.6.2" - invariant "^2.2.2" - levenary "^1.1.1" - semver "^5.5.0" - -"@babel/preset-modules@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" - integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/runtime@7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0-beta.42.tgz#352e40c92e0460d3e82f49bd7e79f6cda76f919f" - integrity sha512-iOGRzUoONLOtmCvjUsZv3mZzgCT6ljHQY5fr1qG1QIiJQwtM7zbPWGGpa3QWETq+UqwWyJnoi5XZDZRwZDFciQ== - dependencies: - core-js "^2.5.3" - regenerator-runtime "^0.11.1" - -"@babel/runtime@^7.8.4": - version "7.9.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" - integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.8.3", "@babel/template@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" - integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/parser" "^7.8.6" - "@babel/types" "^7.8.6" - -"@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2" - integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.5" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.9.0" - "@babel/types" "^7.9.5" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444" - integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg== - dependencies: - "@babel/helper-validator-identifier" "^7.9.5" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@csstools/convert-colors@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" - integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== - -"@jimp/bmp@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/bmp/-/bmp-0.6.8.tgz#8abbfd9e26ba17a47fab311059ea9f7dd82005b6" - integrity sha512-uxVgSkI62uAzk5ZazYHEHBehow590WAkLKmDXLzkr/XP/Hv2Fx1T4DKwJ/15IY5ktq5VAhAUWGXTyd8KWFsx7w== - dependencies: - "@jimp/utils" "^0.6.8" - bmp-js "^0.1.0" - core-js "^2.5.7" - -"@jimp/core@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/core/-/core-0.6.8.tgz#6a41089792516f6e64a5302d12eb562aa7847c7b" - integrity sha512-JOFqBBcSNiDiMZJFr6OJqC6viXj5NVBQISua0eacoYvo4YJtTajOIxC4MqWyUmGrDpRMZBR8QhSsIOwsFrdROA== - dependencies: - "@jimp/utils" "^0.6.8" - any-base "^1.1.0" - buffer "^5.2.0" - core-js "^2.5.7" - 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@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/custom/-/custom-0.6.8.tgz#0476d7b3f5da3121d98895a2e14f2899e602f2b6" - integrity sha512-FrYlzZRVXP2vuVwd7Nc2dlK+iZk4g6IaT1Ib8Z6vU5Kkwlt83FJIPJ2UUFABf3bF5big0wkk8ZUihWxE4Nzdng== - dependencies: - "@jimp/core" "^0.6.8" - core-js "^2.5.7" - -"@jimp/gif@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/gif/-/gif-0.6.8.tgz#848dd4e6e1a56ca2b3ce528969e44dfa99a53b14" - integrity sha512-yyOlujjQcgz9zkjM5ihZDEppn9d1brJ7jQHP5rAKmqep0G7FU1D0AKcV+Ql18RhuI/CgWs10wAVcrQpmLnu4Yw== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - omggif "^1.0.9" - -"@jimp/jpeg@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/jpeg/-/jpeg-0.6.8.tgz#4cad85a6d1e15759acb56bddef29aa3473859f2c" - integrity sha512-rGtXbYpFXAn471qLpTGvhbBMNHJo5KiufN+vC5AWyufntmkt5f0Ox2Cx4ijuBMDtirZchxbMLtrfGjznS4L/ew== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - jpeg-js "^0.3.4" - -"@jimp/plugin-blit@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-blit/-/plugin-blit-0.6.8.tgz#646ebb631f35afc28c1e8908524bc43d1e9afa3d" - integrity sha512-7Tl6YpKTSpvwQbnGNhsfX2zyl3jRVVopd276Y2hF2zpDz9Bycow7NdfNU/4Nx1jaf96X6uWOtSVINcQ7rGd47w== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-blur@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-blur/-/plugin-blur-0.6.8.tgz#7b753ae94f6099103f57c268c3b2679047eefe95" - integrity sha512-NpZCMKxXHLDQsX9zPlWtpMA660DQStY6/z8ZetyxCDbqrLe9YCXpeR4MNhdJdABIiwTm1W5FyFF4kp81PHJx3Q== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-color@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-color/-/plugin-color-0.6.8.tgz#4101cb1208879b331db6e43ea6b96eaf8dbaedbc" - integrity sha512-jjFyU0zNmGOH2rjzHuOMU4kaia0oo82s/7UYfn5h7OUkmUZTd6Do3ZSK1PiXA7KR+s4B76/Omm6Doh/0SGb7BQ== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - tinycolor2 "^1.4.1" - -"@jimp/plugin-contain@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-contain/-/plugin-contain-0.6.8.tgz#af95d33b63d0478943374ae15dd2607fc69cad14" - integrity sha512-p/P2wCXhAzbmEgXvGsvmxLmbz45feF6VpR4m9suPSOr8PC/i/XvTklTqYEUidYYAft4vHgsYJdS74HKSMnH8lw== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-cover@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-cover/-/plugin-cover-0.6.8.tgz#490e3186627a34d93cc015c4169bac9070d6ad17" - integrity sha512-2PvWgk+PJfRsfWDI1G8Fpjrsu0ZlpNyZxO2+fqWlVo6y/y2gP4v08FqvbkcqSjNlOu2IDWIFXpgyU0sTINWZLg== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-crop@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-crop/-/plugin-crop-0.6.8.tgz#ffec8951a2f3eccad1e3cff9afff5326bd980ce7" - integrity sha512-CbrcpWE2xxPK1n/JoTXzhRUhP4mO07mTWaSavenCg664oQl/9XCtL+A0FekuNHzIvn4myEqvkiTwN7FsbunS/Q== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-displace@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-displace/-/plugin-displace-0.6.8.tgz#89df05ab7daaff6befc190bb8ac54ec8d57e533b" - integrity sha512-RmV2bPxoPE6mrPxtYSPtHxm2cGwBQr5a2p+9gH6SPy+eUMrbGjbvjwKNfXWUYD0leML+Pt5XOmAS9pIROmuruQ== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-dither@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-dither/-/plugin-dither-0.6.8.tgz#17e5b9f56575a871e329fef8b388e614b92d84f8" - integrity sha512-x6V/qjxe+xypjpQm7GbiMNqci1EW5UizrcebOhHr8AHijOEqHd2hjXh5f6QIGfrkTFelc4/jzq1UyCsYntqz9Q== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-flip@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-flip/-/plugin-flip-0.6.8.tgz#153df0c677f79d4078bb9e4c1f2ac392b96dc3a1" - integrity sha512-4il6Da6G39s9MyWBEee4jztEOUGJ40E6OlPjkMrdpDNvge6hYEAB31BczTYBP/CEY74j4LDSoY5LbcU4kv06yA== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-gaussian@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-gaussian/-/plugin-gaussian-0.6.8.tgz#100abc7ae1f19fe9c09ed41625b475aae7c6093c" - integrity sha512-pVOblmjv7stZjsqloi4YzHVwAPXKGdNaHPhp4KP4vj41qtc6Hxd9z/+VWGYRTunMFac84gUToe0UKIXd6GhoKw== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-invert@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-invert/-/plugin-invert-0.6.8.tgz#f40bfaa3b592d21ff14ede0e49aabec88048cad0" - integrity sha512-11zuLiXDHr6tFv4U8aieXqNXQEKbDbSBG/h+X62gGTNFpyn8EVPpncHhOqrAFtZUaPibBqMFlNJ15SzwC7ExsQ== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-mask@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-mask/-/plugin-mask-0.6.8.tgz#e64405f7dacf0672bff74f3b95b724d9ac517f86" - integrity sha512-hZJ0OiKGJyv7hDSATwJDkunB1Ie80xJnONMgpUuUseteK45YeYNBOiZVUe8vum8QI1UwavgBzcvQ9u4fcgXc9g== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-normalize@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-normalize/-/plugin-normalize-0.6.8.tgz#a0180f2b8835e3638cdc5e057b44ac63f60db6ba" - integrity sha512-Q4oYhU+sSyTJI7pMZlg9/mYh68ujLfOxXzQGEXuw0sHGoGQs3B0Jw7jmzGa6pIS06Hup5hD2Zuh1ppvMdjJBfQ== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-print@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-print/-/plugin-print-0.6.8.tgz#66309549e01896473111e3a0ad2cee428638bd6e" - integrity sha512-2aokejGn4Drv1FesnZGqh5KEq0FQtR0drlmtyZrBH+r9cx7hh0Qgf4D1BOTDEgXkfSSngjGRjKKRW/fwOrVXYw== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - load-bmfont "^1.4.0" - -"@jimp/plugin-resize@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-resize/-/plugin-resize-0.6.8.tgz#c26d9a973f7eec51ad9018fcbbac1146f7a73aa0" - integrity sha512-27nPh8L1YWsxtfmV/+Ub5dOTpXyC0HMF2cu52RQSCYxr+Lm1+23dJF70AF1poUbUe+FWXphwuUxQzjBJza9UoA== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-rotate@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-rotate/-/plugin-rotate-0.6.8.tgz#2afda247984eeebed95c1bb1b13ccd3be5973299" - integrity sha512-GbjETvL05BDoLdszNUV4Y0yLkHf177MnqGqilA113LIvx9aD0FtUopGXYfRGVvmtTOTouoaGJUc+K6qngvKxww== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugin-scale@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-scale/-/plugin-scale-0.6.8.tgz#5de403345859bb0b30bf3e242dedd8ceb6ecb96c" - integrity sha512-GzIYWR/oCUK2jAwku23zt19V1ssaEU4pL0x2XsLNKuuJEU6DvEytJyTMXCE7OLG/MpDBQcQclJKHgiyQm5gIOQ== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - -"@jimp/plugins@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/plugins/-/plugins-0.6.8.tgz#5618170a986ced1ea795adcd9376122f2543b856" - integrity sha512-fMcTI72Vn/Lz6JftezTURmyP5ml/xGMe0Ljx2KRJ85IWyP33vDmGIUuutFiBEbh2+y7lRT+aTSmjs0QGa/xTmQ== - dependencies: - "@jimp/plugin-blit" "^0.6.8" - "@jimp/plugin-blur" "^0.6.8" - "@jimp/plugin-color" "^0.6.8" - "@jimp/plugin-contain" "^0.6.8" - "@jimp/plugin-cover" "^0.6.8" - "@jimp/plugin-crop" "^0.6.8" - "@jimp/plugin-displace" "^0.6.8" - "@jimp/plugin-dither" "^0.6.8" - "@jimp/plugin-flip" "^0.6.8" - "@jimp/plugin-gaussian" "^0.6.8" - "@jimp/plugin-invert" "^0.6.8" - "@jimp/plugin-mask" "^0.6.8" - "@jimp/plugin-normalize" "^0.6.8" - "@jimp/plugin-print" "^0.6.8" - "@jimp/plugin-resize" "^0.6.8" - "@jimp/plugin-rotate" "^0.6.8" - "@jimp/plugin-scale" "^0.6.8" - core-js "^2.5.7" - timm "^1.6.1" - -"@jimp/png@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/png/-/png-0.6.8.tgz#ee06cf078b381137ec7206c4bb1b4cfcbe15ca6f" - integrity sha512-JHHg/BZ7KDtHQrcG+a7fztw45rdf7okL/YwkN4qU5FH7Fcrp41nX5QnRviDtD9hN+GaNC7kvjvcqRAxW25qjew== - dependencies: - "@jimp/utils" "^0.6.8" - core-js "^2.5.7" - pngjs "^3.3.3" - -"@jimp/tiff@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/tiff/-/tiff-0.6.8.tgz#79bd22ed435edbe29d02a2c8c9bf829f988ebacc" - integrity sha512-iWHbxd+0IKWdJyJ0HhoJCGYmtjPBOusz1z1HT/DnpePs/Lo3TO4d9ALXqYfUkyG74ZK5jULZ69KLtwuhuJz1bg== - dependencies: - core-js "^2.5.7" - utif "^2.0.1" - -"@jimp/types@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/types/-/types-0.6.8.tgz#4510eb635cd00b201745d70e38f791748baa7075" - integrity sha512-vCZ/Cp2osy69VP21XOBACfHI5HeR60Rfd4Jidj4W73UL+HrFWOtyQiJ7hlToyu1vI5mR/NsUQpzyQvz56ADm5A== - dependencies: - "@jimp/bmp" "^0.6.8" - "@jimp/gif" "^0.6.8" - "@jimp/jpeg" "^0.6.8" - "@jimp/png" "^0.6.8" - "@jimp/tiff" "^0.6.8" - core-js "^2.5.7" - timm "^1.6.1" - -"@jimp/utils@^0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@jimp/utils/-/utils-0.6.8.tgz#09f794945631173567aa50f72ac28170de58a63d" - integrity sha512-7RDfxQ2C/rarNG9iso5vmnKQbcvlQjBIlF/p7/uYj72WeZgVCB+5t1fFBKJSU4WhniHX4jUMijK+wYGE3Y3bGw== - dependencies: - core-js "^2.5.7" - -"@sindresorhus/is@^0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" - integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== - -"@types/color-name@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" - integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== - -"@types/cordova@^0.0.34": - version "0.0.34" - resolved "https://registry.yarnpkg.com/@types/cordova/-/cordova-0.0.34.tgz#ea7addf74ecec3d7629827a0c39e2c9addc73d04" - integrity sha1-6nrd907Ow9dimCegw54smt3HPQQ= - -"@types/eslint-visitor-keys@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" - integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== - -"@types/filesystem@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/filesystem/-/filesystem-0.0.29.tgz#ee3748eb5be140dcf980c3bd35f11aec5f7a3748" - integrity sha512-85/1KfRedmfPGsbK8YzeaQUyV1FQAvMPMTuWFQ5EkLd2w7szhNO96bk3Rh/SKmOfd9co2rCLf0Voy4o7ECBOvw== - dependencies: - "@types/filewriter" "*" - -"@types/filewriter@*": - version "0.0.28" - resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.28.tgz#c054e8af4d9dd75db4e63abc76f885168714d4b3" - integrity sha1-wFTor02d11205jq8dviFFocU1LM= - -"@types/json-schema@^7.0.3": - version "7.0.4" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" - integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== - -"@types/q@^1.5.1": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" - integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== - -"@typescript-eslint/eslint-plugin@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.0.1.tgz#368fe7d4c3d927e9fd27b7ba150b4b7e83ddfabe" - integrity sha512-RxGldRQD3hgOK2xtBfNfA5MMV3rn5gVChe+MIf14hKm51jO2urqF64xOyVrGtzThkrd4rS1Kihqx2nkSxkXHvA== - dependencies: - "@typescript-eslint/experimental-utils" "3.0.1" - functional-red-black-tree "^1.0.1" - regexpp "^3.0.0" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/experimental-utils@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.0.1.tgz#e2721c970068fabd6621709234809c98cd3343ad" - integrity sha512-GdwOVz80MOWxbc/br1DC30eeqlxfpVzexHgHtf3L0hcbOu1xAs1wSCNcaBTLMOMZbh1gj/cKZt0eB207FxWfFA== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "3.0.1" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - -"@typescript-eslint/parser@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.0.1.tgz#f5163e3a789422f5c62f4daf822bfa03b7e4472d" - integrity sha512-Pn2tDmOc4Ri93VQnT70W0pqQr6i/pEZqIPXfWXm4RuiIprL0t6SG13ViVXHgfScknL2Fm2G4IqXhUzxSRCWXCw== - dependencies: - "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "3.0.1" - "@typescript-eslint/typescript-estree" "3.0.1" - eslint-visitor-keys "^1.1.0" - -"@typescript-eslint/typescript-estree@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.0.1.tgz#8c0cfb7cda64bd6f54185a7b7d1923d25d36b2a8" - integrity sha512-FrbMdgVCeIGHKaP9OYTttFTlF8Ds7AkjMca2GzYCE7pVch10PAJc1mmAFt+DfQPgu/2TrLAprg2vI0PK/WTdcg== - dependencies: - debug "^4.1.1" - eslint-visitor-keys "^1.1.0" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" - -"@webassemblyjs/ast@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" - integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== - dependencies: - "@webassemblyjs/helper-module-context" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/wast-parser" "1.9.0" - -"@webassemblyjs/floating-point-hex-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" - integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== - -"@webassemblyjs/helper-api-error@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" - integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== - -"@webassemblyjs/helper-buffer@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" - integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== - -"@webassemblyjs/helper-code-frame@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" - integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== - dependencies: - "@webassemblyjs/wast-printer" "1.9.0" - -"@webassemblyjs/helper-fsm@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" - integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== - -"@webassemblyjs/helper-module-context@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" - integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== - dependencies: - "@webassemblyjs/ast" "1.9.0" - -"@webassemblyjs/helper-wasm-bytecode@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" - integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== - -"@webassemblyjs/helper-wasm-section@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" - integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - -"@webassemblyjs/ieee754@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" - integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" - integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" - integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== - -"@webassemblyjs/wasm-edit@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" - integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/helper-wasm-section" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - "@webassemblyjs/wasm-opt" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - "@webassemblyjs/wast-printer" "1.9.0" - -"@webassemblyjs/wasm-gen@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" - integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/ieee754" "1.9.0" - "@webassemblyjs/leb128" "1.9.0" - "@webassemblyjs/utf8" "1.9.0" - -"@webassemblyjs/wasm-opt@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" - integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - -"@webassemblyjs/wasm-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" - integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-api-error" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/ieee754" "1.9.0" - "@webassemblyjs/leb128" "1.9.0" - "@webassemblyjs/utf8" "1.9.0" - -"@webassemblyjs/wast-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" - integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/floating-point-hex-parser" "1.9.0" - "@webassemblyjs/helper-api-error" "1.9.0" - "@webassemblyjs/helper-code-frame" "1.9.0" - "@webassemblyjs/helper-fsm" "1.9.0" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/wast-printer@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" - integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/wast-parser" "1.9.0" - "@xtuc/long" "4.2.2" - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -accepts@~1.3.4, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= - dependencies: - acorn "^3.0.4" - -acorn-jsx@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" - integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== - -acorn-walk@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.1.1.tgz#345f0dffad5c735e7373d2fec9a1023e6a44b83e" - integrity sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ== - -acorn@^3.0.4: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= - -acorn@^5.5.0: - version "5.7.4" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" - integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== - -acorn@^6.2.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" - integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== - -acorn@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" - integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== - -after@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" - integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= - -ajv-errors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" - integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== - -ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" - integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== - -ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.0: - version "6.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7" - integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^6.10.0: - version "6.12.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" - integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -alphanum-sort@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= - -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= - -ansi-colors@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" - integrity sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA== - dependencies: - ansi-wrap "^0.1.0" - -ansi-escapes@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" - integrity sha1-06ioOzGapneTZisT52HHkRQiMG4= - -ansi-escapes@^4.2.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" - integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== - dependencies: - type-fest "^0.11.0" - -ansi-gray@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" - integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= - dependencies: - ansi-wrap "0.1.0" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" - integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" - integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== - dependencies: - "@types/color-name" "^1.1.1" - color-convert "^2.0.1" - -ansi-wrap@0.1.0, ansi-wrap@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= - -any-base@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/any-base/-/any-base-1.1.0.tgz#ae101a62bc08a597b4c9ab5b7089d456630549fe" - integrity sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg== - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -aproba@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -arch@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e" - integrity sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg== - -archive-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/archive-type/-/archive-type-4.0.0.tgz#f92e72233056dfc6969472749c267bdb046b1d70" - integrity sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA= - dependencies: - file-type "^4.2.0" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= - -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - -arraybuffer.slice@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" - integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== - dependencies: - object-assign "^4.1.1" - util "0.10.3" - -assets@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/assets/-/assets-3.0.1.tgz#7a69f4bcc3aca9702760e2a73a7e76ca93e9e3e0" - integrity sha512-fTyLNf/9V24y5zO83f4DAEuvaKj7MWBixbnqdZneAhsv1r21yQ/6ogZfvXHmphJAHsz4DhuOwHeJKVbGqqvk0Q== - dependencies: - async "^2.5.0" - bluebird "^3.4.6" - calipers "^2.0.0" - calipers-gif "^2.0.0" - calipers-jpeg "^2.0.0" - calipers-png "^2.0.0" - calipers-svg "^2.0.0" - calipers-webp "^2.0.0" - glob "^7.0.6" - lodash "^4.15.0" - mime "^2.4.0" - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -ast-types@0.9.6: - version "0.9.6" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9" - integrity sha1-ECyenpAF0+fjgpvwxPok7oYu6bk= - -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -async-each-series@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/async-each-series/-/async-each-series-0.1.1.tgz#7617c1917401fd8ca4a28aadce3dbae98afeb432" - integrity sha1-dhfBkXQB/Yykooqtzj266Yr+tDI= - -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - -async@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= - -async@^2.5.0: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== - dependencies: - lodash "^4.17.14" - -async@~0.2.10: - version "0.2.10" - resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" - integrity sha1-trvgsGdLnXGXCMo43owjfLUmw9E= - -async@~2.1.4: - version "2.1.5" - resolved "https://registry.yarnpkg.com/async/-/async-2.1.5.tgz#e587c68580994ac67fc56ff86d3ac56bdbe810bc" - integrity sha1-5YfGhYCZSsZ/xW/4bTrFa9voELw= - dependencies: - lodash "^4.14.0" - -atob@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -autoprefixer@^9.4.3, autoprefixer@^9.4.7, autoprefixer@^9.6.1: - version "9.7.6" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.6.tgz#63ac5bbc0ce7934e6997207d5bb00d68fa8293a4" - integrity sha512-F7cYpbN7uVVhACZTeeIeealwdGM6wMtfWARVLTy5xmKtgVdBNJvbDRoCK3YO1orcs7gv/KwYlb3iXwu9Ug9BkQ== - dependencies: - browserslist "^4.11.1" - caniuse-lite "^1.0.30001039" - chalk "^2.4.2" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^7.0.27" - postcss-value-parser "^4.0.3" - -axios@0.19.0: - version "0.19.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8" - integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ== - dependencies: - follow-redirects "1.5.10" - is-buffer "^2.0.2" - -babel-loader@^8.0.4: - version "8.1.0" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" - integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw== - dependencies: - find-cache-dir "^2.1.0" - loader-utils "^1.4.0" - mkdirp "^0.5.3" - pify "^4.0.1" - schema-utils "^2.6.5" - -babel-plugin-closure-elimination@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-closure-elimination/-/babel-plugin-closure-elimination-1.3.0.tgz#3217fbf6d416dfdf14ff41a8a34e4d0a6bfc22b2" - integrity sha512-ClKuSxKLLNhe69bvTMuONDI0dQDW49lXB2qtQyyKCzvwegRGel/q4/e+1EoDNDN97Hf1QkxGMbzpAGPmU4Tfjw== - -babel-plugin-console-source@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/babel-plugin-console-source/-/babel-plugin-console-source-2.0.4.tgz#263985b1d69b68e463358d087fa877dd967c5f41" - integrity sha512-OGhrdhuMjiEW0Ma0P9e2B4dFddCpJ/xN/RRaM/4wwDLl+6ZKf+Xd77FtVjpNeDzNRNk8wjRdStA4hpZizXzl1g== - -babel-plugin-danger-remove-unused-import@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/babel-plugin-danger-remove-unused-import/-/babel-plugin-danger-remove-unused-import-1.1.2.tgz#ac39c30edfe524ef8cfc411fec5edc479d19e132" - integrity sha512-3bNmVAaakP3b1aROj7O3bOWj2kBa85sZR5naZ3Rn8L9buiZaAyZLgjfrPDL3zhX4wySOA5jrTm/wSmJPsMm3cg== - -babel-plugin-dynamic-import-node@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== - dependencies: - object.assign "^4.1.0" - -babel-polyfill@6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" - integrity sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0= - dependencies: - babel-runtime "^6.22.0" - core-js "^2.4.0" - regenerator-runtime "^0.10.0" - -babel-runtime@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-runtime@^7.0.0-beta.3: - version "7.0.0-beta.3" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-7.0.0-beta.3.tgz#7c750de5514452c27612172506b49085a4a630f2" - integrity sha512-jlzZ8RACjt0QGxq+wqsw5bCQE9RcUyWpw987mDY3GYxTpOQT2xoyNoG++oVCHzr/nACLBIprfVBNvv/If1ZYcg== - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -backo2@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" - integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -base64-arraybuffer@0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" - integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg= - -base64-js@^1.0.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" - integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== - -base64id@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" - integrity sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY= - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= - -better-assert@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" - integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI= - dependencies: - callsite "1.0.0" - -bfj@^6.1.1: - version "6.1.2" - resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.2.tgz#325c861a822bcb358a41c78a33b8e6e2086dde7f" - integrity sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw== - dependencies: - bluebird "^3.5.5" - check-types "^8.0.3" - hoopy "^0.1.4" - tryer "^1.0.1" - -big.js@^3.1.3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -bin-build@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bin-build/-/bin-build-3.0.0.tgz#c5780a25a8a9f966d8244217e6c1f5082a143861" - integrity sha512-jcUOof71/TNAI2uM5uoUaDq2ePcVBQ3R/qhxAz1rX7UfvduAL/RXD3jXzvn8cVcDJdGVkiR1shal3OH0ImpuhA== - dependencies: - decompress "^4.0.0" - download "^6.2.2" - execa "^0.7.0" - p-map-series "^1.0.0" - tempfile "^2.0.0" - -bin-check@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bin-check/-/bin-check-4.1.0.tgz#fc495970bdc88bb1d5a35fc17e65c4a149fc4a49" - integrity sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA== - dependencies: - execa "^0.7.0" - executable "^4.1.0" - -bin-version-check@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/bin-version-check/-/bin-version-check-4.0.0.tgz#7d819c62496991f80d893e6e02a3032361608f71" - integrity sha512-sR631OrhC+1f8Cvs8WyVWOA33Y8tgwjETNPyyD/myRBXLkfS/vl74FmH/lFcRl9KY3zwGh7jFhvyk9vV3/3ilQ== - dependencies: - bin-version "^3.0.0" - semver "^5.6.0" - semver-truncate "^1.1.2" - -bin-version@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bin-version/-/bin-version-3.1.0.tgz#5b09eb280752b1bd28f0c9db3f96f2f43b6c0839" - integrity sha512-Mkfm4iE1VFt4xd4vH+gx+0/71esbfus2LsnCGe8Pi4mndSPyT+NGES/Eg99jx8/lUGWfu3z2yuB/bt5UB+iVbQ== - dependencies: - execa "^1.0.0" - find-versions "^3.0.0" - -bin-wrapper@^4.0.0, bin-wrapper@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bin-wrapper/-/bin-wrapper-4.1.0.tgz#99348f2cf85031e3ef7efce7e5300aeaae960605" - integrity sha512-hfRmo7hWIXPkbpi0ZltboCMVrU+0ClXR/JgbCKKjlDjQf6igXa7OwdqNcFWQZPZTgiY7ZpzE3+LjjkLiTN2T7Q== - dependencies: - bin-check "^4.1.0" - bin-version-check "^4.0.0" - download "^7.1.0" - import-lazy "^3.1.0" - os-filter-obj "^2.0.0" - pify "^4.0.1" - -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - -bl@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== - dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" - -blob@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683" - integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== - -bluebird@3.x.x, bluebird@^3.4.6, bluebird@^3.5.0, bluebird@^3.5.5: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -bmp-js@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.1.0.tgz#e05a63f796a6c1ff25f4771ec7adadc148c07233" - integrity sha1-4Fpj95amwf8l9Hcex62twUjAcjM= - -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== - -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" - -boolbase@^1.0.0, boolbase@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -brorand@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -browser-sync-client@^2.26.6: - version "2.26.6" - resolved "https://registry.yarnpkg.com/browser-sync-client/-/browser-sync-client-2.26.6.tgz#e5201d3ace8aee88af17656b7b0c0620b6f8e4ab" - integrity sha512-mGrkZdNzttKdf/16I+y+2dTQxoMCIpKbVIMJ/uP8ZpnKu9f9qa/2CYVtLtbjZG8nsM14EwiCrjuFTGBEnT3Gjw== - dependencies: - etag "1.8.1" - fresh "0.5.2" - mitt "^1.1.3" - rxjs "^5.5.6" - -browser-sync-ui@^2.26.4: - version "2.26.4" - resolved "https://registry.yarnpkg.com/browser-sync-ui/-/browser-sync-ui-2.26.4.tgz#3772f13c6b93f2d7d333f4be0ca1ec02aae97dba" - integrity sha512-u20P3EsZoM8Pt+puoi3BU3KlbQAH1lAcV+/O4saF26qokrBqIDotmGonfWwoRbUmdxZkM9MBmA0K39ZTG1h4sA== - dependencies: - async-each-series "0.1.1" - connect-history-api-fallback "^1" - immutable "^3" - server-destroy "1.0.1" - socket.io-client "^2.0.4" - stream-throttle "^0.1.3" - -browser-sync@^2.24.6: - version "2.26.7" - resolved "https://registry.yarnpkg.com/browser-sync/-/browser-sync-2.26.7.tgz#120287716eb405651a76cc74fe851c31350557f9" - integrity sha512-lY3emme0OyvA2ujEMpRmyRy9LY6gHLuTr2/ABxhIm3lADOiRXzP4dgekvnDrQqZ/Ec2Fz19lEjm6kglSG5766w== - dependencies: - browser-sync-client "^2.26.6" - browser-sync-ui "^2.26.4" - bs-recipes "1.3.4" - bs-snippet-injector "^2.0.1" - chokidar "^2.0.4" - connect "3.6.6" - connect-history-api-fallback "^1" - dev-ip "^1.0.1" - easy-extender "^2.3.4" - eazy-logger "^3" - etag "^1.8.1" - fresh "^0.5.2" - fs-extra "3.0.1" - http-proxy "1.15.2" - immutable "^3" - localtunnel "1.9.2" - micromatch "^3.1.10" - opn "5.3.0" - portscanner "2.1.1" - qs "6.2.3" - raw-body "^2.3.2" - resp-modifier "6.0.2" - rx "4.1.0" - send "0.16.2" - serve-index "1.9.1" - serve-static "1.13.2" - server-destroy "1.0.1" - socket.io "2.1.1" - ua-parser-js "0.7.17" - yargs "6.4.0" - -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= - dependencies: - bn.js "^4.1.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= - dependencies: - bn.js "^4.1.1" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.2" - elliptic "^6.0.0" - inherits "^2.0.1" - parse-asn1 "^5.0.0" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - -browserslist@^4.0.0, browserslist@^4.11.1, browserslist@^4.6.4, browserslist@^4.8.5, browserslist@^4.9.1: - version "4.11.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.11.1.tgz#92f855ee88d6e050e7e7311d987992014f1a1f1b" - integrity sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g== - dependencies: - caniuse-lite "^1.0.30001038" - electron-to-chromium "^1.3.390" - node-releases "^1.1.53" - pkg-up "^2.0.0" - -bs-recipes@1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/bs-recipes/-/bs-recipes-1.3.4.tgz#0d2d4d48a718c8c044769fdc4f89592dc8b69585" - integrity sha1-DS1NSKcYyMBEdp/cT4lZLci2lYU= - -bs-snippet-injector@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz#61b5393f11f52559ed120693100343b6edb04dd5" - integrity sha1-YbU5PxH1JVntEgaTEANDtu2wTdU= - -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= - -buffer-equal@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" - integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs= - -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= - -buffer@^4.3.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -buffer@^5.2.0, buffer@^5.2.1: - version "5.5.0" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.5.0.tgz#9c3caa3d623c33dd1c7ef584b89b88bf9c9bc1ce" - integrity sha512-9FTEDjLjwoAkEwyMGDjYJQN2gfRgOKBKRfiglhvibGbpeeU/pQn1bJxQqm32OD/AIeEuHxU9roxXxg34Byp/Ww== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -cacache@^12.0.2: - version "12.0.4" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" - integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== - dependencies: - bluebird "^3.5.5" - chownr "^1.1.1" - figgy-pudding "^3.5.1" - glob "^7.1.4" - graceful-fs "^4.1.15" - infer-owner "^1.0.3" - lru-cache "^5.1.1" - mississippi "^3.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.3" - ssri "^6.0.1" - unique-filename "^1.1.1" - y18n "^4.0.0" - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -cacheable-request@^2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" - integrity sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0= - dependencies: - clone-response "1.0.2" - get-stream "3.0.0" - http-cache-semantics "3.8.1" - keyv "3.0.0" - lowercase-keys "1.0.0" - normalize-url "2.0.1" - responselike "1.0.2" - -calipers-gif@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/calipers-gif/-/calipers-gif-2.0.0.tgz#b5eefec3064a77c6dcdbd5bdc51735a01bafdc37" - integrity sha1-te7+wwZKd8bc29W9xRc1oBuv3Dc= - dependencies: - bluebird "3.x.x" - -calipers-jpeg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/calipers-jpeg/-/calipers-jpeg-2.0.0.tgz#06d56a53f62717dd809cb956cf64423ce693465b" - integrity sha1-BtVqU/YnF92AnLlWz2RCPOaTRls= - dependencies: - bluebird "3.x.x" - -calipers-png@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/calipers-png/-/calipers-png-2.0.0.tgz#1d0d20e5c1ae5f79b74d5286a2e97f59bb70b658" - integrity sha1-HQ0g5cGuX3m3TVKGoul/Wbtwtlg= - dependencies: - bluebird "3.x.x" - -calipers-svg@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/calipers-svg/-/calipers-svg-2.0.1.tgz#cd9eaa58ef7428c1a14f5da57e56715fb60f6541" - integrity sha512-3PROqHARmj8wWudUC7DzXm1+mSocqgY7jNuehFNHgrUVrKf8o7MqDjS92vJz5LvZsAofJsoAFMajkqwbxBROSQ== - dependencies: - bluebird "3.x.x" - -calipers-webp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/calipers-webp/-/calipers-webp-2.0.0.tgz#e126ece2f84cd71779612bfa2b2653cd95cea77a" - integrity sha1-4Sbs4vhM1xd5YSv6KyZTzZXOp3o= - dependencies: - bluebird "3.x.x" - -calipers@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/calipers/-/calipers-2.0.1.tgz#0d3f303ce75ec5f1eda7fecfc7dba6736e35c926" - integrity sha512-AP4Ui2Z8fZf69d8Dx4cfJgPjQHY3m+QXGFCaAGu8pfNQjyajkosS+Kkf1n6pQDMZcelN5h3MdcjweUqxcsS4pg== - dependencies: - bluebird "3.x.x" - -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= - dependencies: - caller-callsite "^2.0.0" - -callsite@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" - integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA= - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camel-case@3.0.x: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" - integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= - dependencies: - no-case "^2.2.0" - upper-case "^1.1.1" - -camelcase-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= - dependencies: - camelcase "^2.0.0" - map-obj "^1.0.0" - -camelcase@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= - -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001038, caniuse-lite@^1.0.30001039: - version "1.0.30001041" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001041.tgz#c2ea138dafc6fe03877921ddcddd4a02a14daf76" - integrity sha512-fqDtRCApddNrQuBxBS7kEiSGdBsgO4wiVw4G/IClfqzfhW45MbTumfN4cuUJGTM0YGFNn97DCXPJ683PS6zwvA== - -caw@^2.0.0, caw@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95" - integrity sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA== - dependencies: - get-proxy "^2.0.0" - isurl "^1.0.0-alpha5" - tunnel-agent "^0.6.0" - url-to-options "^1.0.1" - -chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" - integrity sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.0.0.tgz#6e98081ed2d17faab615eb52ac66ec1fe6209e72" - integrity sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chance@1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/chance/-/chance-1.0.13.tgz#666bec2db42b3084456a3e4f4c28a82db5ccb7e6" - integrity sha512-9cpcgmAIQiXC0eMgQuMZgXuHR2Y+gKUyGQnalqSAg5LlUJyJFsZeKyuHVSGhj+bx18ppH+Jo3VOayNeXR/7p9Q== - -chardet@^0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" - integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= - -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - -charenc@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= - -check-types@^8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552" - integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ== - -chokidar@^2.0.4, chokidar@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - -chownr@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - -chrome-trace-event@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" - integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== - dependencies: - tslib "^1.9.0" - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -circular-dependency-plugin@^5.0.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/circular-dependency-plugin/-/circular-dependency-plugin-5.2.0.tgz#e09dbc2dd3e2928442403e2d45b41cea06bc0a93" - integrity sha512-7p4Kn/gffhQaavNfyDFg7LS5S/UT1JAjyGd4UqR2+jzoYF02eDkj0Ec3+48TsIa4zghjLY87nQHIh/ecK9qLdw== - -circular-json@^0.5.9: - version "0.5.9" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.9.tgz#932763ae88f4f7dead7a0d09c8a51a4743a53b1d" - integrity sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ== - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -class-validator@0.8.5: - version "0.8.5" - resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.8.5.tgz#484785acda98f68549c3a84dc1bb2f77b736dc58" - integrity sha512-84yezRo44aP4oGhvPmqj6obAFQF1NzUyfR0+f8jubzdAspO5pmjpHhBBlPf335epUskzXAFe5uo4Qf+c7SI+DA== - dependencies: - validator "9.2.0" - -clean-css@4.2.x: - version "4.2.3" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" - integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== - dependencies: - source-map "~0.6.0" - -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= - dependencies: - restore-cursor "^2.0.0" - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-table@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" - integrity sha1-9TsFJmqLGguTSz0IIebi3FkUriM= - dependencies: - colors "1.0.3" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= - -clipboard-copy@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/clipboard-copy/-/clipboard-copy-3.1.0.tgz#4c59030a43d4988990564a664baeafba99f78ca4" - integrity sha512-Xsu1NddBXB89IUauda5BIq3Zq73UWkjkaQlPQbLNvNsd5WBMnTWPNKYR6HGaySOxGYZ+BKxP2E9X4ElnI3yiPA== - -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - -cliui@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" - integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^6.2.0" - -clone-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= - -clone-response@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= - -clone@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= - -cloneable-readable@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.3.tgz#120a00cb053bfb63a222e709f9683ea2e11d8cec" - integrity sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ== - dependencies: - inherits "^2.0.1" - process-nextick-args "^2.0.0" - readable-stream "^2.3.5" - -coa@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" - integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== - dependencies: - "@types/q" "^1.5.1" - chalk "^2.4.1" - q "^1.1.2" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0, color-convert@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@^1.0.0, color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-string@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" - integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== - dependencies: - color-name "^1.0.0" - simple-swizzle "^0.2.2" - -color-support@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - -color@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" - integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== - dependencies: - color-convert "^1.9.1" - color-string "^1.5.2" - -colors@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" - integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= - -colors@^1.3.3: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== - -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== - -commander@2.17.x: - version "2.17.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== - -commander@^2.18.0, commander@^2.2.0, commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@~2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== - -commander@~2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= - dependencies: - graceful-readlink ">= 1.0.0" - -commander@~2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q= - dependencies: - graceful-readlink ">= 1.0.0" - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -component-bind@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" - integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= - -component-emitter@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= - -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - -component-inherit@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" - integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -concat-stream@^1.5.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -config-chain@^1.1.11: - version "1.1.12" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" - integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - -connect-history-api-fallback@^1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== - -connect@3.6.6: - version "3.6.6" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.6.tgz#09eff6c55af7236e137135a72574858b6786f524" - integrity sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ= - dependencies: - debug "2.6.9" - finalhandler "1.1.0" - parseurl "~1.3.2" - utils-merge "1.0.1" - -console-browserify@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" - integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== - -console-stream@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/console-stream/-/console-stream-0.1.1.tgz#a095fe07b20465955f2fafd28b5d72bccd949d44" - integrity sha1-oJX+B7IEZZVfL6/Si11yvM2UnUQ= - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= - -content-disposition@0.5.3, content-disposition@^0.5.2: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== - dependencies: - safe-buffer "5.1.2" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - -copy-concurrently@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" - integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== - dependencies: - aproba "^1.1.1" - fs-write-stream-atomic "^1.0.8" - iferr "^0.1.5" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.0" - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -core-js-compat@^3.6.2: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" - integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng== - dependencies: - browserslist "^4.8.5" - semver "7.0.0" - -core-js@3: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" - integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== - -core-js@^2.4.0, core-js@^2.5.3, core-js@^2.5.7: - version "2.6.11" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" - integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cosmiconfig@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - -create-ecdh@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== - dependencies: - bn.js "^4.1.0" - elliptic "^6.0.0" - -create-hash@^1.1.0, create-hash@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -cross-spawn@6.0.5, cross-spawn@^6.0.0: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^7.0.2: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -crypt@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= - -crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -css-blank-pseudo@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" - integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w== - dependencies: - postcss "^7.0.5" - -css-color-names@0.0.4, css-color-names@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" - integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= - -css-declaration-sorter@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" - integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== - dependencies: - postcss "^7.0.1" - timsort "^0.3.0" - -css-has-pseudo@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee" - integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ== - dependencies: - postcss "^7.0.6" - postcss-selector-parser "^5.0.0-rc.4" - -css-loader@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.9.1.tgz#2e1aa00ce7e30ef2c6a7a4b300a080a7c979e0dc" - integrity sha1-LhqgDOfjDvLGp6SzAKCAp8l54Nw= - dependencies: - csso "1.3.x" - loader-utils "~0.2.2" - source-map "~0.1.38" - -css-mqpacker@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/css-mqpacker/-/css-mqpacker-7.0.0.tgz#48f4a0ff45b81ec661c4a33ed80b9db8a026333b" - integrity sha512-temVrWS+sB4uocE2quhW8ru/KguDmGhCU7zN213KxtDvWOH3WS/ZUStfpF4fdCT7W8fPpFrQdWRFqtFtPPfBLA== - dependencies: - minimist "^1.2.0" - postcss "^7.0.0" - -css-prefers-color-scheme@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" - integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg== - dependencies: - postcss "^7.0.5" - -css-select-base-adapter@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" - integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== - -css-select@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" - integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== - dependencies: - boolbase "^1.0.0" - css-what "^3.2.1" - domutils "^1.7.0" - nth-check "^1.0.2" - -css-tree@1.0.0-alpha.37: - version "1.0.0-alpha.37" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" - integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== - dependencies: - mdn-data "2.0.4" - source-map "^0.6.1" - -css-tree@1.0.0-alpha.39: - version "1.0.0-alpha.39" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb" - integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA== - dependencies: - mdn-data "2.0.6" - source-map "^0.6.1" - -css-what@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" - integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== - -cssdb@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" - integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ== - -cssesc@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" - integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -cssnano-preset-advanced@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-4.0.7.tgz#d981527b77712e2f3f3f09c73313e9b71b278b88" - integrity sha512-j1O5/DQnaAqEyFFQfC+Z/vRlLXL3LxJHN+lvsfYqr7KgPH74t69+Rsy2yXkovWNaJjZYBpdz2Fj8ab2nH7pZXw== - dependencies: - autoprefixer "^9.4.7" - cssnano-preset-default "^4.0.7" - postcss-discard-unused "^4.0.1" - postcss-merge-idents "^4.0.1" - postcss-reduce-idents "^4.0.2" - postcss-zindex "^4.0.1" - -cssnano-preset-default@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" - integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== - dependencies: - css-declaration-sorter "^4.0.1" - cssnano-util-raw-cache "^4.0.1" - postcss "^7.0.0" - postcss-calc "^7.0.1" - postcss-colormin "^4.0.3" - postcss-convert-values "^4.0.1" - postcss-discard-comments "^4.0.2" - postcss-discard-duplicates "^4.0.2" - postcss-discard-empty "^4.0.1" - postcss-discard-overridden "^4.0.1" - postcss-merge-longhand "^4.0.11" - postcss-merge-rules "^4.0.3" - postcss-minify-font-values "^4.0.2" - postcss-minify-gradients "^4.0.2" - postcss-minify-params "^4.0.2" - postcss-minify-selectors "^4.0.2" - postcss-normalize-charset "^4.0.1" - postcss-normalize-display-values "^4.0.2" - postcss-normalize-positions "^4.0.2" - postcss-normalize-repeat-style "^4.0.2" - postcss-normalize-string "^4.0.2" - postcss-normalize-timing-functions "^4.0.2" - postcss-normalize-unicode "^4.0.1" - postcss-normalize-url "^4.0.1" - postcss-normalize-whitespace "^4.0.2" - postcss-ordered-values "^4.1.2" - postcss-reduce-initial "^4.0.3" - postcss-reduce-transforms "^4.0.2" - postcss-svgo "^4.0.2" - postcss-unique-selectors "^4.0.1" - -cssnano-util-get-arguments@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" - integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= - -cssnano-util-get-match@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" - integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= - -cssnano-util-raw-cache@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" - integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== - dependencies: - postcss "^7.0.0" - -cssnano-util-same-parent@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" - integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== - -cssnano@^4.1.10: - version "4.1.10" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" - integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== - dependencies: - cosmiconfig "^5.0.0" - cssnano-preset-default "^4.0.7" - is-resolvable "^1.0.0" - postcss "^7.0.0" - -csso@1.3.x: - version "1.3.12" - resolved "https://registry.yarnpkg.com/csso/-/csso-1.3.12.tgz#fc628694a2d38938aaac4996753218fd311cdb9e" - integrity sha1-/GKGlKLTiTiqrEmWdTIY/TEc254= - -csso@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.3.tgz#0d9985dc852c7cc2b2cacfbbe1079014d1a8e903" - integrity sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ== - dependencies: - css-tree "1.0.0-alpha.39" - -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= - dependencies: - array-find-index "^1.0.1" - -cyclist@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" - integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= - -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@4.1.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@~4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - -debug@=3.1.0, debug@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -decompress-response@^3.2.0, decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - -decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== - dependencies: - file-type "^5.2.0" - is-stream "^1.1.0" - tar-stream "^1.5.2" - -decompress-tarbz2@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== - dependencies: - decompress-tar "^4.1.0" - file-type "^6.1.0" - is-stream "^1.1.0" - seek-bzip "^1.0.5" - unbzip2-stream "^1.0.9" - -decompress-targz@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" - integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== - dependencies: - decompress-tar "^4.1.1" - file-type "^5.2.0" - is-stream "^1.1.0" - -decompress-unzip@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= - dependencies: - file-type "^3.8.0" - get-stream "^2.2.0" - pify "^2.3.0" - yauzl "^2.4.2" - -decompress@^4.0.0, decompress@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118" - integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ== - dependencies: - decompress-tar "^4.0.0" - decompress-tarbz2 "^4.0.0" - decompress-targz "^4.0.0" - decompress-unzip "^4.0.1" - graceful-fs "^4.1.10" - make-dir "^1.0.0" - pify "^2.3.0" - strip-dirs "^2.0.0" - -deep-is@^0.1.3, deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -deep-scope-analyser@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/deep-scope-analyser/-/deep-scope-analyser-1.7.0.tgz#23015b3a1d23181b1d9cebd25b783a7378ead8da" - integrity sha512-rl5Dmt2IZkFpZo6XbEY1zG8st2Wpq8Pi/dV2gz8ZF6BDYt3fnor2JNxHwdO1WLo0k6JbmYp0x8MNy8kE4l1NtA== - dependencies: - esrecurse "^4.2.1" - estraverse "^4.2.0" - -define-properties@^1.1.2, define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -detect-file@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" - integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= - -dev-ip@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/dev-ip/-/dev-ip-1.0.1.tgz#a76a3ed1855be7a012bb8ac16cb80f3c00dc28f0" - integrity sha1-p2o+0YVb56ASu4rBbLgPPADcKPA= - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dom-serializer@0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -dom-walk@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" - integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== - -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== - -domelementtype@1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - -domelementtype@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" - integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== - -domutils@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -dot-prop@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" - integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== - dependencies: - is-obj "^2.0.0" - -download@^6.2.2: - version "6.2.5" - resolved "https://registry.yarnpkg.com/download/-/download-6.2.5.tgz#acd6a542e4cd0bb42ca70cfc98c9e43b07039714" - integrity sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA== - dependencies: - caw "^2.0.0" - content-disposition "^0.5.2" - decompress "^4.0.0" - ext-name "^5.0.0" - file-type "5.2.0" - filenamify "^2.0.0" - get-stream "^3.0.0" - got "^7.0.0" - make-dir "^1.0.0" - p-event "^1.0.0" - pify "^3.0.0" - -download@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/download/-/download-7.1.0.tgz#9059aa9d70b503ee76a132897be6dec8e5587233" - integrity sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ== - dependencies: - archive-type "^4.0.0" - caw "^2.0.1" - content-disposition "^0.5.2" - decompress "^4.2.0" - ext-name "^5.0.0" - file-type "^8.1.0" - filenamify "^2.0.0" - get-stream "^3.0.0" - got "^8.3.1" - make-dir "^1.2.0" - p-event "^2.1.0" - pify "^3.0.0" - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= - -duplexer@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= - -duplexify@^3.4.2, duplexify@^3.6.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -easy-extender@^2.3.4: - version "2.3.4" - resolved "https://registry.yarnpkg.com/easy-extender/-/easy-extender-2.3.4.tgz#298789b64f9aaba62169c77a2b3b64b4c9589b8f" - integrity sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q== - dependencies: - lodash "^4.17.10" - -eazy-logger@^3: - version "3.0.2" - resolved "https://registry.yarnpkg.com/eazy-logger/-/eazy-logger-3.0.2.tgz#a325aa5e53d13a2225889b2ac4113b2b9636f4fc" - integrity sha1-oyWqXlPROiIliJsqxBE7K5Y29Pw= - dependencies: - tfunk "^3.0.1" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -ejs@^2.6.1: - version "2.7.4" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" - integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== - -electron-to-chromium@^1.3.390: - version "1.3.403" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.403.tgz#c8bab4e2e72bf78bc28bad1cc355c061f9cc1918" - integrity sha512-JaoxV4RzdBAZOnsF4dAlZ2ijJW72MbqO5lNfOBHUWiBQl3Rwe+mk2RCUMrRI3rSClLJ8HSNQNqcry12H+0ZjFw== - -elliptic@^6.0.0: - version "6.5.2" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" - integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw== - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" - -email-validator@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/email-validator/-/email-validator-2.0.4.tgz#b8dfaa5d0dae28f1b03c95881d904d4e40bfe7ed" - integrity sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ== - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= - -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - -encodeurl@~1.0.1, encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= - dependencies: - iconv-lite "~0.4.13" - -end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -engine.io-client@~3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36" - integrity sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw== - dependencies: - component-emitter "1.2.1" - component-inherit "0.0.3" - debug "~3.1.0" - engine.io-parser "~2.1.1" - has-cors "1.1.0" - indexof "0.0.1" - parseqs "0.0.5" - parseuri "0.0.5" - ws "~3.3.1" - xmlhttprequest-ssl "~1.5.4" - yeast "0.1.2" - -engine.io-client@~3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.4.0.tgz#82a642b42862a9b3f7a188f41776b2deab643700" - integrity sha512-a4J5QO2k99CM2a0b12IznnyQndoEvtA4UAldhGzKqnHf42I3Qs2W5SPnDvatZRcMaNZs4IevVicBPayxYt6FwA== - dependencies: - component-emitter "1.2.1" - component-inherit "0.0.3" - debug "~4.1.0" - engine.io-parser "~2.2.0" - has-cors "1.1.0" - indexof "0.0.1" - parseqs "0.0.5" - parseuri "0.0.5" - ws "~6.1.0" - xmlhttprequest-ssl "~1.5.4" - yeast "0.1.2" - -engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.3.tgz#757ab970fbf2dfb32c7b74b033216d5739ef79a6" - integrity sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA== - dependencies: - after "0.8.2" - arraybuffer.slice "~0.0.7" - base64-arraybuffer "0.1.5" - blob "0.0.5" - has-binary2 "~1.0.2" - -engine.io-parser@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.0.tgz#312c4894f57d52a02b420868da7b5c1c84af80ed" - integrity sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w== - dependencies: - after "0.8.2" - arraybuffer.slice "~0.0.7" - base64-arraybuffer "0.1.5" - blob "0.0.5" - has-binary2 "~1.0.2" - -engine.io@~3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.1.tgz#b60281c35484a70ee0351ea0ebff83ec8c9522a2" - integrity sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w== - dependencies: - accepts "~1.3.4" - base64id "1.0.0" - cookie "0.3.1" - debug "~3.1.0" - engine.io-parser "~2.1.0" - ws "~3.3.1" - -enhanced-resolve@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" - integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.4.0" - tapable "^1.0.0" - -enhanced-resolve@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" - integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.5.0" - tapable "^1.0.0" - -entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" - integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== - -errno@^0.1.3, errno@~0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== - dependencies: - prr "~1.0.1" - -error-ex@^1.2.0, error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5: - version "1.17.5" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" - integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.1.5" - is-regex "^1.0.5" - object-inspect "^1.7.0" - object-keys "^1.1.1" - object.assign "^4.1.0" - string.prototype.trimleft "^2.1.1" - string.prototype.trimright "^2.1.1" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es6-templates@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/es6-templates/-/es6-templates-0.2.3.tgz#5cb9ac9fb1ded6eb1239342b81d792bbb4078ee4" - integrity sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ= - dependencies: - recast "~0.11.12" - through "~2.3.6" - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escodegen-wallaby@1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/escodegen-wallaby/-/escodegen-wallaby-1.6.18.tgz#95a41e2fdc88687466e43550c7bf136386fd4363" - integrity sha512-3UvR14JRNh8VfKJixTDHWmhPNKAJiVZS807KUjECBk6f05WMe8ZeWL1gbrswNYhDiAUeDBQccyTWR91fayx3og== - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" - -eslint-config-prettier@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz#f6d2238c1290d01c859a8b5c1f7d352a0b0da8b1" - integrity sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA== - dependencies: - get-stdin "^6.0.0" - -eslint-plugin-prettier@3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.3.tgz#ae116a0fc0e598fdae48743a4430903de5b4e6ca" - integrity sha512-+HG5jmu/dN3ZV3T6eCD7a4BlAySdN7mLIbJYo0z1cFQuI+r2DiTJEFeF68ots93PsnrMxbzIZ2S/ieX+mkrBeQ== - dependencies: - prettier-linter-helpers "^1.0.0" - -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-scope@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" - integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" - integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-visitor-keys@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== - -eslint@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.1.0.tgz#d9a1df25e5b7859b0a3d86bb05f0940ab676a851" - integrity sha512-DfS3b8iHMK5z/YLSme8K5cge168I8j8o1uiVmFCgnnjxZQbCGyraF8bMl7Ju4yfBmCuxD7shOF7eqGkcuIHfsA== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - eslint-visitor-keys "^1.1.0" - espree "^7.0.0" - esquery "^1.2.0" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^7.0.0" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash "^4.17.14" - minimatch "^3.0.4" - natural-compare "^1.4.0" - optionator "^0.9.1" - progress "^2.0.0" - regexpp "^3.1.0" - semver "^7.2.1" - strip-ansi "^6.0.0" - strip-json-comments "^3.1.0" - table "^5.2.3" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - -espree@3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== - dependencies: - acorn "^5.5.0" - acorn-jsx "^3.0.0" - -espree@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.0.0.tgz#8a7a60f218e69f120a842dc24c5a88aa7748a74e" - integrity sha512-/r2XEx5Mw4pgKdyb7GNLQNsu++asx/dltf/CI8RFi9oGHxmQFgvLbc5Op4U6i8Oaj+kdslhJtVlEZeAqH5qOTw== - dependencies: - acorn "^7.1.1" - acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.1.0" - -esprima@^2.7.1: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esprima@~3.1.0: - version "3.1.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= - -esquery@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" - integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.1.0, esrecurse@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== - dependencies: - estraverse "^4.1.0" - -estraverse@4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= - -estraverse@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= - -estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" - integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@1.8.1, etag@^1.8.1, etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eventemitter3@1.x.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" - integrity sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg= - -events@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" - integrity sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -execa@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" - integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw== - dependencies: - cross-spawn "^6.0.0" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -executable@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" - integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== - dependencies: - pify "^2.2.0" - -exif-parser@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/exif-parser/-/exif-parser-0.1.12.tgz#58a9d2d72c02c1f6f02a0ef4a9166272b7760922" - integrity sha1-WKnS1ywCwfbwKg70qRZicrd2CSI= - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -expand-tilde@^2.0.0, expand-tilde@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= - dependencies: - homedir-polyfill "^1.0.1" - -express@^4.16.3: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -ext-list@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37" - integrity sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA== - dependencies: - mime-db "^1.28.0" - -ext-name@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ext-name/-/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6" - integrity sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ== - dependencies: - ext-list "^2.0.0" - sort-keys-length "^1.0.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -external-editor@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" - integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== - dependencies: - chardet "^0.4.0" - iconv-lite "^0.4.17" - tmp "^0.0.33" - -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -fancy-log@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" - integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - parse-node-version "^1.0.0" - time-stamp "^1.0.0" - -fast-deep-equal@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" - integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== - -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -fastdom@^1.0.8: - version "1.0.9" - resolved "https://registry.yarnpkg.com/fastdom/-/fastdom-1.0.9.tgz#b395fab11a3701173c02a054fe769d8f596a0a26" - integrity sha512-SSp4fbVzu8JkkG01NUX+0iOwe9M5PN3MGIQ84txLf4TkkJG4q30khkzumKgi4hUqO1+jX6wLHfnCPoZ6eSZ6Tg== - dependencies: - strictdom "^1.0.1" - -faster.js@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/faster.js/-/faster.js-1.1.1.tgz#8bbd7eefdb8f03faac26ad5025b059f94c5cfb4d" - integrity sha512-vPThNSLL/E1f7cLHd9yuayxZR82o/Iic4S5ZY45iY5AgBLNIlr3b3c+VpDjoYqjY9a9C/FQVUQy9oTILVP7X0g== - -fastparse@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" - integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== - -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= - dependencies: - pend "~1.2.0" - -figgy-pudding@^3.5.1: - version "3.5.2" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" - integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== - -figures@^1.3.5: - version "1.7.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" - integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= - dependencies: - escape-string-regexp "^1.0.5" - object-assign "^4.1.0" - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= - dependencies: - escape-string-regexp "^1.0.5" - -figures@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - -file-loader@^0.8.1: - version "0.8.5" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-0.8.5.tgz#9275d031fe780f27d47f5f4af02bd43713cc151b" - integrity sha1-knXQMf54DyfUf19K8CvUNxPMFRs= - dependencies: - loader-utils "~0.2.5" - -file-type@5.2.0, file-type@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - integrity sha1-LdvqfHP/42No365J3DOMBYwritY= - -file-type@^3.8.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= - -file-type@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" - integrity sha1-G2AOX8ofvcboDApwxxyNul95BsU= - -file-type@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" - integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== - -file-type@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-8.1.0.tgz#244f3b7ef641bbe0cca196c7276e4b332399f68c" - integrity sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ== - -file-type@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-9.0.0.tgz#a68d5ad07f486414dfb2c8866f73161946714a18" - integrity sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw== - -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -filename-reserved-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" - integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik= - -filenamify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-2.1.0.tgz#88faf495fb1b47abfd612300002a16228c677ee9" - integrity sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA== - dependencies: - filename-reserved-regex "^2.0.0" - strip-outer "^1.0.0" - trim-repeated "^1.0.0" - -filesize@^3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" - integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -finalhandler@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" - integrity sha1-zgtoVbRYU+eRsvzGgARtiCU91/U= - dependencies: - debug "2.6.9" - encodeurl "~1.0.1" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.2" - statuses "~1.3.1" - unpipe "~1.0.0" - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -find-cache-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-versions@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e" - integrity sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww== - dependencies: - semver-regex "^2.0.0" - -findup-sync@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" - integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== - dependencies: - detect-file "^1.0.0" - is-glob "^4.0.0" - micromatch "^3.0.4" - resolve-dir "^1.0.1" - -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - -flatted@^2.0.0, flatted@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== - -flatten@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" - integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== - -flush-write-stream@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" - integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== - dependencies: - inherits "^2.0.3" - readable-stream "^2.3.6" - -follow-redirects@1.5.10: - version "1.5.10" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" - integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== - dependencies: - debug "=3.1.0" - -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -fresh@0.5.2, fresh@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -from2@^2.1.0, from2@^2.1.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.0" - -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - -fs-extra@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" - integrity sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE= - dependencies: - graceful-fs "^4.1.2" - jsonfile "^3.0.0" - universalify "^0.1.0" - -fs-write-stream-atomic@^1.0.8: - version "1.0.10" - resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" - integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= - dependencies: - graceful-fs "^4.1.2" - iferr "^0.1.5" - imurmurhash "^0.1.4" - readable-stream "1 || 2" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^1.2.7: - version "1.2.12" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.12.tgz#db7e0d8ec3b0b45724fd4d83d43554a8f1f0de5c" - integrity sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= - -gensync@^1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" - integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== - -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-proxy@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93" - integrity sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw== - dependencies: - npm-conf "^1.1.0" - -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= - -get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== - -get-stream@3.0.0, get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - -get-stream@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" - integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - -get-stream@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -glob-all@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.2.1.tgz#082ca81afd2247cbd3ed2149bb2630f4dc877d95" - integrity sha512-x877rVkzB3ipid577QOp+eQCR6M5ZyiwrtaYgrX/z3EThaSPFtLDwBXFHc3sH1cG0R0vFYI5SRYeWMMSEyXkUw== - dependencies: - glob "^7.1.2" - yargs "^15.3.1" - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-parent@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== - dependencies: - is-glob "^4.0.1" - -glob@^7.0.5, glob@^7.0.6, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global-modules@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - -global-modules@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" - integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== - dependencies: - global-prefix "^1.0.1" - is-windows "^1.0.1" - resolve-dir "^1.0.0" - -global-prefix@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" - integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= - dependencies: - expand-tilde "^2.0.2" - homedir-polyfill "^1.0.1" - ini "^1.3.4" - is-windows "^1.0.1" - which "^1.2.14" - -global-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" - integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== - dependencies: - ini "^1.3.5" - kind-of "^6.0.2" - which "^1.3.1" - -global@~4.3.0: - version "4.3.2" - resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" - integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= - dependencies: - min-document "^2.19.0" - process "~0.5.1" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^12.1.0: - version "12.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" - integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== - dependencies: - type-fest "^0.8.1" - -gonzales-pe@^4.2.3: - version "4.3.0" - resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.3.0.tgz#fe9dec5f3c557eead09ff868c65826be54d067b3" - integrity sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ== - dependencies: - minimist "^1.2.5" - -got@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== - dependencies: - decompress-response "^3.2.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-plain-obj "^1.1.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - p-cancelable "^0.3.0" - p-timeout "^1.1.1" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - url-parse-lax "^1.0.0" - url-to-options "^1.0.1" - -got@^8.3.1: - version "8.3.2" - resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" - integrity sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw== - dependencies: - "@sindresorhus/is" "^0.7.0" - cacheable-request "^2.1.1" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - into-stream "^3.1.0" - is-retry-allowed "^1.1.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - mimic-response "^1.0.0" - p-cancelable "^0.4.0" - p-timeout "^2.0.1" - pify "^3.0.0" - safe-buffer "^5.1.1" - timed-out "^4.0.1" - url-parse-lax "^3.0.0" - url-to-options "^1.0.1" - -graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" - integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== - -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= - -gzip-size@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" - integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== - dependencies: - duplexer "^0.1.1" - pify "^4.0.1" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-binary2@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d" - integrity sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw== - dependencies: - isarray "2.0.1" - -has-cors@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" - integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbol-support-x@^1.4.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" - integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== - -has-symbols@^1.0.0, has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== - -has-to-string-tag-x@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== - dependencies: - has-symbol-support-x "^1.4.1" - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has@^1.0.0, has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -he@1.2.x: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -hex-color-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" - integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== - -hmac-drbg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -homedir-polyfill@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" - integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== - dependencies: - parse-passwd "^1.0.0" - -hoopy@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" - integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== - -hosted-git-info@^2.1.4: - version "2.8.8" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" - integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== - -howler@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/howler/-/howler-2.1.3.tgz#07c88618f8767e879407a4d647fe2d6d5f15f121" - integrity sha512-PSGbOi1EYgw80C5UQbxtJM7TmzD+giJunIMBYyH3RVzHZx2fZLYBoes0SpVVHi/SFa1GoNtgXj/j6I7NOKYBxQ== - -hsl-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" - integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= - -hsla-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" - integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= - -html-comment-regex@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" - integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== - -html-loader@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-0.5.5.tgz#6356dbeb0c49756d8ebd5ca327f16ff06ab5faea" - integrity sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog== - dependencies: - es6-templates "^0.2.3" - fastparse "^1.1.1" - html-minifier "^3.5.8" - loader-utils "^1.1.0" - object-assign "^4.1.1" - -html-minifier@^3.5.8: - version "3.5.21" - resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" - integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA== - dependencies: - camel-case "3.0.x" - clean-css "4.2.x" - commander "2.17.x" - he "1.2.x" - param-case "2.1.x" - relateurl "0.2.x" - uglify-js "3.4.x" - -http-cache-semantics@3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" - integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== - -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@1.7.3, http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-proxy@1.15.2: - version "1.15.2" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.15.2.tgz#642fdcaffe52d3448d2bda3b0079e9409064da31" - integrity sha1-ZC/cr/5S00SNK9o7AHnpQJBk2jE= - dependencies: - eventemitter3 "1.x.x" - requires-port "1.x.x" - -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= - -iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@~0.4.13: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ieee754@^1.1.4: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== - -iferr@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" - integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= - -ignore-loader@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ignore-loader/-/ignore-loader-0.1.2.tgz#d81f240376d0ba4f0d778972c3ad25874117a463" - integrity sha1-2B8kA3bQuk8Nd4lyw60lh0EXpGM= - -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -imagemin-mozjpeg@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/imagemin-mozjpeg/-/imagemin-mozjpeg-8.0.0.tgz#d2ca4e8c982c7c6eda55069af89dee4c1cebcdfd" - integrity sha512-+EciPiIjCb8JWjQNr1q8sYWYf7GDCNDxPYnkD11TNIjjWNzaV+oTg4DpOPQjl5ZX/KRCPMEgS79zLYAQzLitIA== - dependencies: - execa "^1.0.0" - is-jpg "^2.0.0" - mozjpeg "^6.0.0" - -imagemin-pngquant@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/imagemin-pngquant/-/imagemin-pngquant-8.0.0.tgz#bf7a41d850c6998f2475c54058ab1db9c516385d" - integrity sha512-PVq0diOxO+Zyq/zlMCz2Pfu6mVLHgiT1GpW702OwVlnej+NhS6ZQegYi3OFEDW8d7GxouyR5e8R+t53SMciOeg== - dependencies: - execa "^1.0.0" - is-png "^2.0.0" - is-stream "^2.0.0" - ow "^0.13.2" - pngquant-bin "^5.0.0" - -immutable@^3: - version "3.8.2" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" - integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM= - -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - -import-fresh@^3.0.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" - integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-lazy@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc" - integrity sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ== - -import-local@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" - integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== - dependencies: - pkg-dir "^3.0.0" - resolve-cwd "^2.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -indent-string@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= - dependencies: - repeating "^2.0.0" - -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= - -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= - -infer-owner@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" - integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@^1.3.4, ini@^1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -inquirer@3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" - integrity sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c= - dependencies: - ansi-escapes "^1.1.0" - chalk "^1.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.1" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx "^4.1.0" - string-width "^2.0.0" - strip-ansi "^3.0.0" - through "^2.3.6" - -inquirer@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29" - integrity sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg== - dependencies: - ansi-escapes "^4.2.1" - chalk "^3.0.0" - cli-cursor "^3.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.15" - mute-stream "0.0.8" - run-async "^2.4.0" - rxjs "^6.5.3" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - -interpret@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== - -into-stream@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" - integrity sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY= - dependencies: - from2 "^2.1.1" - p-is-promise "^1.1.0" - -invariant@^2.2.2, invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -inversify@4.11.1: - version "4.11.1" - resolved "https://registry.yarnpkg.com/inversify/-/inversify-4.11.1.tgz#9a10635d1fd347da11da96475b3608babd5945a6" - integrity sha512-9bs/36crPdTSOCcoomHMb96s+B8W0+2c9dHFP/Srv9ZQaPnUvsMgzmMHfgVECqfHVUIW+M5S7SYOjoig8khWuQ== - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= - -invert-kv@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" - integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-absolute-url@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-arrayish@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - -is-buffer@^1.1.5, is-buffer@~1.1.1: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-buffer@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" - integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== - -is-callable@^1.1.4, is-callable@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" - integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== - -is-color-stop@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" - integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= - dependencies: - css-color-names "^0.0.4" - hex-color-regex "^1.1.0" - hsl-regex "^1.0.0" - hsla-regex "^1.0.0" - rgb-regex "^1.0.1" - rgba-regex "^1.0.0" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-date-object@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" - integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-finite@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" - integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-function@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" - integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0, is-glob@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-jpg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-jpg/-/is-jpg-2.0.0.tgz#2e1997fa6e9166eaac0242daae443403e4ef1d97" - integrity sha1-LhmX+m6RZuqsAkLarkQ0A+TvHZc= - -is-natural-number@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= - -is-number-like@^1.0.3: - version "1.0.8" - resolved "https://registry.yarnpkg.com/is-number-like/-/is-number-like-1.0.8.tgz#2e129620b50891042e44e9bbbb30593e75cfbbe3" - integrity sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA== - dependencies: - lodash.isfinite "^3.3.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - -is-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" - integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= - -is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-png@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-png/-/is-png-2.0.0.tgz#ee8cbc9e9b050425cedeeb4a6fb74a649b0a4a8d" - integrity sha512-4KPGizaVGj2LK7xwJIz8o5B2ubu1D/vcQsgOGFEDlpcvgZHto4gBnyd0ig7Ws+67ixmwKoNmu0hYnpo6AaKb5g== - -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - -is-regex@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" - integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== - dependencies: - has "^1.0.3" - -is-resolvable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== - -is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" - integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== - -is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" - integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== - -is-svg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" - integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== - dependencies: - html-comment-regex "^1.1.0" - -is-symbol@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" - integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== - dependencies: - has-symbols "^1.0.1" - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-windows@^1.0.1, is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isarray@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" - integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -isurl@^1.0.0-alpha5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== - dependencies: - has-to-string-tag-x "^1.2.0" - is-object "^1.0.1" - -javascript-obfuscator@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/javascript-obfuscator/-/javascript-obfuscator-0.15.0.tgz#e2b348c3a6895ef9195e3088f05747cff7a914f1" - integrity sha512-d4mzMLkwZarZE9ZDFXQapNba4iHEj6ARveU4qCz7j/T/TlrHJVbyhVRcZigIuiQqgotTWGub5vMCa2/ep+hA+w== - dependencies: - "@babel/runtime" "7.0.0-beta.42" - chalk "2.3.2" - chance "1.0.13" - class-validator "0.8.5" - commander "2.15.1" - escodegen-wallaby "1.6.18" - espree "3.5.4" - estraverse "4.2.0" - inversify "4.11.1" - js-string-escape "1.0.1" - md5 "2.2.1" - mkdirp "0.5.1" - multimatch "2.1.0" - opencollective "1.0.3" - pjson "1.0.9" - reflect-metadata "0.1.12" - source-map-support "0.5.4" - string-template "1.0.0" - tslib "1.9.0" - -jimp@^0.6.1: - version "0.6.8" - resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.6.8.tgz#63074984337cc469cd4030946e503e7c02a18b5c" - integrity sha512-F7emeG7Hp61IM8VFbNvWENLTuHe0ghizWPuP4JS9ujx2r5mCVYEd/zdaz6M2M42ZdN41blxPajLWl9FXo7Mr2Q== - dependencies: - "@jimp/custom" "^0.6.8" - "@jimp/plugins" "^0.6.8" - "@jimp/types" "^0.6.8" - core-js "^2.5.7" - regenerator-runtime "^0.13.3" - -jpeg-js@^0.3.4: - version "0.3.7" - resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.3.7.tgz#471a89d06011640592d314158608690172b1028d" - integrity sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ== - -js-base64@^2.1.9: - version "2.5.2" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209" - integrity sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ== - -js-string-escape@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^3.4.2: - version "3.14.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" - integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= - -json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -json5@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - -json5@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" - integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== - dependencies: - minimist "^1.2.5" - -jsonfile@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" - integrity sha1-pezG9l9T9mLEQVx2daAzHQmS7GY= - optionalDependencies: - graceful-fs "^4.1.6" - -keyv@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" - integrity sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA== - dependencies: - json-buffer "3.0.0" - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -known-css-properties@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.11.0.tgz#0da784f115ea77c76b81536d7052e90ee6c86a8a" - integrity sha512-bEZlJzXo5V/ApNNa5z375mJC6Nrz4vG43UgcSCrg2OHC+yuB6j0iDSrY7RQ/+PRofFB03wNIIt9iXIVLr4wc7w== - -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= - dependencies: - invert-kv "^1.0.0" - -lcid@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" - integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== - dependencies: - invert-kv "^2.0.0" - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levenary@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" - integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== - dependencies: - leven "^3.1.0" - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -limiter@^1.0.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.5.tgz#8f92a25b3b16c6131293a0cc834b4a838a2aa7c2" - integrity sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA== - -load-bmfont@^1.3.1, load-bmfont@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.0.tgz#75f17070b14a8c785fe7f5bee2e6fd4f98093b6b" - integrity sha512-kT63aTAlNhZARowaNYcY29Fn/QYkc52M3l6V1ifRcPewg2lvUZDAj7R6dXjOL9D0sict76op3T5+odumDSF81g== - dependencies: - 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" - -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -loader-runner@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" - integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== - -loader-utils@1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" - integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== - dependencies: - big.js "^5.2.2" - emojis-list "^2.0.0" - json5 "^1.0.1" - -loader-utils@^0.2.5, loader-utils@~0.2.2, loader-utils@~0.2.3, loader-utils@~0.2.5: - version "0.2.17" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" - integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= - dependencies: - big.js "^3.1.3" - emojis-list "^2.0.0" - json5 "^0.5.0" - object-assign "^4.0.1" - -loader-utils@^1.0.0, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^1.0.1" - -localtunnel@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/localtunnel/-/localtunnel-1.9.2.tgz#0012fcabc29cf964c130a01858768aa2bb65b5af" - integrity sha512-NEKF7bDJE9U3xzJu3kbayF0WTvng6Pww7tzqNb/XtEARYwqw7CKEX7BvOMg98FtE9es2CRizl61gkV3hS8dqYg== - dependencies: - axios "0.19.0" - debug "4.1.1" - openurl "1.1.1" - yargs "6.6.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash.clone@^4.3.2: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" - integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y= - -lodash.isfinite@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz#fb89b65a9a80281833f0b7478b3a5104f898ebb3" - integrity sha1-+4m2WpqAKBgz8LdHizpRBPiY67M= - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.some@^4.2.2: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" - integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= - -lodash.template@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" - integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.templatesettings "^4.0.0" - -lodash.templatesettings@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" - integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== - dependencies: - lodash._reinterpolate "^3.0.0" - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.3.0: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -logalot@^2.0.0, logalot@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/logalot/-/logalot-2.1.0.tgz#5f8e8c90d304edf12530951a5554abb8c5e3f552" - integrity sha1-X46MkNME7fElMJUaVVSruMXj9VI= - dependencies: - figures "^1.3.5" - squeak "^1.0.0" - -logrocket@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/logrocket/-/logrocket-1.0.7.tgz#fe17dbdfc861481cd274fbda533d552de7800a3a" - integrity sha512-v6HWEQIsyG+3FkldB7vIAgHh7/qpsiz2Br4bLK5SHBvjqRrHs/Fp+Jr8oiA2GYq0UurAtCu51U8SWft5+OCKtg== - -longest@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= - -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - -lower-case@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" - integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= - -lowercase-keys@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" - integrity sha1-TjNms55/VFfjXxMkvfb4jQv8cwY= - -lowercase-keys@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lpad-align@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/lpad-align/-/lpad-align-1.1.2.tgz#21f600ac1c3095c3c6e497ee67271ee08481fe9e" - integrity sha1-IfYArBwwlcPG5JfuZyce4ISB/p4= - dependencies: - get-stdin "^4.0.1" - indent-string "^2.1.0" - longest "^1.0.0" - meow "^3.3.0" - -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lz-string@^1.4.4: - version "1.4.4" - resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" - integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY= - -make-dir@^1.0.0, make-dir@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== - dependencies: - pify "^3.0.0" - -make-dir@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -map-age-cleaner@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" - integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== - dependencies: - p-defer "^1.0.0" - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-obj@^1.0.0, map-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -markdown-loader@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/markdown-loader/-/markdown-loader-4.0.0.tgz#502eb94f5db1673beb1721bed82dac9e1d333b9a" - integrity sha512-9BCm8iyLF4AVYtjtybOTg8cTcpWYKsDGWWhsc7XaJlXQiddo3ztbZxLPJ28pmCxFI1BlMkT1wDVav1chPjTpdA== - dependencies: - loader-utils "^1.1.0" - marked "^0.5.0" - -marked@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.5.2.tgz#3efdb27b1fd0ecec4f5aba362bddcd18120e5ba9" - integrity sha512-fdZvBa7/vSQIZCi4uuwo2N3q+7jJURpMVCcbaX0S1Mg65WZ5ilXvC67MviJAsdjqqgD+CEq4RKo5AYGgINkVAA== - -match-all@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.5.tgz#f709af311a7cb9ae464d9107a4f0fe08d3326eff" - integrity sha512-KW4trRDMYbVkAKZ1J655vh0931mk3XM1lIJ480TXUL3KBrOsZ6WpryYJELonvtXC1O4erLYB069uHidLkswbjQ== - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -md5@2.2.1, md5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" - integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk= - dependencies: - charenc "~0.0.1" - crypt "~0.0.1" - is-buffer "~1.1.1" - -mdn-data@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" - integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== - -mdn-data@2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978" - integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -mem@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" - integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== - dependencies: - map-age-cleaner "^0.1.1" - mimic-fn "^2.0.0" - p-is-promise "^2.0.0" - -memory-fs@^0.4.0, memory-fs@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -memory-fs@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" - integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -meow@^3.3.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= - dependencies: - camelcase-keys "^2.0.0" - decamelize "^1.1.2" - loud-rejection "^1.0.0" - map-obj "^1.0.1" - minimist "^1.1.3" - normalize-package-data "^2.3.4" - object-assign "^4.0.1" - read-pkg-up "^1.0.1" - redent "^1.0.0" - trim-newlines "^1.0.0" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -mime-db@1.43.0, mime-db@^1.28.0: - version "1.43.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" - integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== - -mime-types@~2.1.17, mime-types@~2.1.24: - version "2.1.26" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" - integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== - dependencies: - mime-db "1.43.0" - -mime@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== - -mime@1.6.0, mime@^1.3.4: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mime@^2.4.0: - version "2.4.4" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" - integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== - -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - -mimic-fn@^2.0.0, mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mimic-response@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -min-document@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= - dependencies: - dom-walk "^0.1.0" - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= - -minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -mississippi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" - integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== - dependencies: - concat-stream "^1.5.0" - duplexify "^3.4.2" - end-of-stream "^1.1.0" - flush-write-stream "^1.0.0" - from2 "^2.1.0" - parallel-transform "^1.1.0" - pump "^3.0.0" - pumpify "^1.3.3" - stream-each "^1.1.0" - through2 "^2.0.0" - -mitt@^1.1.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mitt/-/mitt-1.2.0.tgz#cb24e6569c806e31bd4e3995787fe38a04fdf90d" - integrity sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw== - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -move-concurrently@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" - integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= - dependencies: - aproba "^1.1.1" - copy-concurrently "^1.0.0" - fs-write-stream-atomic "^1.0.8" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.3" - -mozjpeg@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/mozjpeg/-/mozjpeg-6.0.1.tgz#56969dddb5741ef2bcb1af066cae21e61a91a27b" - integrity sha512-9Z59pJMi8ni+IUvSH5xQwK5tNLw7p3dwDNCZ3o1xE+of3G5Hc/yOz6Ue/YuLiBXU3ZB5oaHPURyPdqfBX/QYJA== - dependencies: - bin-build "^3.0.0" - bin-wrapper "^4.0.0" - logalot "^2.1.0" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -multimatch@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= - -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - -nan@^2.12.1: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -neo-async@^2.5.0, neo-async@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -no-case@^2.2.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" - integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== - dependencies: - lower-case "^1.1.1" - -node-fetch@1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" - integrity sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ= - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -node-fetch@^1.6.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -node-libs-browser@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" - integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^3.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.1" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.11.0" - vm-browserify "^1.0.1" - -node-releases@^1.1.53: - version "1.1.53" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4" - integrity sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ== - -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= - -normalize-url@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" - integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw== - dependencies: - prepend-http "^2.0.0" - query-string "^5.0.1" - sort-keys "^2.0.0" - -normalize-url@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" - integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== - -npm-conf@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" - integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw== - dependencies: - config-chain "^1.1.11" - pify "^3.0.0" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - -nth-check@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" - -num2fraction@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -obfuscator-loader@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obfuscator-loader/-/obfuscator-loader-1.1.2.tgz#6e8460066296fc642a68c945e64906e3c964cb0f" - integrity sha512-5PKsa4Vzq8uLJG0GT9BvC9ZxCr44wyV0c9wi782RYWh44GdFMSqlnUldgqSV+HQkFH3MWNc34AlSVSEhg7I26w== - dependencies: - esprima "^4.0.0" - javascript-obfuscator "^0.15.0" - loader-utils "^1.1.0" - -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-component@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" - integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE= - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-inspect@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" - integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== - -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object-path@^0.9.0: - version "0.9.2" - resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.9.2.tgz#0fd9a74fc5fad1ae3968b586bda5c632bd6c05a5" - integrity sha1-D9mnT8X60a45aLWGvaXGMr1sBaU= - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.assign@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - -object.getownpropertydescriptors@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" - integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - -object.values@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" - integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" - has "^1.0.3" - -omggif@^1.0.9: - version "1.0.10" - resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19" - integrity sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw== - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -onesky-fetch@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/onesky-fetch/-/onesky-fetch-0.0.7.tgz#96fce1a258a80683d6a37840958bae2f6fdb2809" - integrity sha1-lvzholioBoPWo3hAlYuuL2/bKAk= - dependencies: - md5 "^2.2.1" - node-fetch "^1.6.3" - -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= - dependencies: - mimic-fn "^1.0.0" - -onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== - dependencies: - mimic-fn "^2.1.0" - -opencollective@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/opencollective/-/opencollective-1.0.3.tgz#aee6372bc28144583690c3ca8daecfc120dd0ef1" - integrity sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE= - dependencies: - babel-polyfill "6.23.0" - chalk "1.1.3" - inquirer "3.0.6" - minimist "1.2.0" - node-fetch "1.6.3" - opn "4.0.2" - -opener@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" - integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== - -openurl@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/openurl/-/openurl-1.1.1.tgz#3875b4b0ef7a52c156f0db41d4609dbb0f94b387" - integrity sha1-OHW0sO96UsFW8NtB1GCduw+Us4c= - -opn@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/opn/-/opn-4.0.2.tgz#7abc22e644dff63b0a96d5ab7f2790c0f01abc95" - integrity sha1-erwi5kTf9jsKltWrfyeQwPAavJU= - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - -opn@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" - integrity sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g== - dependencies: - is-wsl "^1.1.0" - -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= - -os-filter-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/os-filter-obj/-/os-filter-obj-2.0.0.tgz#1c0b62d5f3a2442749a2d139e6dddee6e81d8d16" - integrity sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg== - dependencies: - arch "^2.1.0" - -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= - dependencies: - lcid "^1.0.0" - -os-locale@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" - integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== - dependencies: - execa "^1.0.0" - lcid "^2.0.0" - mem "^4.0.0" - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -ow@^0.13.2: - version "0.13.2" - resolved "https://registry.yarnpkg.com/ow/-/ow-0.13.2.tgz#375e76d3d3f928a8dfcf0cd0b9c921cb62e469a0" - integrity sha512-9wvr+q+ZTDRvXDjL6eDOdFe5WUl/wa5sntf9kAolxqSpkBqaIObwLgFCGXSJASFw+YciXnOVtDWpxXa9cqV94A== - dependencies: - type-fest "^0.5.1" - -p-cancelable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== - -p-cancelable@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" - integrity sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ== - -p-defer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" - integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= - -p-event@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-event/-/p-event-1.3.0.tgz#8e6b4f4f65c72bc5b6fe28b75eda874f96a4a085" - integrity sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU= - dependencies: - p-timeout "^1.1.1" - -p-event@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/p-event/-/p-event-2.3.1.tgz#596279ef169ab2c3e0cae88c1cfbb08079993ef6" - integrity sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA== - dependencies: - p-timeout "^2.0.1" - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -p-is-promise@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" - integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4= - -p-is-promise@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" - integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-map-series@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca" - integrity sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco= - dependencies: - p-reduce "^1.0.0" - -p-reduce@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" - integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= - -p-timeout@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= - dependencies: - p-finally "^1.0.0" - -p-timeout@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" - integrity sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA== - dependencies: - p-finally "^1.0.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -pako@^1.0.5, pako@~1.0.5: - version "1.0.11" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== - -parallel-transform@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" - integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== - dependencies: - cyclist "^1.0.1" - inherits "^2.0.3" - readable-stream "^2.1.5" - -param-case@2.1.x: - version "2.1.1" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" - integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= - dependencies: - no-case "^2.2.0" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-asn1@^5.0.0: - version "5.1.5" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" - integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== - dependencies: - asn1.js "^4.0.0" - browserify-aes "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-bmfont-ascii@^1.0.3: - version "1.0.6" - resolved "https://registry.yarnpkg.com/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz#11ac3c3ff58f7c2020ab22769079108d4dfa0285" - integrity sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU= - -parse-bmfont-binary@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz#d038b476d3e9dd9db1e11a0b0e53a22792b69006" - integrity sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY= - -parse-bmfont-xml@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz#015319797e3e12f9e739c4d513872cd2fa35f389" - integrity sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ== - dependencies: - xml-parse-from-string "^1.0.0" - xml2js "^0.4.5" - -parse-headers@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.3.tgz#5e8e7512383d140ba02f0c7aa9f49b4399c92515" - integrity sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA== - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parse-node-version@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" - integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== - -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= - -parseqs@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" - integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0= - dependencies: - better-assert "~1.0.0" - -parseuri@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" - integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo= - dependencies: - better-assert "~1.0.0" - -parseurl@~1.3.2, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -pbkdf2@^3.0.3: - version "3.0.17" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= - -phin@^2.9.1: - version "2.9.3" - resolved "https://registry.yarnpkg.com/phin/-/phin-2.9.3.tgz#f9b6ac10a035636fb65dfc576aaaa17b8743125c" - integrity sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA== - -phonegap-plugin-mobile-accessibility@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/phonegap-plugin-mobile-accessibility/-/phonegap-plugin-mobile-accessibility-1.0.5.tgz#95a8754d127508bc6e1ae259a53ce765836eac03" - integrity sha1-lah1TRJ1CLxuGuJZpTznZYNurAM= - -pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -pixelmatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-4.0.2.tgz#8f47dcec5011b477b67db03c243bc1f3085e8854" - integrity sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ= - dependencies: - pngjs "^3.0.0" - -pjson@1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/pjson/-/pjson-1.0.9.tgz#8a9520ce76a4739f8fee91679dad6b065b1c7938" - integrity sha512-4hRJH3YzkUpOlShRzhyxAmThSNnAaIlWZCAb27hd0pVUAXNUAHAO7XZbsPPvsCYwBFEScTmCCL6DGE8NyZ8BdQ== - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" - integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= - dependencies: - find-up "^2.1.0" - -plugin-error@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c" - integrity sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA== - dependencies: - ansi-colors "^1.0.1" - arr-diff "^4.0.0" - arr-union "^3.1.0" - extend-shallow "^3.0.2" - -pngjs@^3.0.0, pngjs@^3.3.3: - version "3.4.0" - resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" - integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== - -pngquant-bin@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/pngquant-bin/-/pngquant-bin-5.0.2.tgz#6f34f3e89c9722a72bbc509062b40f1b17cda460" - integrity sha512-OLdT+4JZx5BqE1CFJkrvomYV0aSsv6x2Bba+aWaVc0PMfWlE+ZByNKYAdKeIqsM4uvW1HOSEHnf8KcOnykPNxA== - dependencies: - bin-build "^3.0.0" - bin-wrapper "^4.0.1" - execa "^0.10.0" - logalot "^2.0.0" - -portscanner@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/portscanner/-/portscanner-2.1.1.tgz#eabb409e4de24950f5a2a516d35ae769343fbb96" - integrity sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y= - dependencies: - async "1.5.2" - is-number-like "^1.0.3" - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -postcss-assets@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-assets/-/postcss-assets-5.0.0.tgz#f721d07d339605fb58414e9f69cf05401c54e709" - integrity sha1-9yHQfTOWBftYQU6fac8FQBxU5wk= - dependencies: - assets "^3.0.0" - bluebird "^3.5.0" - postcss "^6.0.10" - postcss-functions "^3.0.0" - -postcss-attribute-case-insensitive@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" - integrity sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^6.0.2" - -postcss-calc@^7.0.1: - version "7.0.2" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.2.tgz#504efcd008ca0273120568b0792b16cdcde8aac1" - integrity sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ== - dependencies: - postcss "^7.0.27" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.0.2" - -postcss-color-functional-notation@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" - integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-color-gray@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" - integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw== - dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.5" - postcss-values-parser "^2.0.0" - -postcss-color-hex-alpha@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" - integrity sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw== - dependencies: - postcss "^7.0.14" - postcss-values-parser "^2.0.1" - -postcss-color-mod-function@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" - integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ== - dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-color-rebeccapurple@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" - integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-colormin@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" - integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== - dependencies: - browserslist "^4.0.0" - color "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-convert-values@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" - integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-custom-media@^7.0.8: - version "7.0.8" - resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" - integrity sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg== - dependencies: - postcss "^7.0.14" - -postcss-custom-properties@^8.0.11: - version "8.0.11" - resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" - integrity sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA== - dependencies: - postcss "^7.0.17" - postcss-values-parser "^2.0.1" - -postcss-custom-selectors@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" - integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-dir-pseudo-class@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2" - integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-discard-comments@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" - integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== - dependencies: - postcss "^7.0.0" - -postcss-discard-duplicates@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" - integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== - dependencies: - postcss "^7.0.0" - -postcss-discard-empty@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" - integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== - dependencies: - postcss "^7.0.0" - -postcss-discard-overridden@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" - integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== - dependencies: - postcss "^7.0.0" - -postcss-discard-unused@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-4.0.1.tgz#ee7cc66af8c7e8c19bd36f12d09c4bde4039abea" - integrity sha512-/3vq4LU0bLH2Lj4NYN7BTf2caly0flUB7Xtrk9a5K3yLuXMkHMqMO/x3sDq8W2b1eQFSCyY0IVz2L+0HP8kUUA== - dependencies: - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - uniqs "^2.0.0" - -postcss-double-position-gradients@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" - integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA== - dependencies: - postcss "^7.0.5" - postcss-values-parser "^2.0.0" - -postcss-env-function@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7" - integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-focus-visible@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" - integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g== - dependencies: - postcss "^7.0.2" - -postcss-focus-within@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680" - integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w== - dependencies: - postcss "^7.0.2" - -postcss-font-variant@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz#71dd3c6c10a0d846c5eda07803439617bbbabacc" - integrity sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg== - dependencies: - postcss "^7.0.2" - -postcss-functions@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-functions/-/postcss-functions-3.0.0.tgz#0e94d01444700a481de20de4d55fb2640564250e" - integrity sha1-DpTQFERwCkgd4g3k1V+yZAVkJQ4= - dependencies: - glob "^7.1.2" - object-assign "^4.1.1" - postcss "^6.0.9" - postcss-value-parser "^3.3.0" - -postcss-gap-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715" - integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg== - dependencies: - postcss "^7.0.2" - -postcss-image-set-function@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288" - integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-initial@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.2.tgz#f018563694b3c16ae8eaabe3c585ac6319637b2d" - integrity sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA== - dependencies: - lodash.template "^4.5.0" - postcss "^7.0.2" - -postcss-lab-function@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e" - integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg== - dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-logical@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5" - integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA== - dependencies: - postcss "^7.0.2" - -postcss-media-minmax@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" - integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw== - dependencies: - postcss "^7.0.2" - -postcss-merge-idents@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-4.0.1.tgz#b7df282a92f052ea0a66c62d8f8812e6d2cbed23" - integrity sha512-43S/VNdF6II0NZ31YxcvNYq4gfURlPAAsJW/z84avBXQCaP4I4qRHUH18slW/SOlJbcxxCobflPNUApYDddS7A== - dependencies: - cssnano-util-same-parent "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-merge-longhand@^4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" - integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== - dependencies: - css-color-names "0.0.4" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - stylehacks "^4.0.0" - -postcss-merge-rules@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" - integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - cssnano-util-same-parent "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - vendors "^1.0.0" - -postcss-minify-font-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" - integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-minify-gradients@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" - integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== - dependencies: - cssnano-util-get-arguments "^4.0.0" - is-color-stop "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-minify-params@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" - integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== - dependencies: - alphanum-sort "^1.0.0" - browserslist "^4.0.0" - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - uniqs "^2.0.0" - -postcss-minify-selectors@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" - integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== - dependencies: - alphanum-sort "^1.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - -postcss-nesting@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" - integrity sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg== - dependencies: - postcss "^7.0.2" - -postcss-normalize-charset@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" - integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== - dependencies: - postcss "^7.0.0" - -postcss-normalize-display-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" - integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-positions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" - integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== - dependencies: - cssnano-util-get-arguments "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-repeat-style@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" - integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== - dependencies: - cssnano-util-get-arguments "^4.0.0" - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-string@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" - integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== - dependencies: - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-timing-functions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" - integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-unicode@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" - integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== - dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-url@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" - integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== - dependencies: - is-absolute-url "^2.0.0" - normalize-url "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-whitespace@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" - integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-ordered-values@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" - integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== - dependencies: - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-overflow-shorthand@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30" - integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g== - dependencies: - postcss "^7.0.2" - -postcss-page-break@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf" - integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ== - dependencies: - postcss "^7.0.2" - -postcss-place@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62" - integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-preset-env@^6.5.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5" - integrity sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg== - dependencies: - autoprefixer "^9.6.1" - browserslist "^4.6.4" - caniuse-lite "^1.0.30000981" - css-blank-pseudo "^0.1.4" - css-has-pseudo "^0.10.0" - css-prefers-color-scheme "^3.1.1" - cssdb "^4.4.0" - postcss "^7.0.17" - postcss-attribute-case-insensitive "^4.0.1" - postcss-color-functional-notation "^2.0.1" - postcss-color-gray "^5.0.0" - postcss-color-hex-alpha "^5.0.3" - postcss-color-mod-function "^3.0.3" - postcss-color-rebeccapurple "^4.0.1" - postcss-custom-media "^7.0.8" - postcss-custom-properties "^8.0.11" - postcss-custom-selectors "^5.1.2" - postcss-dir-pseudo-class "^5.0.0" - postcss-double-position-gradients "^1.0.0" - postcss-env-function "^2.0.2" - postcss-focus-visible "^4.0.0" - postcss-focus-within "^3.0.0" - postcss-font-variant "^4.0.0" - postcss-gap-properties "^2.0.0" - postcss-image-set-function "^3.0.1" - postcss-initial "^3.0.0" - postcss-lab-function "^2.0.1" - postcss-logical "^3.0.0" - postcss-media-minmax "^4.0.0" - postcss-nesting "^7.0.0" - postcss-overflow-shorthand "^2.0.0" - postcss-page-break "^2.0.0" - postcss-place "^4.0.1" - postcss-pseudo-class-any-link "^6.0.0" - postcss-replace-overflow-wrap "^3.0.0" - postcss-selector-matches "^4.0.0" - postcss-selector-not "^4.0.0" - -postcss-pseudo-class-any-link@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" - integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-reduce-idents@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-4.0.2.tgz#30447a6ec20941e78e21bd4482a11f569c4f455b" - integrity sha512-Tz70Ri10TclPoCtFfftjFVddx3fZGUkr0dEDbIEfbYhFUOFQZZ77TEqRrU0e6TvAvF+Wa5VVzYTpFpq0uwFFzw== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-reduce-initial@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" - integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - -postcss-reduce-transforms@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" - integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== - dependencies: - cssnano-util-get-match "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-replace-overflow-wrap@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" - integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw== - dependencies: - postcss "^7.0.2" - -postcss-round-subpixels@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postcss-round-subpixels/-/postcss-round-subpixels-1.2.0.tgz#e21d6ac5952e185f9bdc008b94f004fe509d0a11" - integrity sha1-4h1qxZUuGF+b3ACLlPAE/lCdChE= - dependencies: - postcss "^5.0.2" - postcss-value-parser "^3.1.2" - -postcss-selector-matches@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" - integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.2" - -postcss-selector-not@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz#c68ff7ba96527499e832724a2674d65603b645c0" - integrity sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.2" - -postcss-selector-parser@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" - integrity sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA== - dependencies: - dot-prop "^5.2.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^5.0.0, postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" - integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== - dependencies: - cssesc "^2.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" - integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== - dependencies: - cssesc "^3.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-svgo@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" - integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== - dependencies: - is-svg "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - svgo "^1.0.0" - -postcss-unique-selectors@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" - integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== - dependencies: - alphanum-sort "^1.0.0" - postcss "^7.0.0" - uniqs "^2.0.0" - -postcss-unprefix@^2.1.3: - version "2.1.4" - resolved "https://registry.yarnpkg.com/postcss-unprefix/-/postcss-unprefix-2.1.4.tgz#ab1c038ab77f068799ed36e1cbd997b51e7360a1" - integrity sha512-s+muBiGIMx3RvgPTtPBnSrfvIBHJ2Zx16QZf/VDB/sAxdYP6FIzci8d1gLh0+9psu5W6zVtCbU5micNt6Zh3cg== - dependencies: - autoprefixer "^9.4.3" - known-css-properties "^0.11.0" - normalize-range "^0.1.2" - postcss-selector-parser "^5.0.0" - postcss-value-parser "^3.3.1" - pseudo-classes "^1.0.0" - pseudo-elements "^1.1.0" - -postcss-value-parser@^3.0.0, postcss-value-parser@^3.1.2, postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" - integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== - -postcss-value-parser@^4.0.2, postcss-value-parser@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz#651ff4593aa9eda8d5d0d66593a2417aeaeb325d" - integrity sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg== - -postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" - integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== - dependencies: - flatten "^1.0.2" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-zindex@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-4.0.1.tgz#8db6a4cec3111e5d3fd99ea70abeda61873d10c1" - integrity sha512-d/8BlQcUdEugZNRM9AdCA2V4fqREUtn/wcixLN3L6ITgc2P/FMcVVYz8QZkhItWT9NB5qr8wuN2dJCE4/+dlrA== - dependencies: - has "^1.0.0" - postcss "^7.0.0" - uniqs "^2.0.0" - -postcss@^5.0.2: - version "5.2.18" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" - integrity sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg== - dependencies: - chalk "^1.1.3" - js-base64 "^2.1.9" - source-map "^0.5.6" - supports-color "^3.2.3" - -postcss@^6.0.10, postcss@^6.0.9: - version "6.0.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" - integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.4.0" - -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.27, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.27" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9" - integrity sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ== - dependencies: - chalk "^2.4.2" - source-map "^0.6.1" - supports-color "^6.1.0" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - -prettier@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.4.tgz#2d1bae173e355996ee355ec9830a7a1ee05457ef" - integrity sha512-SVJIQ51spzFDvh4fIbCLvciiDMCrRhlN3mbZvv/+ycjvmF5E73bKdGfU8QDLNmjYJf+lsGnDBC4UUnvTe5OO0w== - -private@^0.1.8, private@~0.1.5: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - -process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -process@~0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" - integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= - -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -promise-inflight@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= - -promise-polyfill@^8.1.0: - version "8.1.3" - resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.1.3.tgz#8c99b3cf53f3a91c68226ffde7bde81d7f904116" - integrity sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g== - -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= - -proxy-addr@~2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" - integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.9.1" - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= - -pseudo-classes@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pseudo-classes/-/pseudo-classes-1.0.0.tgz#60a69b67395c36ff119c4d1c86e1981785206b96" - integrity sha1-YKabZzlcNv8RnE0chuGYF4Uga5Y= - -pseudo-elements@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pseudo-elements/-/pseudo-elements-1.1.0.tgz#9ba6dd8ac3ce1f3d7d36d4355aa3e28d08391f28" - integrity sha1-m6bdisPOHz19NtQ1WqPijQg5Hyg= - -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= - -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -pump@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pumpify@^1.3.3: - version "1.5.1" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" - integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== - dependencies: - duplexify "^3.6.0" - inherits "^2.0.3" - pump "^2.0.0" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^1.2.4: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -q@^1.1.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= - -qs@6.2.3: - version "6.2.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" - integrity sha1-HPyyXBCpsrSDBT/zn138kjOQjP4= - -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - -query-string@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== - dependencies: - decode-uri-component "^0.2.0" - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -query-string@^6.8.1: - version "6.12.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.12.1.tgz#2ae4d272db4fba267141665374e49a1de09e8a7c" - integrity sha512-OHj+zzfRMyj3rmo/6G8a5Ifvw3AleL/EbcHMD27YA31Q+cO5lfmQxECkImuNVjcskLcvBRVHNAB3w6udMs1eAA== - dependencies: - decode-uri-component "^0.2.0" - split-on-first "^1.0.0" - strict-uri-encode "^2.0.0" - -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -range-parser@~1.2.0, range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - -raw-body@^2.3.2: - version "2.4.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" - integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA== - dependencies: - bytes "3.1.0" - http-errors "1.7.3" - iconv-lite "0.4.24" - unpipe "1.0.0" - -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readdirp@^2.1.0, readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -recast@~0.11.12: - version "0.11.23" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3" - integrity sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM= - dependencies: - ast-types "0.9.6" - esprima "~3.1.0" - private "~0.1.5" - source-map "~0.5.0" - -redent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" - integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= - dependencies: - indent-string "^2.1.0" - strip-indent "^1.0.1" - -reflect-metadata@0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.12.tgz#311bf0c6b63cd782f228a81abe146a2bfa9c56f2" - integrity sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A== - -regenerate-unicode-properties@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" - integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== - dependencies: - regenerate "^1.4.0" - -regenerate@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== - -regenerator-runtime@^0.10.0: - version "0.10.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= - -regenerator-runtime@^0.11.0, regenerator-runtime@^0.11.1: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - -regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4: - version "0.13.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" - integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== - -regenerator-transform@^0.14.2: - version "0.14.4" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" - integrity sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw== - dependencies: - "@babel/runtime" "^7.8.4" - private "^0.1.8" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexpp@^3.0.0, regexpp@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== - -regexpu-core@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" - integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.2.0" - regjsgen "^0.5.1" - regjsparser "^0.6.4" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.2.0" - -regjsgen@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" - integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== - -regjsparser@^0.6.4: - version "0.6.4" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" - integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== - dependencies: - jsesc "~0.5.0" - -relateurl@0.2.x: - version "0.2.7" - resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= - dependencies: - is-finite "^1.0.0" - -replace-ext@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -requires-port@1.x.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= - dependencies: - resolve-from "^3.0.0" - -resolve-dir@^1.0.0, resolve-dir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" - integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= - dependencies: - expand-tilde "^2.0.0" - global-modules "^1.0.0" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -resolve@^1.10.0, resolve@^1.3.2: - version "1.15.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" - integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== - dependencies: - path-parse "^1.0.6" - -resp-modifier@6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/resp-modifier/-/resp-modifier-6.0.2.tgz#b124de5c4fbafcba541f48ffa73970f4aa456b4f" - integrity sha1-sSTeXE+6/LpUH0j/pzlw9KpFa08= - dependencies: - debug "^2.2.0" - minimatch "^3.0.2" - -responselike@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -rgb-regex@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" - integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= - -rgba-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" - integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= - -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -rimraf@^2.5.4, rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -run-async@^2.2.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8" - integrity sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg== - dependencies: - is-promise "^2.1.0" - -run-async@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - -run-queue@^1.0.0, run-queue@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" - integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= - dependencies: - aproba "^1.1.1" - -rusha@^0.8.13: - version "0.8.13" - resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.13.tgz#9a084e7b860b17bff3015b92c67a6a336191513a" - integrity sha1-mghOe4YLF7/zAVuSxnpqM2GRUTo= - -rx@4.1.0, rx@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" - integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= - -rxjs@^5.5.6: - version "5.5.12" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc" - integrity sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw== - dependencies: - symbol-observable "1.0.1" - -rxjs@^6.5.3: - version "6.5.5" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" - integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ== - dependencies: - tslib "^1.9.0" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sass-unused@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/sass-unused/-/sass-unused-0.3.0.tgz#69924e4996d6c96840fb3a99e0a0290516811a9f" - integrity sha512-fGNcUpDeSFwnN+BTQ251iM77Py8awPXc96vSE3TpvMcgbC90IrohonRb4oxWX/KzHpezkmUddS8/t04R+yIB8w== - dependencies: - glob "^7.0.5" - gonzales-pe "^4.2.3" - -sax@>=0.6.0, sax@~1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -schema-utils@^0.4.0: - version "0.4.7" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" - integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ== - dependencies: - ajv "^6.1.0" - ajv-keywords "^3.1.0" - -schema-utils@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== - dependencies: - ajv "^6.1.0" - ajv-errors "^1.0.0" - ajv-keywords "^3.1.0" - -schema-utils@^2.6.5: - version "2.6.5" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.5.tgz#c758f0a7e624263073d396e29cd40aa101152d8a" - integrity sha512-5KXuwKziQrTVHh8j/Uxz+QUbxkaLW9X/86NBlx/gnKgtsZA2GIVMUn17qWhRFwF8jdYb3Dig5hRO/W5mZqy6SQ== - dependencies: - ajv "^6.12.0" - ajv-keywords "^3.4.1" - -seek-bzip@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= - dependencies: - commander "~2.8.1" - -semver-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" - integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== - -semver-truncate@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/semver-truncate/-/semver-truncate-1.1.2.tgz#57f41de69707a62709a7e0104ba2117109ea47e8" - integrity sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g= - dependencies: - semver "^5.3.0" - -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - -semver@^7.2.1, semver@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== - -send@0.16.2: - version "0.16.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" - on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.4.0" - -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serialize-error@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-3.0.0.tgz#80100282b09be33c611536f50033481cb9cc87cf" - integrity sha512-+y3nkkG/go1Vdw+2f/+XUXM1DXX1XcxTl99FfiD/OEPUNw4uo0i6FKABfTAN5ZcgGtjTRZcEbxcE/jtXbEY19A== - -serialize-javascript@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" - integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== - -serve-index@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= - dependencies: - accepts "~1.3.4" - batch "0.6.1" - debug "2.6.9" - escape-html "~1.0.3" - http-errors "~1.6.2" - mime-types "~2.1.17" - parseurl "~1.3.2" - -serve-static@1.13.2: - version "1.13.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" - integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.2" - send "0.16.2" - -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - -server-destroy@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/server-destroy/-/server-destroy-1.0.1.tgz#f13bf928e42b9c3e79383e61cc3998b5d14e6cdd" - integrity sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0= - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setimmediate@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== - -simple-swizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= - dependencies: - is-arrayish "^0.3.1" - -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - -sloc@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/sloc/-/sloc-0.2.1.tgz#42ad891e76838c1a22bbd8483468e9d74c7f531e" - integrity sha512-8XJnwCFR4DatLz1s0nGFe6IJPJ+5pjRFhoBuBKq8SLgFI40eD7ak6jOXpzeG0tmIpyOc1zCs9bjKAxMFm1451A== - dependencies: - async "~2.1.4" - cli-table "^0.3.1" - commander "~2.9.0" - readdirp "^2.1.0" - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -socket.io-adapter@~1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz#ab3f0d6f66b8fc7fca3959ab5991f82221789be9" - integrity sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g== - -socket.io-client@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.1.1.tgz#dcb38103436ab4578ddb026638ae2f21b623671f" - integrity sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ== - dependencies: - backo2 "1.0.2" - base64-arraybuffer "0.1.5" - component-bind "1.0.0" - component-emitter "1.2.1" - debug "~3.1.0" - engine.io-client "~3.2.0" - has-binary2 "~1.0.2" - has-cors "1.1.0" - indexof "0.0.1" - object-component "0.0.3" - parseqs "0.0.5" - parseuri "0.0.5" - socket.io-parser "~3.2.0" - to-array "0.1.4" - -socket.io-client@^2.0.4: - version "2.3.0" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.3.0.tgz#14d5ba2e00b9bcd145ae443ab96b3f86cbcc1bb4" - integrity sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA== - dependencies: - backo2 "1.0.2" - base64-arraybuffer "0.1.5" - component-bind "1.0.0" - component-emitter "1.2.1" - debug "~4.1.0" - engine.io-client "~3.4.0" - has-binary2 "~1.0.2" - has-cors "1.1.0" - indexof "0.0.1" - object-component "0.0.3" - parseqs "0.0.5" - parseuri "0.0.5" - socket.io-parser "~3.3.0" - to-array "0.1.4" - -socket.io-parser@~3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077" - integrity sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA== - dependencies: - component-emitter "1.2.1" - debug "~3.1.0" - isarray "2.0.1" - -socket.io-parser@~3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.0.tgz#2b52a96a509fdf31440ba40fed6094c7d4f1262f" - integrity sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng== - dependencies: - component-emitter "1.2.1" - debug "~3.1.0" - isarray "2.0.1" - -socket.io@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.1.tgz#a069c5feabee3e6b214a75b40ce0652e1cfb9980" - integrity sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA== - dependencies: - debug "~3.1.0" - engine.io "~3.2.0" - has-binary2 "~1.0.2" - socket.io-adapter "~1.1.0" - socket.io-client "2.1.1" - socket.io-parser "~3.2.0" - -sort-keys-length@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188" - integrity sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg= - dependencies: - sort-keys "^1.0.0" - -sort-keys@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= - dependencies: - is-plain-obj "^1.0.0" - -sort-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" - integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg= - dependencies: - is-plain-obj "^1.0.0" - -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== - -source-map-resolve@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.4.tgz#54456efa89caa9270af7cd624cc2f123e51fbae8" - integrity sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg== - dependencies: - source-map "^0.6.0" - -source-map-support@~0.5.12: - version "0.5.16" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" - integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - -source-map@^0.5.0, source-map@^0.5.6, source-map@~0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@~0.1.38: - version "0.1.43" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" - integrity sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y= - dependencies: - amdefine ">=0.0.4" - -source-map@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= - dependencies: - amdefine ">=0.0.4" - -spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== - -spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== - -speed-measure-webpack-plugin@^1.3.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.3.tgz#6ff894fc83e8a6310dde3af863a0329cd79da4f5" - integrity sha512-2ljD4Ch/rz2zG3HsLsnPfp23osuPBS0qPuz9sGpkNXTN1Ic4M+W9xB8l8rS8ob2cO4b1L+WTJw/0AJwWYVgcxQ== - dependencies: - chalk "^2.0.1" - -split-on-first@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" - integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -squeak@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/squeak/-/squeak-1.3.0.tgz#33045037b64388b567674b84322a6521073916c3" - integrity sha1-MwRQN7ZDiLVnZ0uEMiplIQc5FsM= - dependencies: - chalk "^1.0.0" - console-stream "^0.1.1" - lpad-align "^1.0.1" - -ssri@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" - integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== - dependencies: - figgy-pudding "^3.5.1" - -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -statuses@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" - integrity sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4= - -statuses@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== - -stream-browserify@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-each@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" - integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== - dependencies: - end-of-stream "^1.1.0" - stream-shift "^1.0.0" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -stream-shift@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" - integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== - -stream-throttle@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/stream-throttle/-/stream-throttle-0.1.3.tgz#add57c8d7cc73a81630d31cd55d3961cfafba9c3" - integrity sha1-rdV8jXzHOoFjDTHNVdOWHPr7qcM= - dependencies: - commander "^2.2.0" - limiter "^1.0.5" - -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - -strict-uri-encode@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" - integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= - -strictdom@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strictdom/-/strictdom-1.0.1.tgz#189de91649f73d44d59b8432efa68ef9d2659460" - integrity sha1-GJ3pFkn3PUTVm4Qy76aO+dJllGA= - -string-replace-webpack-plugin@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz#73c657e759d66cfe80ae1e0cf091aa256d0e715c" - integrity sha1-c8ZX51nWbP6Arh4M8JGqJW0OcVw= - dependencies: - async "~0.2.10" - loader-utils "~0.2.3" - optionalDependencies: - css-loader "^0.9.1" - file-loader "^0.8.1" - style-loader "^0.8.3" - -string-template@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96" - integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y= - -string-width@^1.0.1, string-width@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string-width@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -string.prototype.trimend@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" - integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - -string.prototype.trimleft@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" - integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trimstart "^1.0.0" - -string.prototype.trimright@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" - integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trimend "^1.0.0" - -string.prototype.trimstart@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" - integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - -string_decoder@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-ansi@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" - integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== - dependencies: - ansi-regex "^5.0.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - -strip-dirs@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== - dependencies: - is-natural-number "^4.0.1" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - -strip-indent@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= - dependencies: - get-stdin "^4.0.1" - -strip-json-comments@^3.0.1, strip-json-comments@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180" - integrity sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w== - -strip-outer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" - integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== - dependencies: - escape-string-regexp "^1.0.2" - -style-loader@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.8.3.tgz#f4f92eb7db63768748f15065cd6700f5a1c85357" - integrity sha1-9Pkut9tjdodI8VBlzWcA9aHIU1c= - dependencies: - loader-utils "^0.2.5" - -stylehacks@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" - integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== - dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - -supports-color@6.1.0, supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -supports-color@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= - dependencies: - has-flag "^1.0.0" - -supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" - integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== - dependencies: - has-flag "^4.0.0" - -svgo@^1.0.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" - integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== - dependencies: - chalk "^2.4.1" - coa "^2.0.2" - css-select "^2.0.0" - css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.37" - csso "^4.0.2" - js-yaml "^3.13.1" - mkdirp "~0.5.1" - object.values "^1.1.0" - sax "~1.2.4" - stable "^0.1.8" - unquote "~1.1.1" - util.promisify "~1.0.0" - -symbol-observable@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" - integrity sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ= - -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== - dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" - -tapable@^1.0.0, tapable@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" - integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== - -tar-stream@^1.5.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== - dependencies: - bl "^1.0.0" - buffer-alloc "^1.2.0" - end-of-stream "^1.0.0" - fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.1" - xtend "^4.0.0" - -temp-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" - integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= - -tempfile@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-2.0.0.tgz#6b0446856a9b1114d1856ffcbe509cccb0977265" - integrity sha1-awRGhWqbERTRhW/8vlCczLCXcmU= - dependencies: - temp-dir "^1.0.0" - uuid "^3.0.1" - -terser-webpack-plugin@^1.1.0, terser-webpack-plugin@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" - integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA== - dependencies: - cacache "^12.0.2" - find-cache-dir "^2.1.0" - is-wsl "^1.1.0" - schema-utils "^1.0.0" - serialize-javascript "^2.1.2" - source-map "^0.6.1" - terser "^4.1.2" - webpack-sources "^1.4.0" - worker-farm "^1.7.0" - -terser@^4.1.2: - version "4.6.11" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.11.tgz#12ff99fdd62a26de2a82f508515407eb6ccd8a9f" - integrity sha512-76Ynm7OXUG5xhOpblhytE7X58oeNSmC8xnNhjWVo8CksHit0U0kO4hfNbPrrYwowLWFgM2n9L176VNx2QaHmtA== - dependencies: - commander "^2.20.0" - source-map "~0.6.1" - source-map-support "~0.5.12" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -tfunk@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/tfunk/-/tfunk-3.1.0.tgz#38e4414fc64977d87afdaa72facb6d29f82f7b5b" - integrity sha1-OORBT8ZJd9h6/apy+sttKfgve1s= - dependencies: - chalk "^1.1.1" - object-path "^0.9.0" - -through2@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -through@^2.3.6, through@^2.3.8, through@~2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= - -timed-out@^4.0.0, timed-out@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= - -timers-browserify@^2.0.4: - version "2.0.11" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" - integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== - dependencies: - setimmediate "^1.0.4" - -timm@^1.6.1: - version "1.6.2" - resolved "https://registry.yarnpkg.com/timm/-/timm-1.6.2.tgz#dfd8c6719f7ba1fcfc6295a32670a1c6d166c0bd" - integrity sha512-IH3DYDL1wMUwmIlVmMrmesw5lZD6N+ZOAFWEyLrtpoL9Bcrs9u7M/vyOnHzDD2SMs4irLkVjqxZbHrXStS/Nmw== - -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - -tinycolor2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8" - integrity sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g= - -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -to-array@0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" - integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - -to-buffer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - -trim-newlines@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= - -trim-repeated@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" - integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE= - dependencies: - escape-string-regexp "^1.0.2" - -trim@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= - -tryer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" - integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== - -tslib@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" - integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ== - -tslib@^1.8.1: - version "1.13.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" - integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== - -tslib@^1.9.0: - version "1.11.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" - integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== - -tsutils@^3.17.1: - version "3.17.1" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" - integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== - dependencies: - tslib "^1.8.1" - -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - -type-fest@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" - integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== - -type-fest@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2" - integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - -type-is@~1.6.17, type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -typescript@3.9.3: - version "3.9.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.3.tgz#d3ac8883a97c26139e42df5e93eeece33d610b8a" - integrity sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ== - -ua-parser-js@0.7.17: - version "0.7.17" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" - integrity sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g== - -uglify-js@3.4.x: - version "3.4.10" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f" - integrity sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw== - dependencies: - commander "~2.19.0" - source-map "~0.6.1" - -uglify-template-string-loader@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/uglify-template-string-loader/-/uglify-template-string-loader-1.1.1.tgz#d091d15f66b65f1cae2f4222583009302c86339f" - integrity sha512-EHJx8m0aIHlwX5xlJd2xPYIFvLrPkVK5X8zpVxSNTmu7KoT2eSg1TNlwZS+JS65+dwJXC4rC5mc+F4UVe2rckw== - -ultron@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== - -unbzip2-stream@^1.0.9: - version "1.4.1" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.1.tgz#151b104af853df3efdaa135d8b1eca850a44b426" - integrity sha512-sgDYfSDPMsA4Hr2/w7vOlrJBlwzmyakk1+hW8ObLvxSp0LA36LcL2XItGvOT3OSblohSdevMuT8FQjLsqyy4sA== - dependencies: - buffer "^5.2.1" - through "^2.3.8" - -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== - -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== - dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" - -unicode-match-property-value-ecmascript@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" - integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== - -unicode-property-aliases-ecmascript@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" - integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - -uniqs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= - -unique-filename@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" - integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== - dependencies: - imurmurhash "^0.1.4" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -unquote@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -unused-files-webpack-plugin@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/unused-files-webpack-plugin/-/unused-files-webpack-plugin-3.4.0.tgz#adc67a3b5549d028818d3119cbf2b5c88aea8670" - integrity sha512-cmukKOBdIqaM1pqThY0+jp+mYgCVyzrD8uRbKEucQwIGZcLIRn+gSRiQ7uLjcDd3Zba9NUxVGyYa7lWM4UCGeg== - dependencies: - babel-runtime "^7.0.0-beta.3" - glob-all "^3.1.0" - semver "^5.5.0" - util.promisify "^1.0.0" - warning "^3.0.0" - -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - -upper-case@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" - integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= - -uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== - dependencies: - punycode "^2.1.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= - dependencies: - prepend-http "^1.0.1" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -url-to-options@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -utif@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/utif/-/utif-2.0.1.tgz#9e1582d9bbd20011a6588548ed3266298e711759" - integrity sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg== - dependencies: - pako "^1.0.5" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -util.promisify@^1.0.0, util.promisify@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" - integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.2" - has-symbols "^1.0.1" - object.getownpropertydescriptors "^2.1.0" - -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= - dependencies: - inherits "2.0.1" - -util@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" - integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== - dependencies: - inherits "2.0.3" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@^3.0.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -v8-compile-cache@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" - integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w== - -v8-compile-cache@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" - integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -validator@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-9.2.0.tgz#ad216eed5f37cac31a6fe00ceab1f6b88bded03e" - integrity sha512-6Ij4Eo0KM4LkR0d0IegOwluG5453uqT5QyF5SV5Ezvm8/zmkKI/L4eoraafZGlZPC9guLkwKzgypcw8VGWWnGA== - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -vendors@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" - integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== - -vinyl@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" - integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg== - dependencies: - clone "^2.1.1" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - -vm-browserify@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" - integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== - -warning@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" - integrity sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w= - dependencies: - loose-envify "^1.0.0" - -watchpack@^1.6.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.1.tgz#280da0a8718592174010c078c7585a74cd8cd0e2" - integrity sha512-+IF9hfUFOrYOOaKyfaI7h7dquUIOgyEMoQMLA7OP5FxegKA2+XdXThAZ9TU2kucfhDH7rfMHs1oPYziVGWRnZA== - dependencies: - chokidar "^2.1.8" - graceful-fs "^4.1.2" - neo-async "^2.5.0" - -webpack-bundle-analyzer@^3.0.3: - version "3.7.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.7.0.tgz#84da434e89442899b884d9ad38e466d0db02a56f" - integrity sha512-mETdjZ30a3Yf+NTB/wqTgACK7rAYQl5uxKK0WVTNmF0sM3Uv8s3R58YZMW7Rhu0Lk2Rmuhdj5dcH5Q76zCDVdA== - dependencies: - acorn "^7.1.1" - acorn-walk "^7.1.1" - bfj "^6.1.1" - chalk "^2.4.1" - commander "^2.18.0" - ejs "^2.6.1" - express "^4.16.3" - filesize "^3.6.1" - gzip-size "^5.0.0" - lodash "^4.17.15" - mkdirp "^0.5.1" - opener "^1.5.1" - ws "^6.0.0" - -webpack-cli@^3.1.0: - version "3.3.11" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.11.tgz#3bf21889bf597b5d82c38f215135a411edfdc631" - integrity sha512-dXlfuml7xvAFwYUPsrtQAA9e4DOe58gnzSxhgrO/ZM/gyXTBowrsYeubyN4mqGhYdpXMFNyQ6emjJS9M7OBd4g== - dependencies: - chalk "2.4.2" - cross-spawn "6.0.5" - enhanced-resolve "4.1.0" - findup-sync "3.0.0" - global-modules "2.0.0" - import-local "2.0.0" - interpret "1.2.0" - loader-utils "1.2.3" - supports-color "6.1.0" - v8-compile-cache "2.0.3" - yargs "13.2.4" - -webpack-deep-scope-plugin@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/webpack-deep-scope-plugin/-/webpack-deep-scope-plugin-1.6.2.tgz#131eac79739021e42ebc07066ea8869107f37b85" - integrity sha512-S5ZM1i7oTIVPIS1z/Fu41tqFzaXpy8vZnwEDC9I7NLj5XD8GGrDZbDXtG5FCGkHPGxtAzF4O21DKZZ76vpBGzw== - dependencies: - deep-scope-analyser "^1.7.0" - -webpack-plugin-replace@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/webpack-plugin-replace/-/webpack-plugin-replace-1.2.0.tgz#3f20db96237400433231e35ea76d9be3f7128916" - integrity sha512-1HA3etHpJW55qonJqv84o5w5GY7iqF8fqSHpTWdNwarj1llkkt4jT4QSvYs1hoaU8Lu5akDnq/spHHO5mXwo1w== - -webpack-sources@^1.4.0, webpack-sources@^1.4.1: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack-stream@^5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/webpack-stream/-/webpack-stream-5.2.1.tgz#35c992161399fe8cad9c10d4a5c258f022629b39" - integrity sha512-WvyVU0K1/VB1NZ7JfsaemVdG0PXAQUqbjUNW4A58th4pULvKMQxG+y33HXTL02JvD56ko2Cub+E2NyPwrLBT/A== - dependencies: - fancy-log "^1.3.3" - lodash.clone "^4.3.2" - lodash.some "^4.2.2" - memory-fs "^0.4.1" - plugin-error "^1.0.1" - supports-color "^5.5.0" - through "^2.3.8" - vinyl "^2.1.0" - webpack "^4.26.1" - -webpack-strip-block@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/webpack-strip-block/-/webpack-strip-block-0.2.0.tgz#c60d4a703e0eeee8895e7f1abe9b5fe914681470" - integrity sha1-xg1KcD4O7uiJXn8avptf6RRoFHA= - dependencies: - loader-utils "^1.1.0" - -webpack@^4.26.1, webpack@^4.31.0: - version "4.42.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.42.1.tgz#ae707baf091f5ca3ef9c38b884287cfe8f1983ef" - integrity sha512-SGfYMigqEfdGchGhFFJ9KyRpQKnipvEvjc1TwrXEPCM6H5Wywu10ka8o3KGrMzSMxMQKt8aCHUFh5DaQ9UmyRg== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-module-context" "1.9.0" - "@webassemblyjs/wasm-edit" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - acorn "^6.2.1" - ajv "^6.10.2" - ajv-keywords "^3.4.1" - chrome-trace-event "^1.0.2" - enhanced-resolve "^4.1.0" - eslint-scope "^4.0.3" - json-parse-better-errors "^1.0.2" - loader-runner "^2.4.0" - loader-utils "^1.2.3" - memory-fs "^0.4.1" - micromatch "^3.1.10" - mkdirp "^0.5.3" - neo-async "^2.6.1" - node-libs-browser "^2.2.1" - schema-utils "^1.0.0" - tapable "^1.1.3" - terser-webpack-plugin "^1.4.3" - watchpack "^1.6.0" - webpack-sources "^1.4.1" - -whatwg-fetch@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" - integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== - -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -which@^1.2.14, which@^1.2.9, which@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -window-size@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= - -word-wrap@^1.2.3, word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -worker-farm@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" - integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== - dependencies: - errno "~0.1.7" - -worker-loader@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/worker-loader/-/worker-loader-2.0.0.tgz#45fda3ef76aca815771a89107399ee4119b430ac" - integrity sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw== - dependencies: - loader-utils "^1.0.0" - schema-utils "^0.4.0" - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - -ws@^6.0.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" - integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== - dependencies: - async-limiter "~1.0.0" - -ws@~3.3.1: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== - dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - ultron "~1.1.0" - -ws@~6.1.0: - version "6.1.4" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.4.tgz#5b5c8800afab925e94ccb29d153c8d02c1776ef9" - integrity sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA== - dependencies: - async-limiter "~1.0.0" - -xhr@^2.0.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" - integrity sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ== - dependencies: - global "~4.3.0" - is-function "^1.0.1" - parse-headers "^2.0.0" - xtend "^4.0.0" - -xml-parse-from-string@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" - integrity sha1-qQKekp09vN7RafPG4oI42VpdWig= - -xml2js@^0.4.5: - version "0.4.23" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" - integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - -xmlbuilder@~11.0.0: - version "11.0.1" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" - integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== - -xmlhttprequest-ssl@~1.5.4: - version "1.5.5" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" - integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4= - -xtend@^4.0.0, xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= - -y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yaml-js@^0.1.3: - version "0.1.5" - resolved "https://registry.yarnpkg.com/yaml-js/-/yaml-js-0.1.5.tgz#a01369010b3558d8aaed2394615dfd0780fd8fac" - integrity sha1-oBNpAQs1WNiq7SOUYV39B4D9j6w= - -yaml@^1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" - integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== - -yargs-parser@^13.1.0: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^18.1.1: - version "18.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.2.tgz#2f482bea2136dbde0861683abea7756d30b504f1" - integrity sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^4.1.0, yargs-parser@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" - integrity sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw= - dependencies: - camelcase "^3.0.0" - -yargs@13.2.4: - version "13.2.4" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" - integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - os-locale "^3.1.0" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.0" - -yargs@6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.4.0.tgz#816e1a866d5598ccf34e5596ddce22d92da490d4" - integrity sha1-gW4ahm1VmMzzTlWW3c4i2S2kkNQ= - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - window-size "^0.2.0" - y18n "^3.2.1" - yargs-parser "^4.1.0" - -yargs@6.6.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" - integrity sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg= - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^4.2.0" - -yargs@^15.3.1: - version "15.3.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" - integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.1" - -yauzl@^2.4.2: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - -yawn-yaml@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/yawn-yaml/-/yawn-yaml-1.5.0.tgz#95fba7544d5375fce3dc84514f12218ed0d2ebcb" - integrity sha512-sH2zX9K1QiWhWh9U19pye660qlzrEAd5c4ebw/6lqz17LZw7xYi7nqXlBoVLVtc2FZFXDKiJIsvVcKGYbLVyFQ== - dependencies: - js-yaml "^3.4.2" - lodash "^4.17.11" - yaml-js "^0.1.3" - -yeast@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" - integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== + dependencies: + "@babel/highlight" "^7.8.3" + +"@babel/compat-data@^7.8.6", "@babel/compat-data@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.0.tgz#04815556fc90b0c174abd2c0c1bb966faa036a6c" + integrity sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g== + dependencies: + browserslist "^4.9.1" + invariant "^2.2.4" + semver "^5.5.0" + +"@babel/core@^7.5.4": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" + integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.0" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helpers" "^7.9.0" + "@babel/parser" "^7.9.0" + "@babel/template" "^7.8.6" + "@babel/traverse" "^7.9.0" + "@babel/types" "^7.9.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@^7.9.0", "@babel/generator@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9" + integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ== + dependencies: + "@babel/types" "^7.9.5" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" + integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz#c84097a427a061ac56a1c30ebf54b7b22d241503" + integrity sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-compilation-targets@^7.8.7": + version "7.8.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz#dac1eea159c0e4bd46e309b5a1b04a66b53c1dde" + integrity sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw== + dependencies: + "@babel/compat-data" "^7.8.6" + browserslist "^4.9.1" + invariant "^2.2.4" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/helper-create-regexp-features-plugin@^7.8.3", "@babel/helper-create-regexp-features-plugin@^7.8.8": + version "7.8.8" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" + integrity sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-regex" "^7.8.3" + regexpu-core "^4.7.0" + +"@babel/helper-define-map@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" + integrity sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/types" "^7.8.3" + lodash "^4.17.13" + +"@babel/helper-explode-assignable-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" + integrity sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw== + dependencies: + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-function-name@^7.8.3", "@babel/helper-function-name@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" + integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.9.5" + +"@babel/helper-get-function-arity@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" + integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-hoist-variables@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" + integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-member-expression-to-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" + integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-module-imports@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" + integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-module-transforms@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5" + integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.6" + "@babel/helper-simple-access" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/template" "^7.8.6" + "@babel/types" "^7.9.0" + lodash "^4.17.13" + +"@babel/helper-optimise-call-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" + integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" + integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== + +"@babel/helper-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" + integrity sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ== + dependencies: + lodash "^4.17.13" + +"@babel/helper-remap-async-to-generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" + integrity sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-wrap-function" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-replace-supers@^7.8.3", "@babel/helper-replace-supers@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8" + integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/traverse" "^7.8.6" + "@babel/types" "^7.8.6" + +"@babel/helper-simple-access@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" + integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== + dependencies: + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-split-export-declaration@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" + integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-validator-identifier@^7.9.0", "@babel/helper-validator-identifier@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" + integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== + +"@babel/helper-wrap-function@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" + integrity sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helpers@^7.9.0": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f" + integrity sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA== + dependencies: + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.9.0" + "@babel/types" "^7.9.0" + +"@babel/highlight@^7.8.3": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" + integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ== + dependencies: + "@babel/helper-validator-identifier" "^7.9.0" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.8.6", "@babel/parser@^7.9.0": + version "7.9.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" + integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== + +"@babel/plugin-proposal-async-generator-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" + integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + +"@babel/plugin-proposal-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" + integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + +"@babel/plugin-proposal-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" + integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.0" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" + integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + +"@babel/plugin-proposal-numeric-separator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" + integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + +"@babel/plugin-proposal-object-rest-spread@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz#3fd65911306d8746014ec0d0cf78f0e39a149116" + integrity sha512-VP2oXvAf7KCYTthbUHwBlewbl1Iq059f6seJGsxMizaCdgHIeczOr7FBqELhSqfkIl04Fi8okzWzl63UKbQmmg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.9.5" + +"@babel/plugin-proposal-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" + integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + +"@babel/plugin-proposal-optional-chaining@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" + integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + +"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": + version "7.8.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" + integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.8" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-async-generators@^7.8.0": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-dynamic-import@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-json-strings@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" + integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-object-rest-spread@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" + integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-arrow-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" + integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-async-to-generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" + integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + +"@babel/plugin-transform-block-scoped-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" + integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-block-scoping@^7.4.4", "@babel/plugin-transform-block-scoping@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" + integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + lodash "^4.17.13" + +"@babel/plugin-transform-classes@^7.5.5", "@babel/plugin-transform-classes@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz#800597ddb8aefc2c293ed27459c1fcc935a26c2c" + integrity sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-define-map" "^7.8.3" + "@babel/helper-function-name" "^7.9.5" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.6" + "@babel/helper-split-export-declaration" "^7.8.3" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" + integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-destructuring@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz#72c97cf5f38604aea3abf3b935b0e17b1db76a50" + integrity sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" + integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-duplicate-keys@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" + integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-exponentiation-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" + integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-for-of@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" + integrity sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" + integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" + integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-member-expression-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" + integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-modules-amd@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz#19755ee721912cf5bb04c07d50280af3484efef4" + integrity sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q== + dependencies: + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-commonjs@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz#e3e72f4cbc9b4a260e30be0ea59bdf5a39748940" + integrity sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g== + dependencies: + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-systemjs@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz#e9fd46a296fc91e009b64e07ddaa86d6f0edeb90" + integrity sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ== + dependencies: + "@babel/helper-hoist-variables" "^7.8.3" + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-umd@^7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" + integrity sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ== + dependencies: + "@babel/helper-module-transforms" "^7.9.0" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" + integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + +"@babel/plugin-transform-new-target@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" + integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-object-super@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" + integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795" + integrity sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-property-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" + integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-regenerator@^7.8.7": + version "7.8.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8" + integrity sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA== + dependencies: + regenerator-transform "^0.14.2" + +"@babel/plugin-transform-reserved-words@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" + integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-shorthand-properties@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" + integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" + integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-sticky-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" + integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-regex" "^7.8.3" + +"@babel/plugin-transform-template-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" + integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-typeof-symbol@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" + integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-unicode-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" + integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/preset-env@^7.5.4": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.5.tgz#8ddc76039bc45b774b19e2fc548f6807d8a8919f" + integrity sha512-eWGYeADTlPJH+wq1F0wNfPbVS1w1wtmMJiYk55Td5Yu28AsdR9AsC97sZ0Qq8fHqQuslVSIYSGJMcblr345GfQ== + dependencies: + "@babel/compat-data" "^7.9.0" + "@babel/helper-compilation-targets" "^7.8.7" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-async-generator-functions" "^7.8.3" + "@babel/plugin-proposal-dynamic-import" "^7.8.3" + "@babel/plugin-proposal-json-strings" "^7.8.3" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-proposal-numeric-separator" "^7.8.3" + "@babel/plugin-proposal-object-rest-spread" "^7.9.5" + "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" + "@babel/plugin-proposal-optional-chaining" "^7.9.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.8.3" + "@babel/plugin-transform-async-to-generator" "^7.8.3" + "@babel/plugin-transform-block-scoped-functions" "^7.8.3" + "@babel/plugin-transform-block-scoping" "^7.8.3" + "@babel/plugin-transform-classes" "^7.9.5" + "@babel/plugin-transform-computed-properties" "^7.8.3" + "@babel/plugin-transform-destructuring" "^7.9.5" + "@babel/plugin-transform-dotall-regex" "^7.8.3" + "@babel/plugin-transform-duplicate-keys" "^7.8.3" + "@babel/plugin-transform-exponentiation-operator" "^7.8.3" + "@babel/plugin-transform-for-of" "^7.9.0" + "@babel/plugin-transform-function-name" "^7.8.3" + "@babel/plugin-transform-literals" "^7.8.3" + "@babel/plugin-transform-member-expression-literals" "^7.8.3" + "@babel/plugin-transform-modules-amd" "^7.9.0" + "@babel/plugin-transform-modules-commonjs" "^7.9.0" + "@babel/plugin-transform-modules-systemjs" "^7.9.0" + "@babel/plugin-transform-modules-umd" "^7.9.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" + "@babel/plugin-transform-new-target" "^7.8.3" + "@babel/plugin-transform-object-super" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.9.5" + "@babel/plugin-transform-property-literals" "^7.8.3" + "@babel/plugin-transform-regenerator" "^7.8.7" + "@babel/plugin-transform-reserved-words" "^7.8.3" + "@babel/plugin-transform-shorthand-properties" "^7.8.3" + "@babel/plugin-transform-spread" "^7.8.3" + "@babel/plugin-transform-sticky-regex" "^7.8.3" + "@babel/plugin-transform-template-literals" "^7.8.3" + "@babel/plugin-transform-typeof-symbol" "^7.8.4" + "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.9.5" + browserslist "^4.9.1" + core-js-compat "^3.6.2" + invariant "^2.2.2" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/preset-modules@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" + integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/runtime@^7.8.4": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" + integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/template@^7.8.3", "@babel/template@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" + integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.6" + "@babel/types" "^7.8.6" + +"@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2" + integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.5" + "@babel/helper-function-name" "^7.9.5" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.9.0" + "@babel/types" "^7.9.5" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444" + integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg== + dependencies: + "@babel/helper-validator-identifier" "^7.9.5" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@csstools/convert-colors@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" + integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== + +"@jimp/bmp@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/bmp/-/bmp-0.6.8.tgz#8abbfd9e26ba17a47fab311059ea9f7dd82005b6" + integrity sha512-uxVgSkI62uAzk5ZazYHEHBehow590WAkLKmDXLzkr/XP/Hv2Fx1T4DKwJ/15IY5ktq5VAhAUWGXTyd8KWFsx7w== + dependencies: + "@jimp/utils" "^0.6.8" + bmp-js "^0.1.0" + core-js "^2.5.7" + +"@jimp/core@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/core/-/core-0.6.8.tgz#6a41089792516f6e64a5302d12eb562aa7847c7b" + integrity sha512-JOFqBBcSNiDiMZJFr6OJqC6viXj5NVBQISua0eacoYvo4YJtTajOIxC4MqWyUmGrDpRMZBR8QhSsIOwsFrdROA== + dependencies: + "@jimp/utils" "^0.6.8" + any-base "^1.1.0" + buffer "^5.2.0" + core-js "^2.5.7" + 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@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/custom/-/custom-0.6.8.tgz#0476d7b3f5da3121d98895a2e14f2899e602f2b6" + integrity sha512-FrYlzZRVXP2vuVwd7Nc2dlK+iZk4g6IaT1Ib8Z6vU5Kkwlt83FJIPJ2UUFABf3bF5big0wkk8ZUihWxE4Nzdng== + dependencies: + "@jimp/core" "^0.6.8" + core-js "^2.5.7" + +"@jimp/gif@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/gif/-/gif-0.6.8.tgz#848dd4e6e1a56ca2b3ce528969e44dfa99a53b14" + integrity sha512-yyOlujjQcgz9zkjM5ihZDEppn9d1brJ7jQHP5rAKmqep0G7FU1D0AKcV+Ql18RhuI/CgWs10wAVcrQpmLnu4Yw== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + omggif "^1.0.9" + +"@jimp/jpeg@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/jpeg/-/jpeg-0.6.8.tgz#4cad85a6d1e15759acb56bddef29aa3473859f2c" + integrity sha512-rGtXbYpFXAn471qLpTGvhbBMNHJo5KiufN+vC5AWyufntmkt5f0Ox2Cx4ijuBMDtirZchxbMLtrfGjznS4L/ew== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + jpeg-js "^0.3.4" + +"@jimp/plugin-blit@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-blit/-/plugin-blit-0.6.8.tgz#646ebb631f35afc28c1e8908524bc43d1e9afa3d" + integrity sha512-7Tl6YpKTSpvwQbnGNhsfX2zyl3jRVVopd276Y2hF2zpDz9Bycow7NdfNU/4Nx1jaf96X6uWOtSVINcQ7rGd47w== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-blur@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-blur/-/plugin-blur-0.6.8.tgz#7b753ae94f6099103f57c268c3b2679047eefe95" + integrity sha512-NpZCMKxXHLDQsX9zPlWtpMA660DQStY6/z8ZetyxCDbqrLe9YCXpeR4MNhdJdABIiwTm1W5FyFF4kp81PHJx3Q== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-color@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-color/-/plugin-color-0.6.8.tgz#4101cb1208879b331db6e43ea6b96eaf8dbaedbc" + integrity sha512-jjFyU0zNmGOH2rjzHuOMU4kaia0oo82s/7UYfn5h7OUkmUZTd6Do3ZSK1PiXA7KR+s4B76/Omm6Doh/0SGb7BQ== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + tinycolor2 "^1.4.1" + +"@jimp/plugin-contain@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-contain/-/plugin-contain-0.6.8.tgz#af95d33b63d0478943374ae15dd2607fc69cad14" + integrity sha512-p/P2wCXhAzbmEgXvGsvmxLmbz45feF6VpR4m9suPSOr8PC/i/XvTklTqYEUidYYAft4vHgsYJdS74HKSMnH8lw== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-cover@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-cover/-/plugin-cover-0.6.8.tgz#490e3186627a34d93cc015c4169bac9070d6ad17" + integrity sha512-2PvWgk+PJfRsfWDI1G8Fpjrsu0ZlpNyZxO2+fqWlVo6y/y2gP4v08FqvbkcqSjNlOu2IDWIFXpgyU0sTINWZLg== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-crop@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-crop/-/plugin-crop-0.6.8.tgz#ffec8951a2f3eccad1e3cff9afff5326bd980ce7" + integrity sha512-CbrcpWE2xxPK1n/JoTXzhRUhP4mO07mTWaSavenCg664oQl/9XCtL+A0FekuNHzIvn4myEqvkiTwN7FsbunS/Q== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-displace@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-displace/-/plugin-displace-0.6.8.tgz#89df05ab7daaff6befc190bb8ac54ec8d57e533b" + integrity sha512-RmV2bPxoPE6mrPxtYSPtHxm2cGwBQr5a2p+9gH6SPy+eUMrbGjbvjwKNfXWUYD0leML+Pt5XOmAS9pIROmuruQ== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-dither@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-dither/-/plugin-dither-0.6.8.tgz#17e5b9f56575a871e329fef8b388e614b92d84f8" + integrity sha512-x6V/qjxe+xypjpQm7GbiMNqci1EW5UizrcebOhHr8AHijOEqHd2hjXh5f6QIGfrkTFelc4/jzq1UyCsYntqz9Q== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-flip@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-flip/-/plugin-flip-0.6.8.tgz#153df0c677f79d4078bb9e4c1f2ac392b96dc3a1" + integrity sha512-4il6Da6G39s9MyWBEee4jztEOUGJ40E6OlPjkMrdpDNvge6hYEAB31BczTYBP/CEY74j4LDSoY5LbcU4kv06yA== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-gaussian@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-gaussian/-/plugin-gaussian-0.6.8.tgz#100abc7ae1f19fe9c09ed41625b475aae7c6093c" + integrity sha512-pVOblmjv7stZjsqloi4YzHVwAPXKGdNaHPhp4KP4vj41qtc6Hxd9z/+VWGYRTunMFac84gUToe0UKIXd6GhoKw== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-invert@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-invert/-/plugin-invert-0.6.8.tgz#f40bfaa3b592d21ff14ede0e49aabec88048cad0" + integrity sha512-11zuLiXDHr6tFv4U8aieXqNXQEKbDbSBG/h+X62gGTNFpyn8EVPpncHhOqrAFtZUaPibBqMFlNJ15SzwC7ExsQ== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-mask@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-mask/-/plugin-mask-0.6.8.tgz#e64405f7dacf0672bff74f3b95b724d9ac517f86" + integrity sha512-hZJ0OiKGJyv7hDSATwJDkunB1Ie80xJnONMgpUuUseteK45YeYNBOiZVUe8vum8QI1UwavgBzcvQ9u4fcgXc9g== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-normalize@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-normalize/-/plugin-normalize-0.6.8.tgz#a0180f2b8835e3638cdc5e057b44ac63f60db6ba" + integrity sha512-Q4oYhU+sSyTJI7pMZlg9/mYh68ujLfOxXzQGEXuw0sHGoGQs3B0Jw7jmzGa6pIS06Hup5hD2Zuh1ppvMdjJBfQ== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-print@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-print/-/plugin-print-0.6.8.tgz#66309549e01896473111e3a0ad2cee428638bd6e" + integrity sha512-2aokejGn4Drv1FesnZGqh5KEq0FQtR0drlmtyZrBH+r9cx7hh0Qgf4D1BOTDEgXkfSSngjGRjKKRW/fwOrVXYw== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + load-bmfont "^1.4.0" + +"@jimp/plugin-resize@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-resize/-/plugin-resize-0.6.8.tgz#c26d9a973f7eec51ad9018fcbbac1146f7a73aa0" + integrity sha512-27nPh8L1YWsxtfmV/+Ub5dOTpXyC0HMF2cu52RQSCYxr+Lm1+23dJF70AF1poUbUe+FWXphwuUxQzjBJza9UoA== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-rotate@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-rotate/-/plugin-rotate-0.6.8.tgz#2afda247984eeebed95c1bb1b13ccd3be5973299" + integrity sha512-GbjETvL05BDoLdszNUV4Y0yLkHf177MnqGqilA113LIvx9aD0FtUopGXYfRGVvmtTOTouoaGJUc+K6qngvKxww== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugin-scale@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugin-scale/-/plugin-scale-0.6.8.tgz#5de403345859bb0b30bf3e242dedd8ceb6ecb96c" + integrity sha512-GzIYWR/oCUK2jAwku23zt19V1ssaEU4pL0x2XsLNKuuJEU6DvEytJyTMXCE7OLG/MpDBQcQclJKHgiyQm5gIOQ== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + +"@jimp/plugins@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/plugins/-/plugins-0.6.8.tgz#5618170a986ced1ea795adcd9376122f2543b856" + integrity sha512-fMcTI72Vn/Lz6JftezTURmyP5ml/xGMe0Ljx2KRJ85IWyP33vDmGIUuutFiBEbh2+y7lRT+aTSmjs0QGa/xTmQ== + dependencies: + "@jimp/plugin-blit" "^0.6.8" + "@jimp/plugin-blur" "^0.6.8" + "@jimp/plugin-color" "^0.6.8" + "@jimp/plugin-contain" "^0.6.8" + "@jimp/plugin-cover" "^0.6.8" + "@jimp/plugin-crop" "^0.6.8" + "@jimp/plugin-displace" "^0.6.8" + "@jimp/plugin-dither" "^0.6.8" + "@jimp/plugin-flip" "^0.6.8" + "@jimp/plugin-gaussian" "^0.6.8" + "@jimp/plugin-invert" "^0.6.8" + "@jimp/plugin-mask" "^0.6.8" + "@jimp/plugin-normalize" "^0.6.8" + "@jimp/plugin-print" "^0.6.8" + "@jimp/plugin-resize" "^0.6.8" + "@jimp/plugin-rotate" "^0.6.8" + "@jimp/plugin-scale" "^0.6.8" + core-js "^2.5.7" + timm "^1.6.1" + +"@jimp/png@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/png/-/png-0.6.8.tgz#ee06cf078b381137ec7206c4bb1b4cfcbe15ca6f" + integrity sha512-JHHg/BZ7KDtHQrcG+a7fztw45rdf7okL/YwkN4qU5FH7Fcrp41nX5QnRviDtD9hN+GaNC7kvjvcqRAxW25qjew== + dependencies: + "@jimp/utils" "^0.6.8" + core-js "^2.5.7" + pngjs "^3.3.3" + +"@jimp/tiff@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/tiff/-/tiff-0.6.8.tgz#79bd22ed435edbe29d02a2c8c9bf829f988ebacc" + integrity sha512-iWHbxd+0IKWdJyJ0HhoJCGYmtjPBOusz1z1HT/DnpePs/Lo3TO4d9ALXqYfUkyG74ZK5jULZ69KLtwuhuJz1bg== + dependencies: + core-js "^2.5.7" + utif "^2.0.1" + +"@jimp/types@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/types/-/types-0.6.8.tgz#4510eb635cd00b201745d70e38f791748baa7075" + integrity sha512-vCZ/Cp2osy69VP21XOBACfHI5HeR60Rfd4Jidj4W73UL+HrFWOtyQiJ7hlToyu1vI5mR/NsUQpzyQvz56ADm5A== + dependencies: + "@jimp/bmp" "^0.6.8" + "@jimp/gif" "^0.6.8" + "@jimp/jpeg" "^0.6.8" + "@jimp/png" "^0.6.8" + "@jimp/tiff" "^0.6.8" + core-js "^2.5.7" + timm "^1.6.1" + +"@jimp/utils@^0.6.8": + version "0.6.8" + resolved "https://registry.yarnpkg.com/@jimp/utils/-/utils-0.6.8.tgz#09f794945631173567aa50f72ac28170de58a63d" + integrity sha512-7RDfxQ2C/rarNG9iso5vmnKQbcvlQjBIlF/p7/uYj72WeZgVCB+5t1fFBKJSU4WhniHX4jUMijK+wYGE3Y3bGw== + dependencies: + core-js "^2.5.7" + +"@sindresorhus/is@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" + integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== + +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + +"@types/cordova@^0.0.34": + version "0.0.34" + resolved "https://registry.yarnpkg.com/@types/cordova/-/cordova-0.0.34.tgz#ea7addf74ecec3d7629827a0c39e2c9addc73d04" + integrity sha1-6nrd907Ow9dimCegw54smt3HPQQ= + +"@types/eslint-visitor-keys@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" + integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== + +"@types/filesystem@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/filesystem/-/filesystem-0.0.29.tgz#ee3748eb5be140dcf980c3bd35f11aec5f7a3748" + integrity sha512-85/1KfRedmfPGsbK8YzeaQUyV1FQAvMPMTuWFQ5EkLd2w7szhNO96bk3Rh/SKmOfd9co2rCLf0Voy4o7ECBOvw== + dependencies: + "@types/filewriter" "*" + +"@types/filewriter@*": + version "0.0.28" + resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.28.tgz#c054e8af4d9dd75db4e63abc76f885168714d4b3" + integrity sha1-wFTor02d11205jq8dviFFocU1LM= + +"@types/json-schema@^7.0.3": + version "7.0.4" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" + integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== + +"@types/q@^1.5.1": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" + integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== + +"@typescript-eslint/eslint-plugin@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.0.1.tgz#368fe7d4c3d927e9fd27b7ba150b4b7e83ddfabe" + integrity sha512-RxGldRQD3hgOK2xtBfNfA5MMV3rn5gVChe+MIf14hKm51jO2urqF64xOyVrGtzThkrd4rS1Kihqx2nkSxkXHvA== + dependencies: + "@typescript-eslint/experimental-utils" "3.0.1" + functional-red-black-tree "^1.0.1" + regexpp "^3.0.0" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/experimental-utils@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.0.1.tgz#e2721c970068fabd6621709234809c98cd3343ad" + integrity sha512-GdwOVz80MOWxbc/br1DC30eeqlxfpVzexHgHtf3L0hcbOu1xAs1wSCNcaBTLMOMZbh1gj/cKZt0eB207FxWfFA== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "3.0.1" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/parser@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.0.1.tgz#f5163e3a789422f5c62f4daf822bfa03b7e4472d" + integrity sha512-Pn2tDmOc4Ri93VQnT70W0pqQr6i/pEZqIPXfWXm4RuiIprL0t6SG13ViVXHgfScknL2Fm2G4IqXhUzxSRCWXCw== + dependencies: + "@types/eslint-visitor-keys" "^1.0.0" + "@typescript-eslint/experimental-utils" "3.0.1" + "@typescript-eslint/typescript-estree" "3.0.1" + eslint-visitor-keys "^1.1.0" + +"@typescript-eslint/typescript-estree@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.0.1.tgz#8c0cfb7cda64bd6f54185a7b7d1923d25d36b2a8" + integrity sha512-FrbMdgVCeIGHKaP9OYTttFTlF8Ds7AkjMca2GzYCE7pVch10PAJc1mmAFt+DfQPgu/2TrLAprg2vI0PK/WTdcg== + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" + +"@webassemblyjs/ast@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== + dependencies: + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + +"@webassemblyjs/floating-point-hex-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== + +"@webassemblyjs/helper-api-error@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== + +"@webassemblyjs/helper-buffer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== + +"@webassemblyjs/helper-code-frame@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== + dependencies: + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/helper-fsm@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== + +"@webassemblyjs/helper-module-context@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== + dependencies: + "@webassemblyjs/ast" "1.9.0" + +"@webassemblyjs/helper-wasm-bytecode@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== + +"@webassemblyjs/helper-wasm-section@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + +"@webassemblyjs/ieee754@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" + integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" + integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== + +"@webassemblyjs/wasm-edit@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/helper-wasm-section" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-opt" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/wasm-gen@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wasm-opt@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + +"@webassemblyjs/wasm-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" + +"@webassemblyjs/wast-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/floating-point-hex-parser" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-code-frame" "1.9.0" + "@webassemblyjs/helper-fsm" "1.9.0" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/wast-printer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" + integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + "@xtuc/long" "4.2.2" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +accepts@~1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + dependencies: + mime-types "~2.1.24" + negotiator "0.6.2" + +acorn-jsx@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" + integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== + +acorn-walk@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.1.1.tgz#345f0dffad5c735e7373d2fec9a1023e6a44b83e" + integrity sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ== + +acorn@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" + integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== + +acorn@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" + integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== + +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== + +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.1.tgz#b83ca89c5d42d69031f424cad49aada0236c6957" + integrity sha512-KWcq3xN8fDjSB+IMoh2VaXVhRI0BBGxoYp3rx7Pkb6z0cFjYR9Q9l4yZqqals0/zsioCmocC5H6UvsGD4MoIBA== + +ajv@^6.1.0: + version "6.12.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" + integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^6.10.0: + version "6.12.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" + integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^6.10.2, ajv@^6.12.0: + version "6.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7" + integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +alphanum-sort@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" + integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= + +ansi-escapes@^4.2.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" + integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== + dependencies: + type-fest "^0.11.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + +any-base@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/any-base/-/any-base-1.1.0.tgz#ae101a62bc08a597b4c9ab5b7089d456630549fe" + integrity sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg== + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +aproba@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +arch@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e" + integrity sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg== + +archive-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/archive-type/-/archive-type-4.0.0.tgz#f92e72233056dfc6969472749c267bdb046b1d70" + integrity sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA= + dependencies: + file-type "^4.2.0" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +asn1.js@^4.0.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +assert@^1.1.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + dependencies: + object-assign "^4.1.1" + util "0.10.3" + +assets@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/assets/-/assets-3.0.1.tgz#7a69f4bcc3aca9702760e2a73a7e76ca93e9e3e0" + integrity sha512-fTyLNf/9V24y5zO83f4DAEuvaKj7MWBixbnqdZneAhsv1r21yQ/6ogZfvXHmphJAHsz4DhuOwHeJKVbGqqvk0Q== + dependencies: + async "^2.5.0" + bluebird "^3.4.6" + calipers "^2.0.0" + calipers-gif "^2.0.0" + calipers-jpeg "^2.0.0" + calipers-png "^2.0.0" + calipers-svg "^2.0.0" + calipers-webp "^2.0.0" + glob "^7.0.6" + lodash "^4.15.0" + mime "^2.4.0" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +ast-types@0.9.6: + version "0.9.6" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9" + integrity sha1-ECyenpAF0+fjgpvwxPok7oYu6bk= + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async@^2.5.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + dependencies: + lodash "^4.17.14" + +async@~0.2.10: + version "0.2.10" + resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" + integrity sha1-trvgsGdLnXGXCMo43owjfLUmw9E= + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +autoprefixer@^9.4.3, autoprefixer@^9.4.7, autoprefixer@^9.6.1: + version "9.7.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.6.tgz#63ac5bbc0ce7934e6997207d5bb00d68fa8293a4" + integrity sha512-F7cYpbN7uVVhACZTeeIeealwdGM6wMtfWARVLTy5xmKtgVdBNJvbDRoCK3YO1orcs7gv/KwYlb3iXwu9Ug9BkQ== + dependencies: + browserslist "^4.11.1" + caniuse-lite "^1.0.30001039" + chalk "^2.4.2" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^7.0.27" + postcss-value-parser "^4.0.3" + +babel-loader@^8.0.4: + version "8.1.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" + integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw== + dependencies: + find-cache-dir "^2.1.0" + loader-utils "^1.4.0" + mkdirp "^0.5.3" + pify "^4.0.1" + schema-utils "^2.6.5" + +babel-plugin-closure-elimination@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-closure-elimination/-/babel-plugin-closure-elimination-1.3.0.tgz#3217fbf6d416dfdf14ff41a8a34e4d0a6bfc22b2" + integrity sha512-ClKuSxKLLNhe69bvTMuONDI0dQDW49lXB2qtQyyKCzvwegRGel/q4/e+1EoDNDN97Hf1QkxGMbzpAGPmU4Tfjw== + +babel-plugin-console-source@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/babel-plugin-console-source/-/babel-plugin-console-source-2.0.4.tgz#263985b1d69b68e463358d087fa877dd967c5f41" + integrity sha512-OGhrdhuMjiEW0Ma0P9e2B4dFddCpJ/xN/RRaM/4wwDLl+6ZKf+Xd77FtVjpNeDzNRNk8wjRdStA4hpZizXzl1g== + +babel-plugin-danger-remove-unused-import@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/babel-plugin-danger-remove-unused-import/-/babel-plugin-danger-remove-unused-import-1.1.2.tgz#ac39c30edfe524ef8cfc411fec5edc479d19e132" + integrity sha512-3bNmVAaakP3b1aROj7O3bOWj2kBa85sZR5naZ3Rn8L9buiZaAyZLgjfrPDL3zhX4wySOA5jrTm/wSmJPsMm3cg== + +babel-plugin-dynamic-import-node@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" + integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== + dependencies: + object.assign "^4.1.0" + +babel-runtime@^7.0.0-beta.3: + version "7.0.0-beta.3" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-7.0.0-beta.3.tgz#7c750de5514452c27612172506b49085a4a630f2" + integrity sha512-jlzZ8RACjt0QGxq+wqsw5bCQE9RcUyWpw987mDY3GYxTpOQT2xoyNoG++oVCHzr/nACLBIprfVBNvv/If1ZYcg== + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base64-js@^1.0.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" + integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bfj@^6.1.1: + version "6.1.2" + resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.2.tgz#325c861a822bcb358a41c78a33b8e6e2086dde7f" + integrity sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw== + dependencies: + bluebird "^3.5.5" + check-types "^8.0.3" + hoopy "^0.1.4" + tryer "^1.0.1" + +big.js@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" + integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +bin-build@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bin-build/-/bin-build-3.0.0.tgz#c5780a25a8a9f966d8244217e6c1f5082a143861" + integrity sha512-jcUOof71/TNAI2uM5uoUaDq2ePcVBQ3R/qhxAz1rX7UfvduAL/RXD3jXzvn8cVcDJdGVkiR1shal3OH0ImpuhA== + dependencies: + decompress "^4.0.0" + download "^6.2.2" + execa "^0.7.0" + p-map-series "^1.0.0" + tempfile "^2.0.0" + +bin-check@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bin-check/-/bin-check-4.1.0.tgz#fc495970bdc88bb1d5a35fc17e65c4a149fc4a49" + integrity sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA== + dependencies: + execa "^0.7.0" + executable "^4.1.0" + +bin-version-check@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/bin-version-check/-/bin-version-check-4.0.0.tgz#7d819c62496991f80d893e6e02a3032361608f71" + integrity sha512-sR631OrhC+1f8Cvs8WyVWOA33Y8tgwjETNPyyD/myRBXLkfS/vl74FmH/lFcRl9KY3zwGh7jFhvyk9vV3/3ilQ== + dependencies: + bin-version "^3.0.0" + semver "^5.6.0" + semver-truncate "^1.1.2" + +bin-version@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bin-version/-/bin-version-3.1.0.tgz#5b09eb280752b1bd28f0c9db3f96f2f43b6c0839" + integrity sha512-Mkfm4iE1VFt4xd4vH+gx+0/71esbfus2LsnCGe8Pi4mndSPyT+NGES/Eg99jx8/lUGWfu3z2yuB/bt5UB+iVbQ== + dependencies: + execa "^1.0.0" + find-versions "^3.0.0" + +bin-wrapper@^4.0.0, bin-wrapper@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bin-wrapper/-/bin-wrapper-4.1.0.tgz#99348f2cf85031e3ef7efce7e5300aeaae960605" + integrity sha512-hfRmo7hWIXPkbpi0ZltboCMVrU+0ClXR/JgbCKKjlDjQf6igXa7OwdqNcFWQZPZTgiY7ZpzE3+LjjkLiTN2T7Q== + dependencies: + bin-check "^4.1.0" + bin-version-check "^4.0.0" + download "^7.1.0" + import-lazy "^3.1.0" + os-filter-obj "^2.0.0" + pify "^4.0.1" + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +binary-extensions@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" + integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bl@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" + integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +bluebird@3.x.x, bluebird@^3.4.6, bluebird@^3.5.0, bluebird@^3.5.5: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +bmp-js@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.1.0.tgz#e05a63f796a6c1ff25f4771ec7adadc148c07233" + integrity sha1-4Fpj95amwf8l9Hcex62twUjAcjM= + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: + version "4.11.9" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" + integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== + +bn.js@^5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.2.tgz#c9686902d3c9a27729f43ab10f9d79c2004da7b0" + integrity sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA== + +body-parser@1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + dependencies: + bytes "3.1.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.7.2" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.7.0" + raw-body "2.4.0" + type-is "~1.6.17" + +boolbase@^1.0.0, boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.0.tgz#545d0b1b07e6b2c99211082bf1b12cce7a0b0e11" + integrity sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.2" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +browserslist@^4.0.0, browserslist@^4.11.1, browserslist@^4.6.4, browserslist@^4.8.5, browserslist@^4.9.1: + version "4.11.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.11.1.tgz#92f855ee88d6e050e7e7311d987992014f1a1f1b" + integrity sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g== + dependencies: + caniuse-lite "^1.0.30001038" + electron-to-chromium "^1.3.390" + node-releases "^1.1.53" + pkg-up "^2.0.0" + +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= + +buffer-equal@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" + integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs= + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@^4.3.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +buffer@^5.1.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" + integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + +buffer@^5.2.0, buffer@^5.2.1: + version "5.5.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.5.0.tgz#9c3caa3d623c33dd1c7ef584b89b88bf9c9bc1ce" + integrity sha512-9FTEDjLjwoAkEwyMGDjYJQN2gfRgOKBKRfiglhvibGbpeeU/pQn1bJxQqm32OD/AIeEuHxU9roxXxg34Byp/Ww== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + +cacache@^12.0.2: + version "12.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" + integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== + dependencies: + bluebird "^3.5.5" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.4" + graceful-fs "^4.1.15" + infer-owner "^1.0.3" + lru-cache "^5.1.1" + mississippi "^3.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.3" + ssri "^6.0.1" + unique-filename "^1.1.1" + y18n "^4.0.0" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cacheable-request@^2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" + integrity sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0= + dependencies: + clone-response "1.0.2" + get-stream "3.0.0" + http-cache-semantics "3.8.1" + keyv "3.0.0" + lowercase-keys "1.0.0" + normalize-url "2.0.1" + responselike "1.0.2" + +calipers-gif@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/calipers-gif/-/calipers-gif-2.0.0.tgz#b5eefec3064a77c6dcdbd5bdc51735a01bafdc37" + integrity sha1-te7+wwZKd8bc29W9xRc1oBuv3Dc= + dependencies: + bluebird "3.x.x" + +calipers-jpeg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/calipers-jpeg/-/calipers-jpeg-2.0.0.tgz#06d56a53f62717dd809cb956cf64423ce693465b" + integrity sha1-BtVqU/YnF92AnLlWz2RCPOaTRls= + dependencies: + bluebird "3.x.x" + +calipers-png@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/calipers-png/-/calipers-png-2.0.0.tgz#1d0d20e5c1ae5f79b74d5286a2e97f59bb70b658" + integrity sha1-HQ0g5cGuX3m3TVKGoul/Wbtwtlg= + dependencies: + bluebird "3.x.x" + +calipers-svg@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/calipers-svg/-/calipers-svg-2.0.1.tgz#cd9eaa58ef7428c1a14f5da57e56715fb60f6541" + integrity sha512-3PROqHARmj8wWudUC7DzXm1+mSocqgY7jNuehFNHgrUVrKf8o7MqDjS92vJz5LvZsAofJsoAFMajkqwbxBROSQ== + dependencies: + bluebird "3.x.x" + +calipers-webp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/calipers-webp/-/calipers-webp-2.0.0.tgz#e126ece2f84cd71779612bfa2b2653cd95cea77a" + integrity sha1-4Sbs4vhM1xd5YSv6KyZTzZXOp3o= + dependencies: + bluebird "3.x.x" + +calipers@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/calipers/-/calipers-2.0.1.tgz#0d3f303ce75ec5f1eda7fecfc7dba6736e35c926" + integrity sha512-AP4Ui2Z8fZf69d8Dx4cfJgPjQHY3m+QXGFCaAGu8pfNQjyajkosS+Kkf1n6pQDMZcelN5h3MdcjweUqxcsS4pg== + dependencies: + bluebird "3.x.x" + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camel-case@3.0.x: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" + integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= + dependencies: + no-case "^2.2.0" + upper-case "^1.1.1" + +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001038, caniuse-lite@^1.0.30001039: + version "1.0.30001041" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001041.tgz#c2ea138dafc6fe03877921ddcddd4a02a14daf76" + integrity sha512-fqDtRCApddNrQuBxBS7kEiSGdBsgO4wiVw4G/IClfqzfhW45MbTumfN4cuUJGTM0YGFNn97DCXPJ683PS6zwvA== + +caw@^2.0.0, caw@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95" + integrity sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA== + dependencies: + get-proxy "^2.0.0" + isurl "^1.0.0-alpha5" + tunnel-agent "^0.6.0" + url-to-options "^1.0.1" + +chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^1.0.0, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.0.0.tgz#6e98081ed2d17faab615eb52ac66ec1fe6209e72" + integrity sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +check-types@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552" + integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ== + +chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + optionalDependencies: + fsevents "^1.2.7" + +chokidar@^3.4.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.1.tgz#e905bdecf10eaa0a0b1db0c664481cc4cbc22ba1" + integrity sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.4.0" + optionalDependencies: + fsevents "~2.1.2" + +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chrome-trace-event@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" + integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== + dependencies: + tslib "^1.9.0" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +circular-dependency-plugin@^5.0.2: + version "5.2.0" + resolved "https://registry.yarnpkg.com/circular-dependency-plugin/-/circular-dependency-plugin-5.2.0.tgz#e09dbc2dd3e2928442403e2d45b41cea06bc0a93" + integrity sha512-7p4Kn/gffhQaavNfyDFg7LS5S/UT1JAjyGd4UqR2+jzoYF02eDkj0Ec3+48TsIa4zghjLY87nQHIh/ecK9qLdw== + +circular-json@^0.5.9: + version "0.5.9" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.9.tgz#932763ae88f4f7dead7a0d09c8a51a4743a53b1d" + integrity sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +clean-css@4.2.x: + version "4.2.3" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" + integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== + dependencies: + source-map "~0.6.0" + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + +clipboard-copy@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/clipboard-copy/-/clipboard-copy-3.1.0.tgz#4c59030a43d4988990564a664baeafba99f78ca4" + integrity sha512-Xsu1NddBXB89IUauda5BIq3Zq73UWkjkaQlPQbLNvNsd5WBMnTWPNKYR6HGaySOxGYZ+BKxP2E9X4ElnI3yiPA== + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +clone-response@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +coa@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== + dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" + q "^1.1.2" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0, color-convert@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@^1.0.0, color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-string@^1.5.2: + version "1.5.3" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" + integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" + integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + +colors@^1.3.3: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +commander@2.17.x: + version "2.17.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" + integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== + +commander@^2.18.0, commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@~2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== + +commander@~2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" + integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= + dependencies: + graceful-readlink ">= 1.0.0" + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.5.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +config-chain@^1.1.11: + version "1.1.12" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" + integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +console-browserify@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + +console-stream@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/console-stream/-/console-stream-0.1.1.tgz#a095fe07b20465955f2fafd28b5d72bccd949d44" + integrity sha1-oJX+B7IEZZVfL6/Si11yvM2UnUQ= + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + +content-disposition@0.5.3, content-disposition@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + dependencies: + safe-buffer "5.1.2" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + +cookie@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" + integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== + dependencies: + aproba "^1.1.1" + fs-write-stream-atomic "^1.0.8" + iferr "^0.1.5" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.0" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js-compat@^3.6.2: + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" + integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng== + dependencies: + browserslist "^4.8.5" + semver "7.0.0" + +core-js@3: + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" + integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== + +core-js@^2.4.0, core-js@^2.5.7: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +cosmiconfig@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +crc@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6" + integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ== + dependencies: + buffer "^5.1.0" + +create-ecdh@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-spawn@6.0.5, cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +css-blank-pseudo@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" + integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w== + dependencies: + postcss "^7.0.5" + +css-color-names@0.0.4, css-color-names@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= + +css-declaration-sorter@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" + integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== + dependencies: + postcss "^7.0.1" + timsort "^0.3.0" + +css-has-pseudo@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee" + integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ== + dependencies: + postcss "^7.0.6" + postcss-selector-parser "^5.0.0-rc.4" + +css-loader@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.9.1.tgz#2e1aa00ce7e30ef2c6a7a4b300a080a7c979e0dc" + integrity sha1-LhqgDOfjDvLGp6SzAKCAp8l54Nw= + dependencies: + csso "1.3.x" + loader-utils "~0.2.2" + source-map "~0.1.38" + +css-mqpacker@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/css-mqpacker/-/css-mqpacker-7.0.0.tgz#48f4a0ff45b81ec661c4a33ed80b9db8a026333b" + integrity sha512-temVrWS+sB4uocE2quhW8ru/KguDmGhCU7zN213KxtDvWOH3WS/ZUStfpF4fdCT7W8fPpFrQdWRFqtFtPPfBLA== + dependencies: + minimist "^1.2.0" + postcss "^7.0.0" + +css-prefers-color-scheme@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" + integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg== + dependencies: + postcss "^7.0.5" + +css-select-base-adapter@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== + +css-select@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" + integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== + dependencies: + boolbase "^1.0.0" + css-what "^3.2.1" + domutils "^1.7.0" + nth-check "^1.0.2" + +css-tree@1.0.0-alpha.37: + version "1.0.0-alpha.37" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" + integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== + dependencies: + mdn-data "2.0.4" + source-map "^0.6.1" + +css-tree@1.0.0-alpha.39: + version "1.0.0-alpha.39" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb" + integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA== + dependencies: + mdn-data "2.0.6" + source-map "^0.6.1" + +css-what@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" + integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== + +cssdb@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" + integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ== + +cssesc@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" + integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +cssnano-preset-advanced@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-4.0.7.tgz#d981527b77712e2f3f3f09c73313e9b71b278b88" + integrity sha512-j1O5/DQnaAqEyFFQfC+Z/vRlLXL3LxJHN+lvsfYqr7KgPH74t69+Rsy2yXkovWNaJjZYBpdz2Fj8ab2nH7pZXw== + dependencies: + autoprefixer "^9.4.7" + cssnano-preset-default "^4.0.7" + postcss-discard-unused "^4.0.1" + postcss-merge-idents "^4.0.1" + postcss-reduce-idents "^4.0.2" + postcss-zindex "^4.0.1" + +cssnano-preset-default@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" + integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== + dependencies: + css-declaration-sorter "^4.0.1" + cssnano-util-raw-cache "^4.0.1" + postcss "^7.0.0" + postcss-calc "^7.0.1" + postcss-colormin "^4.0.3" + postcss-convert-values "^4.0.1" + postcss-discard-comments "^4.0.2" + postcss-discard-duplicates "^4.0.2" + postcss-discard-empty "^4.0.1" + postcss-discard-overridden "^4.0.1" + postcss-merge-longhand "^4.0.11" + postcss-merge-rules "^4.0.3" + postcss-minify-font-values "^4.0.2" + postcss-minify-gradients "^4.0.2" + postcss-minify-params "^4.0.2" + postcss-minify-selectors "^4.0.2" + postcss-normalize-charset "^4.0.1" + postcss-normalize-display-values "^4.0.2" + postcss-normalize-positions "^4.0.2" + postcss-normalize-repeat-style "^4.0.2" + postcss-normalize-string "^4.0.2" + postcss-normalize-timing-functions "^4.0.2" + postcss-normalize-unicode "^4.0.1" + postcss-normalize-url "^4.0.1" + postcss-normalize-whitespace "^4.0.2" + postcss-ordered-values "^4.1.2" + postcss-reduce-initial "^4.0.3" + postcss-reduce-transforms "^4.0.2" + postcss-svgo "^4.0.2" + postcss-unique-selectors "^4.0.1" + +cssnano-util-get-arguments@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" + integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= + +cssnano-util-get-match@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" + integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= + +cssnano-util-raw-cache@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" + integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== + dependencies: + postcss "^7.0.0" + +cssnano-util-same-parent@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" + integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== + +cssnano@^4.1.10: + version "4.1.10" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" + integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== + dependencies: + cosmiconfig "^5.0.0" + cssnano-preset-default "^4.0.7" + is-resolvable "^1.0.0" + postcss "^7.0.0" + +csso@1.3.x: + version "1.3.12" + resolved "https://registry.yarnpkg.com/csso/-/csso-1.3.12.tgz#fc628694a2d38938aaac4996753218fd311cdb9e" + integrity sha1-/GKGlKLTiTiqrEmWdTIY/TEc254= + +csso@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.3.tgz#0d9985dc852c7cc2b2cacfbbe1079014d1a8e903" + integrity sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ== + dependencies: + css-tree "1.0.0-alpha.39" + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= + dependencies: + array-find-index "^1.0.1" + +cyclist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= + +debounce-promise@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/debounce-promise/-/debounce-promise-3.1.2.tgz#320fb8c7d15a344455cd33cee5ab63530b6dc7c5" + integrity sha512-rZHcgBkbYavBeD9ej6sP56XfG53d51CD4dnaw989YX/nZ/ZJfgRx/9ePKmTNiUiyQvh4mtrMoS3OAWW+yoYtpg== + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +decamelize@^1.1.2, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +decompress-response@^3.2.0, decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" + integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== + dependencies: + file-type "^5.2.0" + is-stream "^1.1.0" + tar-stream "^1.5.2" + +decompress-tarbz2@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" + integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== + dependencies: + decompress-tar "^4.1.0" + file-type "^6.1.0" + is-stream "^1.1.0" + seek-bzip "^1.0.5" + unbzip2-stream "^1.0.9" + +decompress-targz@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" + integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== + dependencies: + decompress-tar "^4.1.1" + file-type "^5.2.0" + is-stream "^1.1.0" + +decompress-unzip@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" + integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= + dependencies: + file-type "^3.8.0" + get-stream "^2.2.0" + pify "^2.3.0" + yauzl "^2.4.2" + +decompress@^4.0.0, decompress@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118" + integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ== + dependencies: + decompress-tar "^4.0.0" + decompress-tarbz2 "^4.0.0" + decompress-targz "^4.0.0" + decompress-unzip "^4.0.1" + graceful-fs "^4.1.10" + make-dir "^1.0.0" + pify "^2.3.0" + strip-dirs "^2.0.0" + +deep-is@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +deep-scope-analyser@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/deep-scope-analyser/-/deep-scope-analyser-1.7.0.tgz#23015b3a1d23181b1d9cebd25b783a7378ead8da" + integrity sha512-rl5Dmt2IZkFpZo6XbEY1zG8st2Wpq8Pi/dV2gz8ZF6BDYt3fnor2JNxHwdO1WLo0k6JbmYp0x8MNy8kE4l1NtA== + dependencies: + esrecurse "^4.2.1" + estraverse "^4.2.0" + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-serializer@0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +dom-walk@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" + integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +domelementtype@1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" + integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + +domutils@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + +dot-prop@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" + integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== + dependencies: + is-obj "^2.0.0" + +download@^6.2.2: + version "6.2.5" + resolved "https://registry.yarnpkg.com/download/-/download-6.2.5.tgz#acd6a542e4cd0bb42ca70cfc98c9e43b07039714" + integrity sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA== + dependencies: + caw "^2.0.0" + content-disposition "^0.5.2" + decompress "^4.0.0" + ext-name "^5.0.0" + file-type "5.2.0" + filenamify "^2.0.0" + get-stream "^3.0.0" + got "^7.0.0" + make-dir "^1.0.0" + p-event "^1.0.0" + pify "^3.0.0" + +download@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/download/-/download-7.1.0.tgz#9059aa9d70b503ee76a132897be6dec8e5587233" + integrity sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ== + dependencies: + archive-type "^4.0.0" + caw "^2.0.1" + content-disposition "^0.5.2" + decompress "^4.2.0" + ext-name "^5.0.0" + file-type "^8.1.0" + filenamify "^2.0.0" + get-stream "^3.0.0" + got "^8.3.1" + make-dir "^1.2.0" + p-event "^2.1.0" + pify "^3.0.0" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +duplexer@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= + +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +ejs@^2.6.1: + version "2.7.4" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" + integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== + +electron-to-chromium@^1.3.390: + version "1.3.403" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.403.tgz#c8bab4e2e72bf78bc28bad1cc355c061f9cc1918" + integrity sha512-JaoxV4RzdBAZOnsF4dAlZ2ijJW72MbqO5lNfOBHUWiBQl3Rwe+mk2RCUMrRI3rSClLJ8HSNQNqcry12H+0ZjFw== + +elliptic@^6.0.0, elliptic@^6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" + integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + +email-validator@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/email-validator/-/email-validator-2.0.4.tgz#b8dfaa5d0dae28f1b03c95881d904d4e40bfe7ed" + integrity sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ== + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enhanced-resolve@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" + integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.4.0" + tapable "^1.0.0" + +enhanced-resolve@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" + integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" + +entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + +errno@^0.1.3, errno@~0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5: + version "1.17.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" + integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es6-templates@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/es6-templates/-/es6-templates-0.2.3.tgz#5cb9ac9fb1ded6eb1239342b81d792bbb4078ee4" + integrity sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ= + dependencies: + recast "~0.11.12" + through "~2.3.6" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +eslint-config-prettier@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz#f6d2238c1290d01c859a8b5c1f7d352a0b0da8b1" + integrity sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA== + dependencies: + get-stdin "^6.0.0" + +eslint-plugin-prettier@3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.3.tgz#ae116a0fc0e598fdae48743a4430903de5b4e6ca" + integrity sha512-+HG5jmu/dN3ZV3T6eCD7a4BlAySdN7mLIbJYo0z1cFQuI+r2DiTJEFeF68ots93PsnrMxbzIZ2S/ieX+mkrBeQ== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-scope@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" + integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" + integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== + +eslint@7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.1.0.tgz#d9a1df25e5b7859b0a3d86bb05f0940ab676a851" + integrity sha512-DfS3b8iHMK5z/YLSme8K5cge168I8j8o1uiVmFCgnnjxZQbCGyraF8bMl7Ju4yfBmCuxD7shOF7eqGkcuIHfsA== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + eslint-visitor-keys "^1.1.0" + espree "^7.0.0" + esquery "^1.2.0" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^7.0.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash "^4.17.14" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.0.0.tgz#8a7a60f218e69f120a842dc24c5a88aa7748a74e" + integrity sha512-/r2XEx5Mw4pgKdyb7GNLQNsu++asx/dltf/CI8RFi9oGHxmQFgvLbc5Op4U6i8Oaj+kdslhJtVlEZeAqH5qOTw== + dependencies: + acorn "^7.1.1" + acorn-jsx "^5.2.0" + eslint-visitor-keys "^1.1.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esprima@~3.1.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= + +esquery@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" + integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.1.0, esrecurse@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" + integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +events@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" + integrity sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" + integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw== + dependencies: + cross-spawn "^6.0.0" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +executable@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" + integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== + dependencies: + pify "^2.2.0" + +exif-parser@^0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/exif-parser/-/exif-parser-0.1.12.tgz#58a9d2d72c02c1f6f02a0ef4a9166272b7760922" + integrity sha1-WKnS1ywCwfbwKg70qRZicrd2CSI= + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + dependencies: + homedir-polyfill "^1.0.1" + +express@^4.16.3: + version "4.17.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" + integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + dependencies: + accepts "~1.3.7" + array-flatten "1.1.1" + body-parser "1.19.0" + content-disposition "0.5.3" + content-type "~1.0.4" + cookie "0.4.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "~1.1.2" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.5" + qs "6.7.0" + range-parser "~1.2.1" + safe-buffer "5.1.2" + send "0.17.1" + serve-static "1.14.1" + setprototypeof "1.1.1" + statuses "~1.5.0" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +ext-list@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37" + integrity sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA== + dependencies: + mime-db "^1.28.0" + +ext-name@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ext-name/-/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6" + integrity sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ== + dependencies: + ext-list "^2.0.0" + sort-keys-length "^1.0.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fastdom@^1.0.8: + version "1.0.9" + resolved "https://registry.yarnpkg.com/fastdom/-/fastdom-1.0.9.tgz#b395fab11a3701173c02a054fe769d8f596a0a26" + integrity sha512-SSp4fbVzu8JkkG01NUX+0iOwe9M5PN3MGIQ84txLf4TkkJG4q30khkzumKgi4hUqO1+jX6wLHfnCPoZ6eSZ6Tg== + dependencies: + strictdom "^1.0.1" + +faster.js@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/faster.js/-/faster.js-1.1.1.tgz#8bbd7eefdb8f03faac26ad5025b059f94c5cfb4d" + integrity sha512-vPThNSLL/E1f7cLHd9yuayxZR82o/Iic4S5ZY45iY5AgBLNIlr3b3c+VpDjoYqjY9a9C/FQVUQy9oTILVP7X0g== + +fastparse@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" + integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + +figgy-pudding@^3.5.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== + +figures@^1.3.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + +file-loader@^0.8.1: + version "0.8.5" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-0.8.5.tgz#9275d031fe780f27d47f5f4af02bd43713cc151b" + integrity sha1-knXQMf54DyfUf19K8CvUNxPMFRs= + dependencies: + loader-utils "~0.2.5" + +file-type@5.2.0, file-type@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" + integrity sha1-LdvqfHP/42No365J3DOMBYwritY= + +file-type@^3.8.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" + integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= + +file-type@^4.2.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" + integrity sha1-G2AOX8ofvcboDApwxxyNul95BsU= + +file-type@^6.1.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" + integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== + +file-type@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-8.1.0.tgz#244f3b7ef641bbe0cca196c7276e4b332399f68c" + integrity sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ== + +file-type@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-9.0.0.tgz#a68d5ad07f486414dfb2c8866f73161946714a18" + integrity sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw== + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +filename-reserved-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" + integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik= + +filenamify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-2.1.0.tgz#88faf495fb1b47abfd612300002a16228c677ee9" + integrity sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA== + dependencies: + filename-reserved-regex "^2.0.0" + strip-outer "^1.0.0" + trim-repeated "^1.0.0" + +filesize@^3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" + integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-cache-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-versions@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e" + integrity sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww== + dependencies: + semver-regex "^2.0.0" + +findup-sync@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" + integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== + dependencies: + detect-file "^1.0.0" + is-glob "^4.0.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0, flatted@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + +flatten@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" + integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== + +flush-write-stream@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== + dependencies: + inherits "^2.0.3" + readable-stream "^2.3.6" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +forwarded@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +from2@^2.1.0, from2@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs-write-stream-atomic@^1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.2.7: + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== + dependencies: + bindings "^1.5.0" + nan "^2.12.1" + +fsevents@~2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-proxy@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93" + integrity sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw== + dependencies: + npm-conf "^1.1.0" + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= + +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + +get-stream@3.0.0, get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +get-stream@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" + integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= + dependencies: + object-assign "^4.0.1" + pinkie-promise "^2.0.0" + +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +glob-all@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.2.1.tgz#082ca81afd2247cbd3ed2149bb2630f4dc877d95" + integrity sha512-x877rVkzB3ipid577QOp+eQCR6M5ZyiwrtaYgrX/z3EThaSPFtLDwBXFHc3sH1cG0R0vFYI5SRYeWMMSEyXkUw== + dependencies: + glob "^7.1.2" + yargs "^15.3.1" + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-parent@^5.0.0, glob-parent@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + +glob@^7.0.5, glob@^7.0.6, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-modules@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + +global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" + +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= + dependencies: + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" + +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +global@~4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" + integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= + dependencies: + min-document "^2.19.0" + process "~0.5.1" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^12.1.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== + dependencies: + type-fest "^0.8.1" + +gonzales-pe@^4.2.3: + version "4.3.0" + resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.3.0.tgz#fe9dec5f3c557eead09ff868c65826be54d067b3" + integrity sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ== + dependencies: + minimist "^1.2.5" + +got@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" + integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== + dependencies: + decompress-response "^3.2.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-plain-obj "^1.1.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + isurl "^1.0.0-alpha5" + lowercase-keys "^1.0.0" + p-cancelable "^0.3.0" + p-timeout "^1.1.1" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + url-parse-lax "^1.0.0" + url-to-options "^1.0.1" + +got@^8.3.1: + version "8.3.2" + resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" + integrity sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw== + dependencies: + "@sindresorhus/is" "^0.7.0" + cacheable-request "^2.1.1" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + into-stream "^3.1.0" + is-retry-allowed "^1.1.0" + isurl "^1.0.0-alpha5" + lowercase-keys "^1.0.0" + mimic-response "^1.0.0" + p-cancelable "^0.4.0" + p-timeout "^2.0.1" + pify "^3.0.0" + safe-buffer "^5.1.1" + timed-out "^4.0.1" + url-parse-lax "^3.0.0" + url-to-options "^1.0.1" + +graceful-fs@^4.1.10: + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= + +gzip-size@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" + integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== + dependencies: + duplexer "^0.1.1" + pify "^4.0.1" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbol-support-x@^1.4.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" + integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== + +has-symbols@^1.0.0, has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + +has-to-string-tag-x@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" + integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== + dependencies: + has-symbol-support-x "^1.4.1" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.0, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.2.x: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hex-color-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" + integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== + +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +homedir-polyfill@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + dependencies: + parse-passwd "^1.0.0" + +hoopy@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" + integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== + +hosted-git-info@^2.1.4: + version "2.8.8" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" + integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== + +howler@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/howler/-/howler-2.1.3.tgz#07c88618f8767e879407a4d647fe2d6d5f15f121" + integrity sha512-PSGbOi1EYgw80C5UQbxtJM7TmzD+giJunIMBYyH3RVzHZx2fZLYBoes0SpVVHi/SFa1GoNtgXj/j6I7NOKYBxQ== + +hsl-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" + integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= + +hsla-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" + integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= + +html-comment-regex@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" + integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== + +html-loader@^0.5.5: + version "0.5.5" + resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-0.5.5.tgz#6356dbeb0c49756d8ebd5ca327f16ff06ab5faea" + integrity sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog== + dependencies: + es6-templates "^0.2.3" + fastparse "^1.1.1" + html-minifier "^3.5.8" + loader-utils "^1.1.0" + object-assign "^4.1.1" + +html-minifier@^3.5.8: + version "3.5.21" + resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" + integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA== + dependencies: + camel-case "3.0.x" + clean-css "4.2.x" + commander "2.17.x" + he "1.2.x" + param-case "2.1.x" + relateurl "0.2.x" + uglify-js "3.4.x" + +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + +http-errors@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + +iconv-lite@0.4.24, iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.4: + version "1.1.13" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" + integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== + +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= + +ignore-loader@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ignore-loader/-/ignore-loader-0.1.2.tgz#d81f240376d0ba4f0d778972c3ad25874117a463" + integrity sha1-2B8kA3bQuk8Nd4lyw60lh0EXpGM= + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +imagemin-mozjpeg@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/imagemin-mozjpeg/-/imagemin-mozjpeg-8.0.0.tgz#d2ca4e8c982c7c6eda55069af89dee4c1cebcdfd" + integrity sha512-+EciPiIjCb8JWjQNr1q8sYWYf7GDCNDxPYnkD11TNIjjWNzaV+oTg4DpOPQjl5ZX/KRCPMEgS79zLYAQzLitIA== + dependencies: + execa "^1.0.0" + is-jpg "^2.0.0" + mozjpeg "^6.0.0" + +imagemin-pngquant@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/imagemin-pngquant/-/imagemin-pngquant-8.0.0.tgz#bf7a41d850c6998f2475c54058ab1db9c516385d" + integrity sha512-PVq0diOxO+Zyq/zlMCz2Pfu6mVLHgiT1GpW702OwVlnej+NhS6ZQegYi3OFEDW8d7GxouyR5e8R+t53SMciOeg== + dependencies: + execa "^1.0.0" + is-png "^2.0.0" + is-stream "^2.0.0" + ow "^0.13.2" + pngquant-bin "^5.0.0" + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.0.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" + integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-lazy@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc" + integrity sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ== + +import-local@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== + dependencies: + pkg-dir "^3.0.0" + resolve-cwd "^2.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= + dependencies: + repeating "^2.0.0" + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= + +infer-owner@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ini@^1.3.4, ini@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +inquirer@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29" + integrity sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg== + dependencies: + ansi-escapes "^4.2.1" + chalk "^3.0.0" + cli-cursor "^3.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.15" + mute-stream "0.0.8" + run-async "^2.4.0" + rxjs "^6.5.3" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + +interpret@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" + integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== + +into-stream@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" + integrity sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY= + dependencies: + from2 "^2.1.1" + p-is-promise "^1.1.0" + +invariant@^2.2.2, invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" + integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-absolute-url@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-callable@^1.1.4, is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== + +is-color-stop@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" + integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= + dependencies: + css-color-names "^0.0.4" + hex-color-regex "^1.1.0" + hsl-regex "^1.0.0" + hsla-regex "^1.0.0" + rgb-regex "^1.0.1" + rgba-regex "^1.0.0" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-finite@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-function@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" + integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-jpg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-jpg/-/is-jpg-2.0.0.tgz#2e1997fa6e9166eaac0242daae443403e4ef1d97" + integrity sha1-LhmX+m6RZuqsAkLarkQ0A+TvHZc= + +is-natural-number@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" + integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + +is-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" + integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= + +is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-png@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-png/-/is-png-2.0.0.tgz#ee8cbc9e9b050425cedeeb4a6fb74a649b0a4a8d" + integrity sha512-4KPGizaVGj2LK7xwJIz8o5B2ubu1D/vcQsgOGFEDlpcvgZHto4gBnyd0ig7Ws+67ixmwKoNmu0hYnpo6AaKb5g== + +is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== + dependencies: + has "^1.0.3" + +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== + +is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" + integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== + +is-stream@^1.0.0, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + +is-svg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" + integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== + dependencies: + html-comment-regex "^1.1.0" + +is-symbol@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-windows@^1.0.1, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isurl@^1.0.0-alpha5: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" + integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== + dependencies: + has-to-string-tag-x "^1.2.0" + is-object "^1.0.1" + +jimp@^0.6.1: + version "0.6.8" + resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.6.8.tgz#63074984337cc469cd4030946e503e7c02a18b5c" + integrity sha512-F7emeG7Hp61IM8VFbNvWENLTuHe0ghizWPuP4JS9ujx2r5mCVYEd/zdaz6M2M42ZdN41blxPajLWl9FXo7Mr2Q== + dependencies: + "@jimp/custom" "^0.6.8" + "@jimp/plugins" "^0.6.8" + "@jimp/types" "^0.6.8" + core-js "^2.5.7" + regenerator-runtime "^0.13.3" + +jpeg-js@^0.3.4: + version "0.3.7" + resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.3.7.tgz#471a89d06011640592d314158608690172b1028d" + integrity sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ== + +js-base64@^2.1.9: + version "2.5.2" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209" + integrity sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^3.4.2: + version "3.14.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + +json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json5@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + +keyv@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" + integrity sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA== + dependencies: + json-buffer "3.0.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +known-css-properties@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.11.0.tgz#0da784f115ea77c76b81536d7052e90ee6c86a8a" + integrity sha512-bEZlJzXo5V/ApNNa5z375mJC6Nrz4vG43UgcSCrg2OHC+yuB6j0iDSrY7RQ/+PRofFB03wNIIt9iXIVLr4wc7w== + +lcid@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" + integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== + dependencies: + invert-kv "^2.0.0" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levenary@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" + integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== + dependencies: + leven "^3.1.0" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +load-bmfont@^1.3.1, load-bmfont@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.0.tgz#75f17070b14a8c785fe7f5bee2e6fd4f98093b6b" + integrity sha512-kT63aTAlNhZARowaNYcY29Fn/QYkc52M3l6V1ifRcPewg2lvUZDAj7R6dXjOL9D0sict76op3T5+odumDSF81g== + dependencies: + 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" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +loader-runner@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== + +loader-utils@1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" + integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== + dependencies: + big.js "^5.2.2" + emojis-list "^2.0.0" + json5 "^1.0.1" + +loader-utils@^0.2.5, loader-utils@~0.2.2, loader-utils@~0.2.3, loader-utils@~0.2.5: + version "0.2.17" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" + integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + object-assign "^4.0.1" + +loader-utils@^1.0.0, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= + +lodash.template@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" + integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.templatesettings@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== + dependencies: + lodash._reinterpolate "^3.0.0" + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + +lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +logalot@^2.0.0, logalot@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/logalot/-/logalot-2.1.0.tgz#5f8e8c90d304edf12530951a5554abb8c5e3f552" + integrity sha1-X46MkNME7fElMJUaVVSruMXj9VI= + dependencies: + figures "^1.3.5" + squeak "^1.0.0" + +logrocket@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/logrocket/-/logrocket-1.0.7.tgz#fe17dbdfc861481cd274fbda533d552de7800a3a" + integrity sha512-v6HWEQIsyG+3FkldB7vIAgHh7/qpsiz2Br4bLK5SHBvjqRrHs/Fp+Jr8oiA2GYq0UurAtCu51U8SWft5+OCKtg== + +longest@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +lower-case@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" + integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= + +lowercase-keys@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" + integrity sha1-TjNms55/VFfjXxMkvfb4jQv8cwY= + +lowercase-keys@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lpad-align@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/lpad-align/-/lpad-align-1.1.2.tgz#21f600ac1c3095c3c6e497ee67271ee08481fe9e" + integrity sha1-IfYArBwwlcPG5JfuZyce4ISB/p4= + dependencies: + get-stdin "^4.0.1" + indent-string "^2.1.0" + longest "^1.0.0" + meow "^3.3.0" + +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lz-string@^1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" + integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY= + +make-dir@^1.0.0, make-dir@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + dependencies: + pify "^3.0.0" + +make-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +markdown-loader@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/markdown-loader/-/markdown-loader-4.0.0.tgz#502eb94f5db1673beb1721bed82dac9e1d333b9a" + integrity sha512-9BCm8iyLF4AVYtjtybOTg8cTcpWYKsDGWWhsc7XaJlXQiddo3ztbZxLPJ28pmCxFI1BlMkT1wDVav1chPjTpdA== + dependencies: + loader-utils "^1.1.0" + marked "^0.5.0" + +marked@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.5.2.tgz#3efdb27b1fd0ecec4f5aba362bddcd18120e5ba9" + integrity sha512-fdZvBa7/vSQIZCi4uuwo2N3q+7jJURpMVCcbaX0S1Mg65WZ5ilXvC67MviJAsdjqqgD+CEq4RKo5AYGgINkVAA== + +match-all@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.5.tgz#f709af311a7cb9ae464d9107a4f0fe08d3326eff" + integrity sha512-KW4trRDMYbVkAKZ1J655vh0931mk3XM1lIJ480TXUL3KBrOsZ6WpryYJELonvtXC1O4erLYB069uHidLkswbjQ== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== + +mdn-data@2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978" + integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +mem@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" + integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== + dependencies: + map-age-cleaner "^0.1.1" + mimic-fn "^2.0.0" + p-is-promise "^2.0.0" + +memory-fs@^0.4.0, memory-fs@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +meow@^3.3.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.43.0, mime-db@^1.28.0: + version "1.43.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" + integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== + +mime-types@~2.1.24: + version "2.1.26" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" + integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== + dependencies: + mime-db "1.43.0" + +mime@1.6.0, mime@^1.3.4: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mime@^2.4.0: + version "2.4.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" + integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== + +mimic-fn@^2.0.0, mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= + dependencies: + dom-walk "^0.1.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== + dependencies: + concat-stream "^1.5.0" + duplexify "^3.4.2" + end-of-stream "^1.1.0" + flush-write-stream "^1.0.0" + from2 "^2.1.0" + parallel-transform "^1.1.0" + pump "^3.0.0" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= + dependencies: + aproba "^1.1.1" + copy-concurrently "^1.0.0" + fs-write-stream-atomic "^1.0.8" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.3" + +mozjpeg@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/mozjpeg/-/mozjpeg-6.0.1.tgz#56969dddb5741ef2bcb1af066cae21e61a91a27b" + integrity sha512-9Z59pJMi8ni+IUvSH5xQwK5tNLw7p3dwDNCZ3o1xE+of3G5Hc/yOz6Ue/YuLiBXU3ZB5oaHPURyPdqfBX/QYJA== + dependencies: + bin-build "^3.0.0" + bin-wrapper "^4.0.0" + logalot "^2.1.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + +nan@^2.12.1: + version "2.14.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" + integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + +neo-async@^2.5.0, neo-async@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +no-case@^2.2.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" + integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== + dependencies: + lower-case "^1.1.1" + +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^3.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.1" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.11.0" + vm-browserify "^1.0.1" + +node-releases@^1.1.53: + version "1.1.53" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4" + integrity sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ== + +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= + +normalize-url@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" + integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw== + dependencies: + prepend-http "^2.0.0" + query-string "^5.0.1" + sort-keys "^2.0.0" + +normalize-url@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" + integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== + +npm-conf@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" + integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw== + dependencies: + config-chain "^1.1.11" + pify "^3.0.0" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +nth-check@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== + dependencies: + boolbase "~1.0.0" + +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= + +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" + integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.getownpropertydescriptors@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +object.values@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + +omggif@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19" + integrity sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw== + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + +opener@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" + integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + +os-filter-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/os-filter-obj/-/os-filter-obj-2.0.0.tgz#1c0b62d5f3a2442749a2d139e6dddee6e81d8d16" + integrity sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg== + dependencies: + arch "^2.1.0" + +os-locale@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== + dependencies: + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +ow@^0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/ow/-/ow-0.13.2.tgz#375e76d3d3f928a8dfcf0cd0b9c921cb62e469a0" + integrity sha512-9wvr+q+ZTDRvXDjL6eDOdFe5WUl/wa5sntf9kAolxqSpkBqaIObwLgFCGXSJASFw+YciXnOVtDWpxXa9cqV94A== + dependencies: + type-fest "^0.5.1" + +p-cancelable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" + integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== + +p-cancelable@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" + integrity sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ== + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + +p-event@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-event/-/p-event-1.3.0.tgz#8e6b4f4f65c72bc5b6fe28b75eda874f96a4a085" + integrity sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU= + dependencies: + p-timeout "^1.1.1" + +p-event@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/p-event/-/p-event-2.3.1.tgz#596279ef169ab2c3e0cae88c1cfbb08079993ef6" + integrity sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA== + dependencies: + p-timeout "^2.0.1" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-is-promise@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" + integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4= + +p-is-promise@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" + integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-map-series@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca" + integrity sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco= + dependencies: + p-reduce "^1.0.0" + +p-reduce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" + integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= + +p-timeout@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" + integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= + dependencies: + p-finally "^1.0.0" + +p-timeout@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" + integrity sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA== + dependencies: + p-finally "^1.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +pako@^1.0.5, pako@~1.0.5: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +parallel-transform@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" + integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== + dependencies: + cyclist "^1.0.1" + inherits "^2.0.3" + readable-stream "^2.1.5" + +param-case@2.1.x: + version "2.1.1" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" + integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= + dependencies: + no-case "^2.2.0" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.5" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" + integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-bmfont-ascii@^1.0.3: + version "1.0.6" + resolved "https://registry.yarnpkg.com/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz#11ac3c3ff58f7c2020ab22769079108d4dfa0285" + integrity sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU= + +parse-bmfont-binary@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz#d038b476d3e9dd9db1e11a0b0e53a22792b69006" + integrity sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY= + +parse-bmfont-xml@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz#015319797e3e12f9e739c4d513872cd2fa35f389" + integrity sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ== + dependencies: + xml-parse-from-string "^1.0.0" + xml2js "^0.4.5" + +parse-headers@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.3.tgz#5e8e7512383d140ba02f0c7aa9f49b4399c92515" + integrity sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA== + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +pbkdf2@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" + integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + +phin@^2.9.1: + version "2.9.3" + resolved "https://registry.yarnpkg.com/phin/-/phin-2.9.3.tgz#f9b6ac10a035636fb65dfc576aaaa17b8743125c" + integrity sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA== + +phonegap-plugin-mobile-accessibility@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/phonegap-plugin-mobile-accessibility/-/phonegap-plugin-mobile-accessibility-1.0.5.tgz#95a8754d127508bc6e1ae259a53ce765836eac03" + integrity sha1-lah1TRJ1CLxuGuJZpTznZYNurAM= + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + +pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + +pixelmatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-4.0.2.tgz#8f47dcec5011b477b67db03c243bc1f3085e8854" + integrity sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ= + dependencies: + pngjs "^3.0.0" + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" + integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= + dependencies: + find-up "^2.1.0" + +pngjs@^3.0.0, pngjs@^3.3.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" + integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== + +pngquant-bin@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/pngquant-bin/-/pngquant-bin-5.0.2.tgz#6f34f3e89c9722a72bbc509062b40f1b17cda460" + integrity sha512-OLdT+4JZx5BqE1CFJkrvomYV0aSsv6x2Bba+aWaVc0PMfWlE+ZByNKYAdKeIqsM4uvW1HOSEHnf8KcOnykPNxA== + dependencies: + bin-build "^3.0.0" + bin-wrapper "^4.0.1" + execa "^0.10.0" + logalot "^2.0.0" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +postcss-assets@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-assets/-/postcss-assets-5.0.0.tgz#f721d07d339605fb58414e9f69cf05401c54e709" + integrity sha1-9yHQfTOWBftYQU6fac8FQBxU5wk= + dependencies: + assets "^3.0.0" + bluebird "^3.5.0" + postcss "^6.0.10" + postcss-functions "^3.0.0" + +postcss-attribute-case-insensitive@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" + integrity sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA== + dependencies: + postcss "^7.0.2" + postcss-selector-parser "^6.0.2" + +postcss-calc@^7.0.1: + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.2.tgz#504efcd008ca0273120568b0792b16cdcde8aac1" + integrity sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ== + dependencies: + postcss "^7.0.27" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.2" + +postcss-color-functional-notation@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" + integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g== + dependencies: + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-color-gray@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" + integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw== + dependencies: + "@csstools/convert-colors" "^1.4.0" + postcss "^7.0.5" + postcss-values-parser "^2.0.0" + +postcss-color-hex-alpha@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" + integrity sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw== + dependencies: + postcss "^7.0.14" + postcss-values-parser "^2.0.1" + +postcss-color-mod-function@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" + integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ== + dependencies: + "@csstools/convert-colors" "^1.4.0" + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-color-rebeccapurple@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" + integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g== + dependencies: + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-colormin@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" + integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== + dependencies: + browserslist "^4.0.0" + color "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-convert-values@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" + integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-custom-media@^7.0.8: + version "7.0.8" + resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" + integrity sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg== + dependencies: + postcss "^7.0.14" + +postcss-custom-properties@^8.0.11: + version "8.0.11" + resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" + integrity sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA== + dependencies: + postcss "^7.0.17" + postcss-values-parser "^2.0.1" + +postcss-custom-selectors@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" + integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w== + dependencies: + postcss "^7.0.2" + postcss-selector-parser "^5.0.0-rc.3" + +postcss-dir-pseudo-class@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2" + integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw== + dependencies: + postcss "^7.0.2" + postcss-selector-parser "^5.0.0-rc.3" + +postcss-discard-comments@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" + integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== + dependencies: + postcss "^7.0.0" + +postcss-discard-duplicates@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" + integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== + dependencies: + postcss "^7.0.0" + +postcss-discard-empty@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" + integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== + dependencies: + postcss "^7.0.0" + +postcss-discard-overridden@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" + integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== + dependencies: + postcss "^7.0.0" + +postcss-discard-unused@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-4.0.1.tgz#ee7cc66af8c7e8c19bd36f12d09c4bde4039abea" + integrity sha512-/3vq4LU0bLH2Lj4NYN7BTf2caly0flUB7Xtrk9a5K3yLuXMkHMqMO/x3sDq8W2b1eQFSCyY0IVz2L+0HP8kUUA== + dependencies: + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + uniqs "^2.0.0" + +postcss-double-position-gradients@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" + integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA== + dependencies: + postcss "^7.0.5" + postcss-values-parser "^2.0.0" + +postcss-env-function@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7" + integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw== + dependencies: + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-focus-visible@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" + integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g== + dependencies: + postcss "^7.0.2" + +postcss-focus-within@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680" + integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w== + dependencies: + postcss "^7.0.2" + +postcss-font-variant@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz#71dd3c6c10a0d846c5eda07803439617bbbabacc" + integrity sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg== + dependencies: + postcss "^7.0.2" + +postcss-functions@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-functions/-/postcss-functions-3.0.0.tgz#0e94d01444700a481de20de4d55fb2640564250e" + integrity sha1-DpTQFERwCkgd4g3k1V+yZAVkJQ4= + dependencies: + glob "^7.1.2" + object-assign "^4.1.1" + postcss "^6.0.9" + postcss-value-parser "^3.3.0" + +postcss-gap-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715" + integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg== + dependencies: + postcss "^7.0.2" + +postcss-image-set-function@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288" + integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw== + dependencies: + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-initial@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.2.tgz#f018563694b3c16ae8eaabe3c585ac6319637b2d" + integrity sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA== + dependencies: + lodash.template "^4.5.0" + postcss "^7.0.2" + +postcss-lab-function@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e" + integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg== + dependencies: + "@csstools/convert-colors" "^1.4.0" + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-logical@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5" + integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA== + dependencies: + postcss "^7.0.2" + +postcss-media-minmax@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" + integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw== + dependencies: + postcss "^7.0.2" + +postcss-merge-idents@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-4.0.1.tgz#b7df282a92f052ea0a66c62d8f8812e6d2cbed23" + integrity sha512-43S/VNdF6II0NZ31YxcvNYq4gfURlPAAsJW/z84avBXQCaP4I4qRHUH18slW/SOlJbcxxCobflPNUApYDddS7A== + dependencies: + cssnano-util-same-parent "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-merge-longhand@^4.0.11: + version "4.0.11" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" + integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== + dependencies: + css-color-names "0.0.4" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + stylehacks "^4.0.0" + +postcss-merge-rules@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" + integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + cssnano-util-same-parent "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + vendors "^1.0.0" + +postcss-minify-font-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" + integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-gradients@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" + integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + is-color-stop "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-params@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" + integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== + dependencies: + alphanum-sort "^1.0.0" + browserslist "^4.0.0" + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + uniqs "^2.0.0" + +postcss-minify-selectors@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" + integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== + dependencies: + alphanum-sort "^1.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + +postcss-nesting@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" + integrity sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg== + dependencies: + postcss "^7.0.2" + +postcss-normalize-charset@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" + integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== + dependencies: + postcss "^7.0.0" + +postcss-normalize-display-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" + integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-positions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" + integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== + dependencies: + cssnano-util-get-arguments "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-repeat-style@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" + integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-string@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" + integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== + dependencies: + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-timing-functions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" + integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-unicode@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" + integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-url@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" + integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-whitespace@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" + integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-ordered-values@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" + integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== + dependencies: + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-overflow-shorthand@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30" + integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g== + dependencies: + postcss "^7.0.2" + +postcss-page-break@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf" + integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ== + dependencies: + postcss "^7.0.2" + +postcss-place@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62" + integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg== + dependencies: + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-preset-env@^6.5.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5" + integrity sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg== + dependencies: + autoprefixer "^9.6.1" + browserslist "^4.6.4" + caniuse-lite "^1.0.30000981" + css-blank-pseudo "^0.1.4" + css-has-pseudo "^0.10.0" + css-prefers-color-scheme "^3.1.1" + cssdb "^4.4.0" + postcss "^7.0.17" + postcss-attribute-case-insensitive "^4.0.1" + postcss-color-functional-notation "^2.0.1" + postcss-color-gray "^5.0.0" + postcss-color-hex-alpha "^5.0.3" + postcss-color-mod-function "^3.0.3" + postcss-color-rebeccapurple "^4.0.1" + postcss-custom-media "^7.0.8" + postcss-custom-properties "^8.0.11" + postcss-custom-selectors "^5.1.2" + postcss-dir-pseudo-class "^5.0.0" + postcss-double-position-gradients "^1.0.0" + postcss-env-function "^2.0.2" + postcss-focus-visible "^4.0.0" + postcss-focus-within "^3.0.0" + postcss-font-variant "^4.0.0" + postcss-gap-properties "^2.0.0" + postcss-image-set-function "^3.0.1" + postcss-initial "^3.0.0" + postcss-lab-function "^2.0.1" + postcss-logical "^3.0.0" + postcss-media-minmax "^4.0.0" + postcss-nesting "^7.0.0" + postcss-overflow-shorthand "^2.0.0" + postcss-page-break "^2.0.0" + postcss-place "^4.0.1" + postcss-pseudo-class-any-link "^6.0.0" + postcss-replace-overflow-wrap "^3.0.0" + postcss-selector-matches "^4.0.0" + postcss-selector-not "^4.0.0" + +postcss-pseudo-class-any-link@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" + integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew== + dependencies: + postcss "^7.0.2" + postcss-selector-parser "^5.0.0-rc.3" + +postcss-reduce-idents@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-4.0.2.tgz#30447a6ec20941e78e21bd4482a11f569c4f455b" + integrity sha512-Tz70Ri10TclPoCtFfftjFVddx3fZGUkr0dEDbIEfbYhFUOFQZZ77TEqRrU0e6TvAvF+Wa5VVzYTpFpq0uwFFzw== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-reduce-initial@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" + integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + +postcss-reduce-transforms@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" + integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== + dependencies: + cssnano-util-get-match "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-replace-overflow-wrap@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" + integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw== + dependencies: + postcss "^7.0.2" + +postcss-round-subpixels@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-round-subpixels/-/postcss-round-subpixels-1.2.0.tgz#e21d6ac5952e185f9bdc008b94f004fe509d0a11" + integrity sha1-4h1qxZUuGF+b3ACLlPAE/lCdChE= + dependencies: + postcss "^5.0.2" + postcss-value-parser "^3.1.2" + +postcss-selector-matches@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" + integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww== + dependencies: + balanced-match "^1.0.0" + postcss "^7.0.2" + +postcss-selector-not@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz#c68ff7ba96527499e832724a2674d65603b645c0" + integrity sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ== + dependencies: + balanced-match "^1.0.0" + postcss "^7.0.2" + +postcss-selector-parser@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" + integrity sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA== + dependencies: + dot-prop "^5.2.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^5.0.0, postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" + integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== + dependencies: + cssesc "^2.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" + integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== + dependencies: + cssesc "^3.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-svgo@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" + integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== + dependencies: + is-svg "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + svgo "^1.0.0" + +postcss-unique-selectors@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" + integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== + dependencies: + alphanum-sort "^1.0.0" + postcss "^7.0.0" + uniqs "^2.0.0" + +postcss-unprefix@^2.1.3: + version "2.1.4" + resolved "https://registry.yarnpkg.com/postcss-unprefix/-/postcss-unprefix-2.1.4.tgz#ab1c038ab77f068799ed36e1cbd997b51e7360a1" + integrity sha512-s+muBiGIMx3RvgPTtPBnSrfvIBHJ2Zx16QZf/VDB/sAxdYP6FIzci8d1gLh0+9psu5W6zVtCbU5micNt6Zh3cg== + dependencies: + autoprefixer "^9.4.3" + known-css-properties "^0.11.0" + normalize-range "^0.1.2" + postcss-selector-parser "^5.0.0" + postcss-value-parser "^3.3.1" + pseudo-classes "^1.0.0" + pseudo-elements "^1.1.0" + +postcss-value-parser@^3.0.0, postcss-value-parser@^3.1.2, postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== + +postcss-value-parser@^4.0.2, postcss-value-parser@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz#651ff4593aa9eda8d5d0d66593a2417aeaeb325d" + integrity sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg== + +postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" + integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== + dependencies: + flatten "^1.0.2" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-zindex@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-4.0.1.tgz#8db6a4cec3111e5d3fd99ea70abeda61873d10c1" + integrity sha512-d/8BlQcUdEugZNRM9AdCA2V4fqREUtn/wcixLN3L6ITgc2P/FMcVVYz8QZkhItWT9NB5qr8wuN2dJCE4/+dlrA== + dependencies: + has "^1.0.0" + postcss "^7.0.0" + uniqs "^2.0.0" + +postcss@^5.0.2: + version "5.2.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" + integrity sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg== + dependencies: + chalk "^1.1.3" + js-base64 "^2.1.9" + source-map "^0.5.6" + supports-color "^3.2.3" + +postcss@^6.0.10, postcss@^6.0.9: + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" + integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== + dependencies: + chalk "^2.4.1" + source-map "^0.6.1" + supports-color "^5.4.0" + +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.27, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.27" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9" + integrity sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.4.tgz#2d1bae173e355996ee355ec9830a7a1ee05457ef" + integrity sha512-SVJIQ51spzFDvh4fIbCLvciiDMCrRhlN3mbZvv/+ycjvmF5E73bKdGfU8QDLNmjYJf+lsGnDBC4UUnvTe5OO0w== + +private@^0.1.8, private@~0.1.5: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +process@~0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" + integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= + +promise-polyfill@^8.1.0: + version "8.1.3" + resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.1.3.tgz#8c99b3cf53f3a91c68226ffde7bde81d7f904116" + integrity sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g== + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= + +proxy-addr@~2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" + integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== + dependencies: + forwarded "~0.1.2" + ipaddr.js "1.9.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +pseudo-classes@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pseudo-classes/-/pseudo-classes-1.0.0.tgz#60a69b67395c36ff119c4d1c86e1981785206b96" + integrity sha1-YKabZzlcNv8RnE0chuGYF4Uga5Y= + +pseudo-elements@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pseudo-elements/-/pseudo-elements-1.1.0.tgz#9ba6dd8ac3ce1f3d7d36d4355aa3e28d08391f28" + integrity sha1-m6bdisPOHz19NtQ1WqPijQg5Hyg= + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + +qs@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +query-string@^6.8.1: + version "6.12.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.12.1.tgz#2ae4d272db4fba267141665374e49a1de09e8a7c" + integrity sha512-OHj+zzfRMyj3rmo/6G8a5Ifvw3AleL/EbcHMD27YA31Q+cO5lfmQxECkImuNVjcskLcvBRVHNAB3w6udMs1eAA== + dependencies: + decode-uri-component "^0.2.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + dependencies: + bytes "3.1.0" + http-errors "1.7.2" + iconv-lite "0.4.24" + unpipe "1.0.0" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +readdirp@~3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" + integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== + dependencies: + picomatch "^2.2.1" + +recast@~0.11.12: + version "0.11.23" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3" + integrity sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM= + dependencies: + ast-types "0.9.6" + esprima "~3.1.0" + private "~0.1.5" + source-map "~0.5.0" + +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + +regenerate-unicode-properties@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== + dependencies: + regenerate "^1.4.0" + +regenerate@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4: + version "0.13.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" + integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== + +regenerator-transform@^0.14.2: + version "0.14.4" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" + integrity sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw== + dependencies: + "@babel/runtime" "^7.8.4" + private "^0.1.8" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexpp@^3.0.0, regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + +regexpu-core@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" + integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.2.0" + regjsgen "^0.5.1" + regjsparser "^0.6.4" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.2.0" + +regjsgen@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" + integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== + +regjsparser@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" + integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== + dependencies: + jsesc "~0.5.0" + +relateurl@0.2.x: + version "0.2.7" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= + dependencies: + is-finite "^1.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= + dependencies: + resolve-from "^3.0.0" + +resolve-dir@^1.0.0, resolve-dir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@^1.10.0, resolve@^1.3.2: + version "1.15.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" + integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== + dependencies: + path-parse "^1.0.6" + +responselike@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +rgb-regex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" + integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= + +rgba-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" + integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= + +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +rimraf@^2.5.4, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +run-async@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= + dependencies: + aproba "^1.1.1" + +rusha@^0.8.13: + version "0.8.13" + resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.13.tgz#9a084e7b860b17bff3015b92c67a6a336191513a" + integrity sha1-mghOe4YLF7/zAVuSxnpqM2GRUTo= + +rxjs@^6.5.3: + version "6.5.5" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" + integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ== + dependencies: + tslib "^1.9.0" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sass-unused@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/sass-unused/-/sass-unused-0.3.0.tgz#69924e4996d6c96840fb3a99e0a0290516811a9f" + integrity sha512-fGNcUpDeSFwnN+BTQ251iM77Py8awPXc96vSE3TpvMcgbC90IrohonRb4oxWX/KzHpezkmUddS8/t04R+yIB8w== + dependencies: + glob "^7.0.5" + gonzales-pe "^4.2.3" + +sax@>=0.6.0, sax@~1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +schema-utils@^0.4.0: + version "0.4.7" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" + integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ== + dependencies: + ajv "^6.1.0" + ajv-keywords "^3.1.0" + +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== + dependencies: + ajv "^6.1.0" + ajv-errors "^1.0.0" + ajv-keywords "^3.1.0" + +schema-utils@^2.6.5: + version "2.6.5" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.5.tgz#c758f0a7e624263073d396e29cd40aa101152d8a" + integrity sha512-5KXuwKziQrTVHh8j/Uxz+QUbxkaLW9X/86NBlx/gnKgtsZA2GIVMUn17qWhRFwF8jdYb3Dig5hRO/W5mZqy6SQ== + dependencies: + ajv "^6.12.0" + ajv-keywords "^3.4.1" + +seek-bzip@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" + integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= + dependencies: + commander "~2.8.1" + +semver-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" + integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== + +semver-truncate@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/semver-truncate/-/semver-truncate-1.1.2.tgz#57f41de69707a62709a7e0104ba2117109ea47e8" + integrity sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g= + dependencies: + semver "^5.3.0" + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@^7.2.1, semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + +send@0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.7.2" + mime "1.6.0" + ms "2.1.1" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +serialize-error@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-3.0.0.tgz#80100282b09be33c611536f50033481cb9cc87cf" + integrity sha512-+y3nkkG/go1Vdw+2f/+XUXM1DXX1XcxTl99FfiD/OEPUNw4uo0i6FKABfTAN5ZcgGtjTRZcEbxcE/jtXbEY19A== + +serialize-javascript@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" + integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== + +serialize-javascript@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.1.0.tgz#8bf3a9170712664ef2561b44b691eafe399214ea" + integrity sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg== + dependencies: + randombytes "^2.1.0" + +serve-static@1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.1" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + dependencies: + is-arrayish "^0.3.1" + +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +sort-keys-length@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188" + integrity sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg= + dependencies: + sort-keys "^1.0.0" + +sort-keys@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" + integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= + dependencies: + is-plain-obj "^1.0.0" + +sort-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" + integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg= + dependencies: + is-plain-obj "^1.0.0" + +source-list-map@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@~0.5.12: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.0, source-map@^0.5.6, source-map@~0.5.0: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@~0.1.38: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + integrity sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y= + dependencies: + amdefine ">=0.0.4" + +spdx-correct@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + +split-on-first@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" + integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +squeak@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/squeak/-/squeak-1.3.0.tgz#33045037b64388b567674b84322a6521073916c3" + integrity sha1-MwRQN7ZDiLVnZ0uEMiplIQc5FsM= + dependencies: + chalk "^1.0.0" + console-stream "^0.1.1" + lpad-align "^1.0.1" + +ssri@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" + integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== + dependencies: + figgy-pudding "^3.5.1" + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-shift@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= + +strictdom@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strictdom/-/strictdom-1.0.1.tgz#189de91649f73d44d59b8432efa68ef9d2659460" + integrity sha1-GJ3pFkn3PUTVm4Qy76aO+dJllGA= + +string-replace-webpack-plugin@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/string-replace-webpack-plugin/-/string-replace-webpack-plugin-0.1.3.tgz#73c657e759d66cfe80ae1e0cf091aa256d0e715c" + integrity sha1-c8ZX51nWbP6Arh4M8JGqJW0OcVw= + dependencies: + async "~0.2.10" + loader-utils "~0.2.3" + optionalDependencies: + css-loader "^0.9.1" + file-loader "^0.8.1" + style-loader "^0.8.3" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string.prototype.trimend@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" + integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.trimleft@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" + integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.trimstart "^1.0.0" + +string.prototype.trimright@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" + integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.trimend "^1.0.0" + +string.prototype.trimstart@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" + integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string_decoder@^1.0.0, string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= + dependencies: + is-utf8 "^0.2.0" + +strip-dirs@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" + integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== + dependencies: + is-natural-number "^4.0.1" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= + dependencies: + get-stdin "^4.0.1" + +strip-json-comments@^3.0.1, strip-json-comments@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180" + integrity sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w== + +strip-outer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" + integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== + dependencies: + escape-string-regexp "^1.0.2" + +style-loader@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.8.3.tgz#f4f92eb7db63768748f15065cd6700f5a1c85357" + integrity sha1-9Pkut9tjdodI8VBlzWcA9aHIU1c= + dependencies: + loader-utils "^0.2.5" + +stylehacks@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" + integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + +supports-color@6.1.0, supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= + dependencies: + has-flag "^1.0.0" + +supports-color@^5.3.0, supports-color@^5.4.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + +svgo@^1.0.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" + integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== + dependencies: + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.37" + csso "^4.0.2" + js-yaml "^3.13.1" + mkdirp "~0.5.1" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" + +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + +tapable@^1.0.0, tapable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + +tar-stream@^1.5.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + +temp-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" + integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= + +tempfile@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-2.0.0.tgz#6b0446856a9b1114d1856ffcbe509cccb0977265" + integrity sha1-awRGhWqbERTRhW/8vlCczLCXcmU= + dependencies: + temp-dir "^1.0.0" + uuid "^3.0.1" + +terser-webpack-plugin@^1.1.0: + version "1.4.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" + integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA== + dependencies: + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" + schema-utils "^1.0.0" + serialize-javascript "^2.1.2" + source-map "^0.6.1" + terser "^4.1.2" + webpack-sources "^1.4.0" + worker-farm "^1.7.0" + +terser-webpack-plugin@^1.4.3: + version "1.4.4" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz#2c63544347324baafa9a56baaddf1634c8abfc2f" + integrity sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA== + dependencies: + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" + schema-utils "^1.0.0" + serialize-javascript "^3.1.0" + source-map "^0.6.1" + terser "^4.1.2" + webpack-sources "^1.4.0" + worker-farm "^1.7.0" + +terser@^4.1.2: + version "4.8.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" + integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through@^2.3.6, through@^2.3.8, through@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +timed-out@^4.0.0, timed-out@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= + +timers-browserify@^2.0.4: + version "2.0.11" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" + integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== + dependencies: + setimmediate "^1.0.4" + +timm@^1.6.1: + version "1.6.2" + resolved "https://registry.yarnpkg.com/timm/-/timm-1.6.2.tgz#dfd8c6719f7ba1fcfc6295a32670a1c6d166c0bd" + integrity sha512-IH3DYDL1wMUwmIlVmMrmesw5lZD6N+ZOAFWEyLrtpoL9Bcrs9u7M/vyOnHzDD2SMs4irLkVjqxZbHrXStS/Nmw== + +timsort@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= + +tinycolor2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8" + integrity sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g= + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= + +trim-repeated@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" + integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE= + dependencies: + escape-string-regexp "^1.0.2" + +trim@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= + +tryer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" + integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== + +tslib@^1.8.1, tslib@^1.9.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" + integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== + +tsutils@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" + integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== + dependencies: + tslib "^1.8.1" + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" + integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== + +type-fest@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2" + integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +type-is@~1.6.17, type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +typescript@3.9.3: + version "3.9.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.3.tgz#d3ac8883a97c26139e42df5e93eeece33d610b8a" + integrity sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ== + +uglify-js@3.4.x: + version "3.4.10" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f" + integrity sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw== + dependencies: + commander "~2.19.0" + source-map "~0.6.1" + +uglify-template-string-loader@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/uglify-template-string-loader/-/uglify-template-string-loader-1.1.1.tgz#d091d15f66b65f1cae2f4222583009302c86339f" + integrity sha512-EHJx8m0aIHlwX5xlJd2xPYIFvLrPkVK5X8zpVxSNTmu7KoT2eSg1TNlwZS+JS65+dwJXC4rC5mc+F4UVe2rckw== + +unbzip2-stream@^1.0.9: + version "1.4.1" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.1.tgz#151b104af853df3efdaa135d8b1eca850a44b426" + integrity sha512-sgDYfSDPMsA4Hr2/w7vOlrJBlwzmyakk1+hW8ObLvxSp0LA36LcL2XItGvOT3OSblohSdevMuT8FQjLsqyy4sA== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" + integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= + +uniqs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" + integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== + dependencies: + imurmurhash "^0.1.4" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +unused-files-webpack-plugin@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/unused-files-webpack-plugin/-/unused-files-webpack-plugin-3.4.0.tgz#adc67a3b5549d028818d3119cbf2b5c88aea8670" + integrity sha512-cmukKOBdIqaM1pqThY0+jp+mYgCVyzrD8uRbKEucQwIGZcLIRn+gSRiQ7uLjcDd3Zba9NUxVGyYa7lWM4UCGeg== + dependencies: + babel-runtime "^7.0.0-beta.3" + glob-all "^3.1.0" + semver "^5.5.0" + util.promisify "^1.0.0" + warning "^3.0.0" + +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + +upper-case@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" + integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= + dependencies: + prepend-http "^1.0.1" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + +url-to-options@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" + integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +utif@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/utif/-/utif-2.0.1.tgz#9e1582d9bbd20011a6588548ed3266298e711759" + integrity sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg== + dependencies: + pako "^1.0.5" + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util.promisify@^1.0.0, util.promisify@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" + integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.2" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@^3.0.1: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +v8-compile-cache@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" + integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w== + +v8-compile-cache@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" + integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +vendors@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" + integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== + +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + +warning@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" + integrity sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w= + dependencies: + loose-envify "^1.0.0" + +watchpack-chokidar2@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" + integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== + dependencies: + chokidar "^2.1.8" + +watchpack@^1.6.1: + version "1.7.2" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.2.tgz#c02e4d4d49913c3e7e122c3325365af9d331e9aa" + integrity sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g== + dependencies: + graceful-fs "^4.1.2" + neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.0" + watchpack-chokidar2 "^2.0.0" + +webpack-bundle-analyzer@^3.0.3: + version "3.7.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.7.0.tgz#84da434e89442899b884d9ad38e466d0db02a56f" + integrity sha512-mETdjZ30a3Yf+NTB/wqTgACK7rAYQl5uxKK0WVTNmF0sM3Uv8s3R58YZMW7Rhu0Lk2Rmuhdj5dcH5Q76zCDVdA== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + bfj "^6.1.1" + chalk "^2.4.1" + commander "^2.18.0" + ejs "^2.6.1" + express "^4.16.3" + filesize "^3.6.1" + gzip-size "^5.0.0" + lodash "^4.17.15" + mkdirp "^0.5.1" + opener "^1.5.1" + ws "^6.0.0" + +webpack-cli@^3.1.0: + version "3.3.11" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.11.tgz#3bf21889bf597b5d82c38f215135a411edfdc631" + integrity sha512-dXlfuml7xvAFwYUPsrtQAA9e4DOe58gnzSxhgrO/ZM/gyXTBowrsYeubyN4mqGhYdpXMFNyQ6emjJS9M7OBd4g== + dependencies: + chalk "2.4.2" + cross-spawn "6.0.5" + enhanced-resolve "4.1.0" + findup-sync "3.0.0" + global-modules "2.0.0" + import-local "2.0.0" + interpret "1.2.0" + loader-utils "1.2.3" + supports-color "6.1.0" + v8-compile-cache "2.0.3" + yargs "13.2.4" + +webpack-deep-scope-plugin@^1.6.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/webpack-deep-scope-plugin/-/webpack-deep-scope-plugin-1.6.2.tgz#131eac79739021e42ebc07066ea8869107f37b85" + integrity sha512-S5ZM1i7oTIVPIS1z/Fu41tqFzaXpy8vZnwEDC9I7NLj5XD8GGrDZbDXtG5FCGkHPGxtAzF4O21DKZZ76vpBGzw== + dependencies: + deep-scope-analyser "^1.7.0" + +webpack-plugin-replace@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/webpack-plugin-replace/-/webpack-plugin-replace-1.2.0.tgz#3f20db96237400433231e35ea76d9be3f7128916" + integrity sha512-1HA3etHpJW55qonJqv84o5w5GY7iqF8fqSHpTWdNwarj1llkkt4jT4QSvYs1hoaU8Lu5akDnq/spHHO5mXwo1w== + +webpack-sources@^1.4.0, webpack-sources@^1.4.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack-strip-block@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/webpack-strip-block/-/webpack-strip-block-0.2.0.tgz#c60d4a703e0eeee8895e7f1abe9b5fe914681470" + integrity sha1-xg1KcD4O7uiJXn8avptf6RRoFHA= + dependencies: + loader-utils "^1.1.0" + +webpack@^4.43.0: + version "4.43.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.43.0.tgz#c48547b11d563224c561dad1172c8aa0b8a678e6" + integrity sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + acorn "^6.4.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" + enhanced-resolve "^4.1.0" + eslint-scope "^4.0.3" + json-parse-better-errors "^1.0.2" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.3" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" + schema-utils "^1.0.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.6.1" + webpack-sources "^1.4.1" + +whatwg-fetch@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" + integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@^1.2.14, which@^1.2.9, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +worker-farm@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" + integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== + dependencies: + errno "~0.1.7" + +worker-loader@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/worker-loader/-/worker-loader-2.0.0.tgz#45fda3ef76aca815771a89107399ee4119b430ac" + integrity sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw== + dependencies: + loader-utils "^1.0.0" + schema-utils "^0.4.0" + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + +ws@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== + dependencies: + async-limiter "~1.0.0" + +xhr@^2.0.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" + integrity sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ== + dependencies: + global "~4.3.0" + is-function "^1.0.1" + parse-headers "^2.0.0" + xtend "^4.0.0" + +xml-parse-from-string@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" + integrity sha1-qQKekp09vN7RafPG4oI42VpdWig= + +xml2js@^0.4.5: + version "0.4.23" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" + integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yaml-js@^0.1.3: + version "0.1.5" + resolved "https://registry.yarnpkg.com/yaml-js/-/yaml-js-0.1.5.tgz#a01369010b3558d8aaed2394615dfd0780fd8fac" + integrity sha1-oBNpAQs1WNiq7SOUYV39B4D9j6w= + +yaml@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" + integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== + +yargs-parser@^13.1.0: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^18.1.1: + version "18.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.2.tgz#2f482bea2136dbde0861683abea7756d30b504f1" + integrity sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@13.2.4: + version "13.2.4" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" + integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + os-locale "^3.1.0" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.0" + +yargs@^15.3.1: + version "15.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" + integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.1" + +yarn@^1.22.4: + version "1.22.4" + resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.4.tgz#01c1197ca5b27f21edc8bc472cd4c8ce0e5a470e" + integrity sha512-oYM7hi/lIWm9bCoDMEWgffW8aiNZXCWeZ1/tGy0DWrN6vmzjCXIKu2Y21o8DYVBUtiktwKcNoxyGl/2iKLUNGA== + +yauzl@^2.4.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + +yawn-yaml@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/yawn-yaml/-/yawn-yaml-1.5.0.tgz#95fba7544d5375fce3dc84514f12218ed0d2ebcb" + integrity sha512-sH2zX9K1QiWhWh9U19pye660qlzrEAd5c4ebw/6lqz17LZw7xYi7nqXlBoVLVtc2FZFXDKiJIsvVcKGYbLVyFQ== + dependencies: + js-yaml "^3.4.2" + lodash "^4.17.11" + yaml-js "^0.1.3"