diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 00000000..9a3e06f4 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[{src, translations}/*] +end_of_line = crlf +insert_final_newline = true +indent_style = space +indent_size = 4 +charset = utf-8 \ No newline at end of file diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 61b4b3c3..00000000 --- a/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -*.wav filter=lfs diff=lfs merge=lfs -text -*.webm filter=lfs diff=lfs merge=lfs -text -*.mp3 filter=lfs diff=lfs merge=lfs -text -*.psd filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4dffdc7..40053d64 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,23 @@ jobs: cd gulp/ yarn cd .. - - name: Lint run: | yarn lint + - name: TSLint + run: | + cd gulp + yarn gulp translations.fullBuild + cd .. + yarn tslint + + yaml-lint: + name: yaml-lint + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v2 + - name: YAML Lint + uses: ibiqlik/action-yamllint@v1.0.0 + with: + file_or_dir: translations/*.yaml diff --git a/.gitignore b/.gitignore index 3c599ecc..a0e08a62 100644 --- a/.gitignore +++ b/.gitignore @@ -15,34 +15,11 @@ pids *.seed *.pid.lock -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - # Compiled binary addons (https://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ # TypeScript cache *.tsbuildinfo @@ -53,18 +30,9 @@ typings/ # Optional eslint cache .eslintcache -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - # Optional REPL history .node_repl_history -# Output of 'npm pack' -*.tgz - # Yarn Integrity file .yarn-integrity @@ -72,47 +40,13 @@ typings/ .env .env.test -# parcel-bundler cache (https://parceljs.org/) -.cache - -# Next.js build output -.next - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and *not* Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - - # Buildfiles build +res_built +gulp/runnable-texturepacker.jar tmp_standalone_files - -# Github Actions files -.github/workflows - # Local config config.local.js .DS_Store diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile new file mode 100644 index 00000000..41956947 --- /dev/null +++ b/.gitpod.Dockerfile @@ -0,0 +1,4 @@ +FROM gitpod/workspace-full + +RUN sudo apt-get update \ + && sudo apt install ffmpeg -yq diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 00000000..18373c95 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,10 @@ +image: + file: .gitpod.Dockerfile +tasks: + - init: yarn && gp sync-done boot + - before: cd gulp + init: gp sync-await boot && yarn + command: yarn gulp +ports: + - port: 3005 + onOpen: open-preview 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..bb79d866 --- /dev/null +++ b/.yamllint @@ -0,0 +1,7 @@ +extends: default + +rules: + line-length: + level: warning + max: 200 + document-start: disable diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..61d54684 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,31 @@ +FROM node:12 as base + +EXPOSE 3001 3005 + +WORKDIR /shapez.io + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ffmpeg default-jre \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +COPY package.json yarn.lock ./ +RUN yarn + +COPY gulp ./gulp +WORKDIR /shapez.io/gulp +RUN yarn + +WORKDIR /shapez.io +COPY res ./res +COPY src/html ./src/html +COPY src/css ./src/css +COPY version ./version +COPY sync-translations.js ./ +COPY translations ./translations +COPY src/js ./src/js +COPY res_raw ./res_raw +COPY .git ./.git + +WORKDIR /shapez.io/gulp +ENTRYPOINT ["yarn", "gulp"] diff --git a/README.md b/README.md index 5a5847aa..85b5d26b 100644 --- a/README.md +++ b/README.md @@ -11,17 +11,35 @@ 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 -- Run `git lfs pull` to download sound assets - Make sure `ffmpeg` is on your path - Install Node.js and Yarn +- Install Java (required for textures) - Run `yarn` in the root folder - Cd into `gulp` folder - Run `yarn` and then `yarn gulp` - it should now open in your browser -**Notice**: This will produce a debug build with several debugging flags enabled. If you want to disable them, modify `config.js`. +**Notice**: This will produce a debug build with several debugging flags enabled. If you want to disable them, modify [`src/js/core/config.js`](src/js/core/config.js). + +## Build Online with one-click setup + +You can use [Gitpod](https://www.gitpod.io/) (an Online Open Source VS Code-like IDE which is free for Open Source) for working on issues and making PRs to this project. With a single click it will start a workspace and automatically: + +- clone the `shapez.io` repo. +- install all of the dependencies. +- start `gulp` in `gulp/` directory. + +[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/from-referrer/) ## Helping translate @@ -41,15 +59,74 @@ 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 component 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/resources.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. + +#### Checklist for a new building / testing it + +This is a quick checklist, if a new building is added this points should be fulfilled: + +2. The translation for all variants is done and finalized +3. The artwork (regular sprite) is finalized +4. The blueprint sprite has been generated and is up to date +5. The building has been added to the appropriate toolbar +6. The building has a keybinding which makes sense +7. The building has a reward assigned and is unlocked at a meaningful point +8. The reward for the building has a proper translation +9. The reward for the building has a proper image +10. The building has a proper tutorial image assigned +11. The buliding has a proper toolbar icon +12. The reward requires a proper shape +13. The building has a proper silhouette color +14. The building has a proper matrix for being rendered on the minimap +15. The building has proper statistics in the dialog +16. The building properly contributes to the shapes produced analytics +17. The building is properly persisted in the savegame +18. The building is explained properly, ideally via an interactive tutorial + ### Assets -For most assets I use Adobe Photoshop, you can find them in `assets/`. +For most assets I use Adobe Photoshop, you can find them here. -You will need a Texture Packer license in order to regenerate the atlas. If you don't have one but want to contribute assets, let me know and I might compile it for you. I'm currently switching to an open source solution but I can't give an estimate when thats done. +All assets will be automatically rebuilt into the atlas once changed (Thanks to dengr1065!) shapez.io Screenshot diff --git a/artwork/README.md b/artwork/README.md deleted file mode 100644 index dab59a98..00000000 --- a/artwork/README.md +++ /dev/null @@ -1,3 +0,0 @@ -The artwork can be found here: - -https://github.com/tobspr/shapez.io-artwork diff --git a/electron/package.json b/electron/package.json index a67249a0..c8d3a124 100644 --- a/electron/package.json +++ b/electron/package.json @@ -1,16 +1,16 @@ -{ - "name": "electron", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "private": true, - "scripts": { - "startDev": "electron --disable-direct-composition --in-process-gpu . --dev --local", - "startDevGpu": "electron --enable-gpu-rasterization --enable-accelerated-2d-canvas --num-raster-threads=8 --enable-zero-copy . --dev --local", - "start": "electron --disable-direct-composition --in-process-gpu ." - }, - "devDependencies": { - "electron": "^6.1.12" - }, - "dependencies": {} -} +{ + "name": "electron", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "private": true, + "scripts": { + "startDev": "electron --disable-direct-composition --in-process-gpu . --dev --local", + "startDevGpu": "electron --enable-gpu-rasterization --enable-accelerated-2d-canvas --num-raster-threads=8 --enable-zero-copy . --dev --local", + "start": "electron --disable-direct-composition --in-process-gpu ." + }, + "devDependencies": { + "electron": "10.1.3" + }, + "dependencies": {} +} diff --git a/electron/yarn.lock b/electron/yarn.lock index 01214c92..fa92ec46 100644 --- a/electron/yarn.lock +++ b/electron/yarn.lock @@ -1,961 +1,572 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@types/node@^10.12.18": - version "10.17.24" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.24.tgz#c57511e3a19c4b5e9692bb2995c40a3a52167944" - integrity sha512-5SCfvCxV74kzR3uWgTYiGxrd69TbT1I6+cMx1A5kEly/IVveJBimtAMlXiEyVFn5DvUFewQWxOOiJhlxeQwxgA== - -ajv@^6.5.5: - 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" - -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= - -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= - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" - integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -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== - -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= - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -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= - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -concat-stream@1.6.2: - 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" - -core-util-is@1.0.2, 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= - -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" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -debug@2.6.9, debug@^2.1.3, debug@^2.2.0: - 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@^3.0.0: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -decamelize@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -electron-download@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-4.1.1.tgz#02e69556705cc456e520f9e035556ed5a015ebe8" - integrity sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg== - dependencies: - debug "^3.0.0" - env-paths "^1.0.0" - fs-extra "^4.0.1" - minimist "^1.2.0" - nugget "^2.0.1" - path-exists "^3.0.0" - rc "^1.2.1" - semver "^5.4.1" - sumchecker "^2.0.2" - -electron@^6.1.12: - version "6.1.12" - resolved "https://registry.yarnpkg.com/electron/-/electron-6.1.12.tgz#a7aee6dfa75b57f32b3645ef8e14dcef6d5f31a9" - integrity sha512-RUPM8xJfTcm53V9EKMBhvpLu1+CQkmuvWDmVCypR5XbUG1OOrOLiKl0CqUZ9+tEDuOmC+DmzmJP2MZXScBU5IA== - dependencies: - "@types/node" "^10.12.18" - electron-download "^4.1.0" - extract-zip "^1.0.3" - -env-paths@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0" - integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA= - -error-ex@^1.2.0: - 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" - -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extract-zip@^1.0.3: - version "1.6.7" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9" - integrity sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k= - dependencies: - concat-stream "1.6.2" - debug "2.6.9" - mkdirp "0.5.1" - yauzl "2.4.1" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -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-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== - -fd-slicer@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" - integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU= - dependencies: - pend "~1.2.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" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -fs-extra@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.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= - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -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-fs@^4.1.6: - version "4.2.2" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" - integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== - dependencies: - ajv "^6.5.5" - har-schema "^2.0.0" - -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== - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -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" - -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== - -ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -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-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-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -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= - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -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-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= - optionalDependencies: - graceful-fs "^4.1.6" - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.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" - -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" - -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= - -meow@^3.1.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" - -mime-db@1.44.0: - version "1.44.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" - integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== - -mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.27" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" - integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== - dependencies: - mime-db "1.44.0" - -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.0, minimist@^1.1.3, minimist@^1.2.0: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -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" - -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.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -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" - -nugget@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nugget/-/nugget-2.0.1.tgz#201095a487e1ad36081b3432fa3cada4f8d071b0" - integrity sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA= - dependencies: - debug "^2.1.3" - minimist "^1.1.0" - pretty-bytes "^1.0.2" - progress-stream "^1.1.0" - request "^2.45.0" - single-line-log "^1.1.2" - throttleit "0.0.2" - -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= - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-assign@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-keys@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= - -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" - -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-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-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" - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -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= - -pretty-bytes@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-1.0.4.tgz#0a22e8210609ad35542f8c8d5d2159aff0751c84" - integrity sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ= - dependencies: - get-stdin "^4.0.1" - meow "^3.1.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== - -progress-stream@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/progress-stream/-/progress-stream-1.2.0.tgz#2cd3cfea33ba3a89c9c121ec3347abe9ab125f77" - integrity sha1-LNPP6jO6OonJwSHsM0er6asSX3c= - dependencies: - speedometer "~0.1.2" - through2 "~0.2.3" - -psl@^1.1.28: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -rc@^1.2.1: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -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@^2.2.2: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - 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@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -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" - -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" - -request@^2.45.0: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -resolve@^1.10.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== - dependencies: - path-parse "^1.0.6" - -safe-buffer@^5.0.1, safe-buffer@^5.1.2: - 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-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== - -safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -"semver@2 || 3 || 4 || 5", semver@^5.4.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -signal-exit@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== - -single-line-log@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/single-line-log/-/single-line-log-1.1.2.tgz#c2f83f273a3e1a16edb0995661da0ed5ef033364" - integrity sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q= - dependencies: - string-width "^1.0.1" - -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.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - 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== - -speedometer@~0.1.2: - version "0.1.4" - resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d" - integrity sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0= - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -string-width@^1.0.1: - 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_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - -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-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-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@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -sumchecker@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-2.0.2.tgz#0f42c10e5d05da5d42eea3e56c3399a37d6c5b3e" - integrity sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4= - dependencies: - debug "^2.2.0" - -throttleit@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf" - integrity sha1-z+34jmDADdlpe2H90qg0OptoDq8= - -through2@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f" - integrity sha1-6zKE2k6jEbbMis42U3SKUqvyWj8= - dependencies: - readable-stream "~1.1.9" - xtend "~2.1.1" - -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -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= - -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" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -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== - -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" - -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= - -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -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" - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -xtend@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= - dependencies: - object-keys "~0.4.0" - -yauzl@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" - integrity sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU= - dependencies: - fd-slicer "~1.0.1" +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@electron/get@^1.0.1": + version "1.12.2" + resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.12.2.tgz#6442066afb99be08cefb9a281e4b4692b33764f3" + integrity sha512-vAuHUbfvBQpYTJ5wB7uVIDq5c/Ry0fiTBMs7lnEYAo/qXXppIVcWdfBr57u6eRnKdVso7KSiH6p/LbQAG6Izrg== + dependencies: + debug "^4.1.1" + env-paths "^2.2.0" + fs-extra "^8.1.0" + got "^9.6.0" + progress "^2.0.3" + sanitize-filename "^1.6.2" + sumchecker "^3.0.1" + optionalDependencies: + global-agent "^2.0.2" + global-tunnel-ng "^2.7.1" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@types/node@^12.0.12": + version "12.12.62" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.62.tgz#733923d73669188d35950253dd18a21570085d2b" + integrity sha512-qAfo81CsD7yQIM9mVyh6B/U47li5g7cfpVQEDMfQeF8pSZVwzbhwU3crc0qG4DmpsebpJPR49AKOExQyJ05Cpg== + +boolean@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.1.tgz#35ecf2b4a2ee191b0b44986f14eb5f052a5cbb4f" + integrity sha512-HRZPIjPcbwAVQvOTxR4YE3o8Xs98NqbbL1iEZDCz7CL8ql0Lt5iOyJFxfnAB0oFs8Oh02F/lLlg30Mexv46LjA== + +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== + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +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" + +concat-stream@1.6.2: + 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" + +core-js@^3.6.5: + 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-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= + +debug@2.6.9: + 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.0, debug@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + dependencies: + ms "2.1.2" + +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" + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + +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" + +detect-node@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" + integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +electron@10.1.3: + version "10.1.3" + resolved "https://registry.yarnpkg.com/electron/-/electron-10.1.3.tgz#7e276e373bf30078bd4cb1184850a91268dc0e6c" + integrity sha512-CR8LrlG47MdAp317SQ3vGYa2o2cIMdMSMPYH46OVitFLk35dwE9fn3VqvhUIXhCHYcNWIAPzMhkVHpkoFdKWuw== + dependencies: + "@electron/get" "^1.0.1" + "@types/node" "^12.0.12" + extract-zip "^1.0.3" + +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.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" + +env-paths@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" + integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== + +es6-error@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +extract-zip@^1.0.3: + version "1.6.7" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9" + integrity sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k= + dependencies: + concat-stream "1.6.2" + debug "2.6.9" + mkdirp "0.5.1" + yauzl "2.4.1" + +fd-slicer@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" + integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU= + dependencies: + pend "~1.2.0" + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +get-stream@^4.1.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-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +global-agent@^2.0.2: + version "2.1.12" + resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-2.1.12.tgz#e4ae3812b731a9e81cbf825f9377ef450a8e4195" + integrity sha512-caAljRMS/qcDo69X9BfkgrihGUgGx44Fb4QQToNQjsiWh+YlQ66uqYVAdA8Olqit+5Ng0nkz09je3ZzANMZcjg== + dependencies: + boolean "^3.0.1" + core-js "^3.6.5" + es6-error "^4.1.1" + matcher "^3.0.0" + roarr "^2.15.3" + semver "^7.3.2" + serialize-error "^7.0.1" + +global-tunnel-ng@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz#d03b5102dfde3a69914f5ee7d86761ca35d57d8f" + integrity sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg== + dependencies: + encodeurl "^1.0.2" + lodash "^4.17.10" + npm-conf "^1.1.3" + tunnel "^0.0.6" + +globalthis@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.1.tgz#40116f5d9c071f9e8fb0037654df1ab3a83b7ef9" + integrity sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw== + dependencies: + define-properties "^1.1.3" + +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +graceful-fs@^4.1.6: + version "4.2.2" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" + integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== + +graceful-fs@^4.2.0: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + +inherits@^2.0.3, 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== + +ini@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +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-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +lodash@^4.17.10: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +matcher@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca" + integrity sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng== + dependencies: + escape-string-regexp "^4.0.0" + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +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" + +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.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +normalize-url@^4.1.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" + integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== + +npm-conf@^1.1.3: + 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" + +object-keys@^1.0.12: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +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" + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + +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= + +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= + +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== + +progress@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +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= + +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" + +readable-stream@^2.2.2: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + 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" + +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" + +roarr@^2.15.3: + version "2.15.4" + resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.4.tgz#f5fe795b7b838ccfe35dc608e0282b9eba2e7afd" + integrity sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A== + dependencies: + boolean "^3.0.1" + detect-node "^2.0.4" + globalthis "^1.0.1" + json-stringify-safe "^5.0.1" + semver-compare "^1.0.0" + sprintf-js "^1.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== + +sanitize-filename@^1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378" + integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== + dependencies: + truncate-utf8-bytes "^1.0.0" + +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + +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== + +serialize-error@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18" + integrity sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw== + dependencies: + type-fest "^0.13.1" + +sprintf-js@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" + integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== + +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" + +sumchecker@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42" + integrity sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg== + dependencies: + debug "^4.1.0" + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +truncate-utf8-bytes@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" + integrity sha1-QFkjkJWS1W94pYGENLC3hInKXys= + dependencies: + utf8-byte-length "^1.0.1" + +tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + +type-fest@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" + integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +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== + +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" + +utf8-byte-length@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" + integrity sha1-9F8VDExm7uloGGUFq5P8u4rWv2E= + +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= + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +yauzl@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" + integrity sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU= + dependencies: + fd-slicer "~1.0.1" diff --git a/gulp/.gitattributes b/gulp/.gitattributes deleted file mode 100644 index d899f655..00000000 --- a/gulp/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.wav filter=lfs diff=lfs merge=lfs -text diff --git a/gulp/.gitignore b/gulp/.gitignore index aa92ef40..80dc3c89 100644 --- a/gulp/.gitignore +++ b/gulp/.gitignore @@ -1,2 +1 @@ -additional_build_files -steampipe +additional_build_files diff --git a/gulp/atlas2json.js b/gulp/atlas2json.js new file mode 100644 index 00000000..b77a47f3 --- /dev/null +++ b/gulp/atlas2json.js @@ -0,0 +1,127 @@ +const { join, resolve } = require("path"); +const { readFileSync, readdirSync, writeFileSync } = require("fs"); + +const suffixToScale = { + lq: "0.25", + mq: "0.5", + hq: "0.75" +}; + +function convert(srcDir) { + const full = resolve(srcDir); + const srcFiles = readdirSync(full) + .filter(n => n.endsWith(".atlas")) + .map(n => join(full, n)); + + for (const atlas of srcFiles) { + console.log(`Processing: ${atlas}`); + + // Read all text, split it into line array + // and filter all empty lines + const lines = readFileSync(atlas, "utf-8") + .split("\n") + .filter(n => n.trim()); + + // Get source image name + const image = lines.shift(); + const srcMeta = {}; + + // Read all metadata (supports only one page) + while (true) { + const kv = lines.shift().split(":"); + if (kv.length != 2) { + lines.unshift(kv[0]); + break; + } + + srcMeta[kv[0]] = kv[1].trim(); + } + + const frames = {}; + let current = null; + + lines.push("Dummy line to make it convert last frame"); + + for (const line of lines) { + if (!line.startsWith(" ")) { + // New frame, convert previous if it exists + if (current != null) { + let { name, rotate, xy, size, orig, offset, index } = current; + + // Convert to arrays because Node.js doesn't + // support latest JS features + xy = xy.split(",").map(v => Number(v)); + size = size.split(",").map(v => Number(v)); + orig = orig.split(",").map(v => Number(v)); + offset = offset.split(",").map(v => Number(v)); + + // GDX TexturePacker removes index suffixes + const indexSuff = index != -1 ? `_${index}` : ""; + const isTrimmed = size != orig; + + frames[`${name}${indexSuff}.png`] = { + // Bounds on atlas + frame: { + x: xy[0], + y: xy[1], + w: size[0], + h: size[1] + }, + + // Whether image was rotated + rotated: rotate == "true", + trimmed: isTrimmed, + + // How is the image trimmed + spriteSourceSize: { + x: offset[0], + y: (orig[1] - size[1]) - offset[1], + w: size[0], + h: size[1] + }, + + sourceSize: { + w: orig[0], + h: orig[1] + } + } + } + + // Simple object that will hold other metadata + current = { + name: line + }; + } else { + // Read and set current image metadata + const kv = line.split(":").map(v => v.trim()); + current[kv[0]] = isNaN(Number(kv[1])) ? kv[1] : Number(kv[1]); + } + } + + const atlasSize = srcMeta.size.split(",").map(v => Number(v)); + const atlasScale = suffixToScale[atlas.match(/_(\w+)\.atlas$/)[1]]; + + const result = JSON.stringify({ + frames, + meta: { + image, + format: srcMeta.format, + size: { + w: atlasSize[0], + h: atlasSize[1] + }, + scale: atlasScale.toString() + } + }); + + writeFileSync(atlas.replace(".atlas", ".json"), result, { + encoding: "utf-8" + }); + } +} + +if (require.main == module) { + convert(process.argv[2]); +} + +module.exports = { convert }; diff --git a/gulp/buildutils.js b/gulp/buildutils.js index 1fb2a9a3..ea253773 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,16 +25,12 @@ 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/")); + getTag() { + try { + return execSync("git describe --tag --exact-match").toString("ascii"); + } catch (e) { + throw new Error('Current git HEAD is not a version tag'); + } }, getVersion() { diff --git a/gulp/convert_atlas.js b/gulp/convert_atlas.js deleted file mode 100644 index 8e0ba990..00000000 --- a/gulp/convert_atlas.js +++ /dev/null @@ -1,96 +0,0 @@ -// Converts the atlas description to a JSON file - -String.prototype.replaceAll = function (search, replacement) { - var target = this; - return target.split(search).join(replacement); -}; - -const fs = require("fs"); -const path = require("path"); - -const folder = path.join(__dirname, "res_built", "atlas"); -const files = fs.readdirSync(folder); - -const metadata = []; - -files.forEach(filename => { - if (filename.endsWith(".atlas")) { - // Read content - - const content = fs.readFileSync(path.join(folder, filename), "ascii"); - - const lines = content.replaceAll("\r", "").replaceAll("\t", "").split("\n"); - - const readLine = () => lines.splice(0, 1)[0]; - const readValue = () => readLine().replaceAll(" ", "").split(":")[1]; - const readVector = () => - readValue() - .split(",") - .map(d => parseInt(d, 10)); - - let maxAtlas = 100; - - atlasLoop: while (maxAtlas-- > 0 && lines.length >= 7) { - const result = { - entries: [], - }; - - // Extract header - const header_fileStart = readLine(); - const header_fileName = readLine(); - const header_size = readVector(); - const header_format = readLine(); - const header_filter = readLine(); - const header_repeat = readLine(); - const baseAtlasName = header_fileName.replace(".png", ""); - - // Store size - result.size = header_size; - - lineLoop: while (lines.length >= 7) { - const entryResult = {}; - - const nextLine = lines[0]; - if (nextLine.length === 0) { - break; - } - - const entry_fileName = readLine() + ".png"; - - const entry_rotate = readValue(); - const entry_xy = readVector(); - const entry_size = readVector(); - const entry_orig = readVector(); - const entry_offset = readVector(); - const entry_index = readValue(); - - entryResult.filename = entry_fileName; - entryResult.xy = entry_xy; - entryResult.size = entry_size; - // entryResult.offset = entry_offset; - - entryResult.origSize = entry_orig; - - let offset = [0, 0]; - - // GDX Atlas packer uses 1 - y coordinates. This sucks, and we have to convert it - offset[0] = entry_offset[0]; - offset[1] = entry_orig[1] - entry_offset[1] - entry_size[1]; - - entryResult.offset = offset; - - result.entries.push(entryResult); - } - - console.log("[Atlas]", "'" + baseAtlasName + "'", "has", result.entries.length, "entries"); - // fs.writeFileSync(path.join(folder, baseAtlasName + ".gen.json"), JSON.stringify(result)); - - metadata.push({ - filename: baseAtlasName + ".png", - entries: result, - }); - } - } -}); - -fs.writeFileSync(path.join(folder, "meta.gen.json"), JSON.stringify(metadata, null, 4)); 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..73a0a7cf 100644 --- a/gulp/css.js +++ b/gulp/css.js @@ -1,101 +1,137 @@ -const path = require("path"); -const buildUtils = require("./buildutils"); - -function gulptasksCSS($, gulp, buildFolder, browserSync) { - // The assets plugin copies the files - const commitHash = buildUtils.getRevision(); - const postcssAssetsPlugin = cachebust => - $.postcssAssets({ - loadPaths: [path.join(buildFolder, "res", "ui")], - basePath: buildFolder, - baseUrl: ".", - cachebuster: cachebust - ? (filePath, urlPathname) => ({ - pathname: buildUtils.cachebust(urlPathname, commitHash), - }) - : "", - }); - - // Postcss configuration - const postcssPlugins = (prod, { cachebust = false }) => { - const plugins = [postcssAssetsPlugin(cachebust)]; - if (prod) { - plugins.unshift( - $.postcssUnprefix(), - $.postcssPresetEnv({ - browsers: ["> 0.1%"], - }) - ); - - plugins.push( - $.cssMqpacker({ - sort: true, - }), - $.cssnano({ - preset: [ - "advanced", - { - cssDeclarationSorter: false, - discardUnused: true, - mergeIdents: false, - reduceIdents: true, - zindex: true, - }, - ], - }), - $.postcssRoundSubpixels() - ); - } - return plugins; - }; - - // Performs linting on css - gulp.task("css.lint", () => { - return gulp - .src(["../src/css/**/*.scss"]) - .pipe($.sassLint({ configFile: ".sasslint.yml" })) - .pipe($.sassLint.format()) - .pipe($.sassLint.failOnError()); - }); - - // Builds the css in dev mode - gulp.task("css.dev", () => { - return gulp - .src(["../src/css/main.scss"]) - .pipe($.plumber()) - .pipe($.sass.sync().on("error", $.sass.logError)) - .pipe($.postcss(postcssPlugins(false, {}))) - .pipe(gulp.dest(buildFolder)) - .pipe(browserSync.stream()); - }); - - // Builds the css in production mode (=minified) - gulp.task("css.prod", () => { - return ( - gulp - .src("../src/css/main.scss", { cwd: __dirname }) - .pipe($.plumber()) - .pipe($.sass.sync({ outputStyle: "compressed" }).on("error", $.sass.logError)) - .pipe($.postcss(postcssPlugins(true, { cachebust: true }))) - // .pipe($.cssbeautify()) - .pipe(gulp.dest(buildFolder)) - ); - }); - - // Builds the css in production mode (=minified), without cachebusting - gulp.task("css.prod-standalone", () => { - return ( - gulp - .src("../src/css/main.scss", { cwd: __dirname }) - .pipe($.plumber()) - .pipe($.sass.sync({ outputStyle: "compressed" }).on("error", $.sass.logError)) - .pipe($.postcss(postcssPlugins(true, { cachebust: false }))) - // .pipe($.cssbeautify()) - .pipe(gulp.dest(buildFolder)) - ); - }); -} - -module.exports = { - gulptasksCSS, -}; +const path = require("path"); +const buildUtils = require("./buildutils"); + +function gulptasksCSS($, gulp, buildFolder, browserSync) { + // The assets plugin copies the files + const commitHash = buildUtils.getRevision(); + const postcssAssetsPlugin = cachebust => + $.postcssAssets({ + loadPaths: [path.join(buildFolder, "res", "ui")], + basePath: buildFolder, + baseUrl: ".", + cachebuster: cachebust + ? (filePath, urlPathname) => ({ + pathname: buildUtils.cachebust(urlPathname, commitHash), + }) + : "", + }); + + // Postcss configuration + const postcssPlugins = (prod, { cachebust = false }) => { + const plugins = [postcssAssetsPlugin(cachebust)]; + if (prod) { + plugins.unshift( + $.postcssUnprefix(), + $.postcssPresetEnv({ + browsers: ["> 0.1%"], + }) + ); + + plugins.push( + $.cssMqpacker({ + sort: true, + }), + $.cssnano({ + preset: [ + "advanced", + { + cssDeclarationSorter: false, + discardUnused: true, + mergeIdents: false, + reduceIdents: true, + zindex: true, + }, + ], + }), + $.postcssRoundSubpixels() + ); + } + return plugins; + }; + + // Performs linting on css + gulp.task("css.lint", () => { + return gulp + .src(["../src/css/**/*.scss"]) + .pipe($.sassLint({ configFile: ".sasslint.yml" })) + .pipe($.sassLint.format()) + .pipe($.sassLint.failOnError()); + }); + + function resourcesTask({ cachebust, isProd }) { + return gulp + .src("../src/css/main.scss", { cwd: __dirname }) + .pipe($.plumber()) + .pipe($.sass.sync().on("error", $.sass.logError)) + .pipe( + $.postcss([ + $.postcssCriticalSplit({ + blockTag: "@load-async", + }), + ]) + ) + .pipe($.rename("async-resources.css")) + .pipe($.postcss(postcssPlugins(isProd, { cachebust }))) + .pipe(gulp.dest(buildFolder)) + .pipe(browserSync.stream()); + } + + // Builds the css resources + gulp.task("css.resources.dev", () => { + return resourcesTask({ cachebust: false, isProd: false }); + }); + + // Builds the css resources in prod (=minified) + gulp.task("css.resources.prod", () => { + return resourcesTask({ cachebust: true, isProd: true }); + }); + + // Builds the css resources in prod (=minified), without cachebusting + gulp.task("css.resources.prod-standalone", () => { + return resourcesTask({ cachebust: false, isProd: true }); + }); + + function mainTask({ cachebust, isProd }) { + return gulp + .src("../src/css/main.scss", { cwd: __dirname }) + .pipe($.plumber()) + .pipe($.sass.sync().on("error", $.sass.logError)) + .pipe( + $.postcss([ + $.postcssCriticalSplit({ + blockTag: "@load-async", + output: "rest", + }), + ]) + ) + .pipe($.postcss(postcssPlugins(isProd, { cachebust }))) + .pipe(gulp.dest(buildFolder)) + .pipe(browserSync.stream()); + } + + // Builds the css main + gulp.task("css.main.dev", () => { + return mainTask({ cachebust: false, isProd: false }); + }); + + // Builds the css main in prod (=minified) + gulp.task("css.main.prod", () => { + return mainTask({ cachebust: true, isProd: true }); + }); + + // Builds the css main in prod (=minified), without cachebusting + gulp.task("css.main.prod-standalone", () => { + return mainTask({ cachebust: false, isProd: true }); + }); + + gulp.task("css.dev", gulp.parallel("css.main.dev", "css.resources.dev")); + gulp.task("css.prod", gulp.parallel("css.main.prod", "css.resources.prod")); + gulp.task( + "css.prod-standalone", + gulp.parallel("css.main.prod-standalone", "css.resources.prod-standalone") + ); +} + +module.exports = { + gulptasksCSS, +}; diff --git a/gulp/entitlements.plist b/gulp/entitlements.plist new file mode 100644 index 00000000..8f574f5f --- /dev/null +++ b/gulp/entitlements.plist @@ -0,0 +1,12 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.debugger + + + diff --git a/gulp/gulpfile.js b/gulp/gulpfile.js index 0db3f729..7b0416ca 100644 --- a/gulp/gulpfile.js +++ b/gulp/gulpfile.js @@ -1,325 +1,335 @@ -/* eslint-disable */ - -require("colors"); - -const gulp = require("gulp"); -const browserSync = require("browser-sync").create({}); -const path = require("path"); -const deleteEmpty = require("delete-empty"); -const execSync = require("child_process").execSync; - -const lfsOutput = execSync("git lfs install", { encoding: "utf-8" }); -if (!lfsOutput.toLowerCase().includes("git lfs initialized")) { - console.error(` - Git LFS is not installed, unable to build. - - To install Git LFS on Linux: - - Arch: - sudo pacman -S git-lfs - - Debian/Ubuntu: - sudo apt install git-lfs - - For other systems, see: - https://github.com/git-lfs/git-lfs/wiki/Installation - `); - process.exit(1); -} - -// Load other plugins dynamically -const $ = require("gulp-load-plugins")({ - scope: ["devDependencies"], - pattern: "*", -}); - -// Check environment variables - -const envVars = [ - "SHAPEZ_CLI_SERVER_HOST", - // "SHAPEZ_CLI_PHONEGAP_KEY", - "SHAPEZ_CLI_ALPHA_FTP_USER", - "SHAPEZ_CLI_ALPHA_FTP_PW", - "SHAPEZ_CLI_STAGING_FTP_USER", - "SHAPEZ_CLI_STAGING_FTP_PW", - "SHAPEZ_CLI_LIVE_FTP_USER", - "SHAPEZ_CLI_LIVE_FTP_PW", -]; - -for (let i = 0; i < envVars.length; ++i) { - if (!process.env[envVars[i]]) { - console.warn("Please set", envVars[i]); - // process.exit(1); - } -} - -const baseDir = path.join(__dirname, ".."); -const buildFolder = path.join(baseDir, "build"); - -const imgres = require("./image-resources"); -imgres.gulptasksImageResources($, gulp, buildFolder); - -const css = require("./css"); -css.gulptasksCSS($, gulp, buildFolder, browserSync); - -const sounds = require("./sounds"); -sounds.gulptasksSounds($, gulp, buildFolder); - -const js = require("./js"); -js.gulptasksJS($, gulp, buildFolder, browserSync); - -const html = require("./html"); -html.gulptasksHTML($, gulp, buildFolder, browserSync); - -const ftp = require("./ftp"); -ftp.gulptasksFTP($, gulp, buildFolder); - -const docs = require("./docs"); -docs.gulptasksDocs($, gulp, buildFolder); - -const standalone = require("./standalone"); -standalone.gulptasksStandalone($, gulp, buildFolder); - -const translations = require("./translations"); -translations.gulptasksTranslations($, gulp, buildFolder); - -// FIXME -// const cordova = require("./cordova"); -// cordova.gulptasksCordova($, gulp, buildFolder); - -///////////////////// BUILD TASKS ///////////////////// - -// Cleans up everything -gulp.task("utils.cleanBuildFolder", () => { - return gulp.src(buildFolder, { read: false, allowEmpty: true }).pipe($.clean({ force: true })); -}); -gulp.task("utils.cleanBuildTempFolder", () => { - return gulp - .src(path.join(__dirname, "..", "src", "js", "built-temp"), { read: false, allowEmpty: true }) - .pipe($.clean({ force: true })); -}); - -gulp.task("utils.cleanup", gulp.series("utils.cleanBuildFolder", "utils.cleanBuildTempFolder")); - -// Requires no uncomitted files -gulp.task("utils.requireCleanWorkingTree", cb => { - let output = $.trim(execSync("git status -su").toString("ascii")).replace(/\r/gi, "").split("\n"); - - // Filter files which are OK to be untracked - output = output - .map(x => x.replace(/[\r\n]+/gi, "")) - .filter(x => x.indexOf(".local.js") < 0) - .filter(x => x.length > 0); - if (output.length > 0) { - console.error("\n\nYou have unstaged changes, please commit everything first!"); - console.error("Unstaged files:"); - console.error(output.map(x => "'" + x + "'").join("\n")); - process.exit(1); - } - cb(); -}); - -gulp.task("utils.copyAdditionalBuildFiles", cb => { - const additionalFolder = path.join("additional_build_files"); - const additionalSrcGlobs = [ - path.join(additionalFolder, "**/*.*"), - path.join(additionalFolder, "**/.*"), - path.join(additionalFolder, "**/*"), - ]; - - return gulp.src(additionalSrcGlobs).pipe(gulp.dest(buildFolder)); -}); - -// Starts a webserver on the built directory (useful for testing prod build) -gulp.task("main.webserver", () => { - return gulp.src(buildFolder).pipe( - $.webserver({ - livereload: { - enable: true, - }, - directoryListing: false, - open: true, - port: 3005, - }) - ); -}); - -function serve({ standalone }) { - browserSync.init({ - server: buildFolder, - port: 3005, - ghostMode: { - clicks: false, - scroll: false, - location: false, - forms: false, - }, - logLevel: "info", - logPrefix: "BS", - online: false, - xip: false, - notify: false, - reloadDebounce: 100, - reloadOnRestart: true, - watchEvents: ["add", "change"], - }); - - // Watch .scss files, those trigger a css rebuild - gulp.watch(["../src/**/*.scss"], gulp.series("css.dev")); - - // Watch .html files, those trigger a html rebuild - gulp.watch("../src/**/*.html", gulp.series(standalone ? "html.standalone-dev" : "html.dev")); - - // Watch sound files - // gulp.watch(["../res_raw/sounds/**/*.mp3", "../res_raw/sounds/**/*.wav"], gulp.series("sounds.dev")); - - // Watch translations - gulp.watch("../translations/**/*.yaml", gulp.series("translations.convertToJson")); - - gulp.watch( - ["../res_raw/sounds/sfx/*.mp3", "../res_raw/sounds/sfx/*.wav"], - gulp.series("sounds.sfx", "sounds.copy") - ); - gulp.watch( - ["../res_raw/sounds/music/*.mp3", "../res_raw/sounds/music/*.wav"], - gulp.series("sounds.music", "sounds.copy") - ); - - // Watch resource files and copy them on change - gulp.watch(imgres.nonImageResourcesGlobs, gulp.series("imgres.copyNonImageResources")); - gulp.watch(imgres.imageResourcesGlobs, gulp.series("imgres.copyImageResources")); - - // Watch .atlas files and recompile the atlas on change - gulp.watch("../res_built/atlas/*.json", gulp.series("imgres.atlas")); - - // Watch the build folder and reload when anything changed - const extensions = ["html", "js", "png", "gif", "jpg", "svg", "mp3", "ico", "woff2", "json"]; - gulp.watch(extensions.map(ext => path.join(buildFolder, "**", "*." + ext))).on("change", function (path) { - return gulp.src(path).pipe(browserSync.reload({ stream: true })); - }); - - gulp.watch("../src/js/built-temp/*.json").on("change", function (path) { - return gulp.src(path).pipe(browserSync.reload({ stream: true })); - }); - - // Start the webpack watching server (Will never return) - if (standalone) { - gulp.series("js.standalone-dev.watch")(() => true); - } else { - gulp.series("js.dev.watch")(() => true); - } -} - -///////////////////// RUNNABLE TASKS ///////////////////// - -// Pre and postbuild -gulp.task("step.baseResources", gulp.series("imgres.allOptimized")); -gulp.task("step.deleteEmpty", cb => { - deleteEmpty.sync(buildFolder); - cb(); -}); - -gulp.task("step.postbuild", gulp.series("imgres.cleanupUnusedCssInlineImages", "step.deleteEmpty")); - -// Builds everything (dev) -gulp.task( - "build.dev", - gulp.series( - "utils.cleanup", - "utils.copyAdditionalBuildFiles", - "imgres.atlas", - "sounds.dev", - "imgres.copyImageResources", - "imgres.copyNonImageResources", - "translations.fullBuild", - "css.dev", - "html.dev" - ) -); - -// Builds everything (standalone -dev) -gulp.task( - "build.standalone.dev", - gulp.series( - "utils.cleanup", - "imgres.atlas", - "sounds.dev", - "imgres.copyImageResources", - "imgres.copyNonImageResources", - "translations.fullBuild", - "js.standalone-dev", - "css.dev", - "html.standalone-dev" - ) -); - -// Builds everything (staging) -gulp.task("step.staging.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.staging")); -gulp.task( - "step.staging.mainbuild", - gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.staging.code") -); -gulp.task("step.staging.all", gulp.series("step.staging.mainbuild", "css.prod", "html.staging")); -gulp.task("build.staging", gulp.series("utils.cleanup", "step.staging.all", "step.postbuild")); - -// Builds everything (prod) -gulp.task("step.prod.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.prod")); -gulp.task( - "step.prod.mainbuild", - gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.prod.code") -); -gulp.task("step.prod.all", gulp.series("step.prod.mainbuild", "css.prod", "html.prod")); -gulp.task("build.prod", gulp.series("utils.cleanup", "step.prod.all", "step.postbuild")); - -// Builds everything (standalone-beta) -gulp.task( - "step.standalone-beta.code", - gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-beta") -); -gulp.task("step.standalone-beta.mainbuild", gulp.parallel("step.baseResources", "step.standalone-beta.code")); -gulp.task( - "step.standalone-beta.all", - gulp.series("step.standalone-beta.mainbuild", "css.prod-standalone", "html.standalone-beta") -); -gulp.task( - "build.standalone-beta", - gulp.series("utils.cleanup", "step.standalone-beta.all", "step.postbuild") -); - -// Builds everything (standalone-prod) -gulp.task( - "step.standalone-prod.code", - gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-prod") -); -gulp.task("step.standalone-prod.mainbuild", gulp.parallel("step.baseResources", "step.standalone-prod.code")); -gulp.task( - "step.standalone-prod.all", - gulp.series("step.standalone-prod.mainbuild", "css.prod-standalone", "html.standalone-prod") -); -gulp.task( - "build.standalone-prod", - gulp.series("utils.cleanup", "step.standalone-prod.all", "step.postbuild") -); - -// Deploying! -gulp.task( - "main.deploy.alpha", - gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.alpha") -); -gulp.task( - "main.deploy.staging", - gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.staging") -); -gulp.task("main.deploy.prod", gulp.series("utils.requireCleanWorkingTree", "build.prod", "ftp.upload.prod")); -gulp.task("main.deploy.all", gulp.series("main.deploy.staging", "main.deploy.prod")); -gulp.task("main.standalone", gulp.series("build.standalone-prod", "standalone.package.prod")); - -// Live-development -gulp.task( - "main.serveDev", - gulp.series("build.dev", () => serve({ standalone: false })) -); -gulp.task( - "main.serveStandalone", - gulp.series("build.standalone.dev", () => serve({ standalone: true })) -); - -gulp.task("default", gulp.series("main.serveDev")); +/* eslint-disable */ + +require("colors"); + +const gulp = require("gulp"); +const browserSync = require("browser-sync").create({}); +const path = require("path"); +const deleteEmpty = require("delete-empty"); +const execSync = require("child_process").execSync; + +// Load other plugins dynamically +const $ = require("gulp-load-plugins")({ + scope: ["devDependencies"], + pattern: "*", +}); + +// Check environment variables + +const envVars = [ + "SHAPEZ_CLI_SERVER_HOST", + // "SHAPEZ_CLI_PHONEGAP_KEY", + "SHAPEZ_CLI_ALPHA_FTP_USER", + "SHAPEZ_CLI_ALPHA_FTP_PW", + "SHAPEZ_CLI_STAGING_FTP_USER", + "SHAPEZ_CLI_STAGING_FTP_PW", + "SHAPEZ_CLI_LIVE_FTP_USER", + "SHAPEZ_CLI_LIVE_FTP_PW", + "SHAPEZ_CLI_APPLE_ID", + "SHAPEZ_CLI_APPLE_CERT_NAME", + "SHAPEZ_CLI_GITHUB_USER", + "SHAPEZ_CLI_GITHUB_TOKEN", +]; + +for (let i = 0; i < envVars.length; ++i) { + if (!process.env[envVars[i]]) { + console.warn("Please set", envVars[i]); + // process.exit(1); + } +} + +const baseDir = path.join(__dirname, ".."); +const buildFolder = path.join(baseDir, "build"); + +const imgres = require("./image-resources"); +imgres.gulptasksImageResources($, gulp, buildFolder); + +const css = require("./css"); +css.gulptasksCSS($, gulp, buildFolder, browserSync); + +const sounds = require("./sounds"); +sounds.gulptasksSounds($, gulp, buildFolder); + +const js = require("./js"); +js.gulptasksJS($, gulp, buildFolder, browserSync); + +const html = require("./html"); +html.gulptasksHTML($, gulp, buildFolder, browserSync); + +const ftp = require("./ftp"); +ftp.gulptasksFTP($, gulp, buildFolder); + +const docs = require("./docs"); +docs.gulptasksDocs($, gulp, buildFolder); + +const standalone = require("./standalone"); +standalone.gulptasksStandalone($, gulp, buildFolder); + +const releaseUploader = require("./release-uploader"); +releaseUploader.gulptasksReleaseUploader($, gulp, buildFolder); + +const translations = require("./translations"); +translations.gulptasksTranslations($, gulp, buildFolder); + +///////////////////// BUILD TASKS ///////////////////// + +// Cleans up everything +gulp.task("utils.cleanBuildFolder", () => { + return gulp.src(buildFolder, { read: false, allowEmpty: true }).pipe($.clean({ force: true })); +}); +gulp.task("utils.cleanBuildTempFolder", () => { + return gulp + .src(path.join(__dirname, "..", "src", "js", "built-temp"), { read: false, allowEmpty: true }) + .pipe($.clean({ force: true })); +}); +gulp.task("utils.cleanImageBuildFolder", () => { + return gulp + .src(path.join(__dirname, "res_built"), { read: false, allowEmpty: true }) + .pipe($.clean({ force: true })); +}); + +gulp.task( + "utils.cleanup", + gulp.series("utils.cleanBuildFolder", "utils.cleanImageBuildFolder", "utils.cleanBuildTempFolder") +); + +// Requires no uncomitted files +gulp.task("utils.requireCleanWorkingTree", cb => { + let output = $.trim(execSync("git status -su").toString("ascii")).replace(/\r/gi, "").split("\n"); + + // Filter files which are OK to be untracked + output = output + .map(x => x.replace(/[\r\n]+/gi, "")) + .filter(x => x.indexOf(".local.js") < 0) + .filter(x => x.length > 0); + if (output.length > 0) { + console.error("\n\nYou have unstaged changes, please commit everything first!"); + console.error("Unstaged files:"); + console.error(output.map(x => "'" + x + "'").join("\n")); + process.exit(1); + } + cb(); +}); + +gulp.task("utils.copyAdditionalBuildFiles", cb => { + const additionalFolder = path.join("additional_build_files"); + const additionalSrcGlobs = [ + path.join(additionalFolder, "**/*.*"), + path.join(additionalFolder, "**/.*"), + path.join(additionalFolder, "**/*"), + ]; + + return gulp.src(additionalSrcGlobs).pipe(gulp.dest(buildFolder)); +}); + +// Starts a webserver on the built directory (useful for testing prod build) +gulp.task("main.webserver", () => { + return gulp.src(buildFolder).pipe( + $.webserver({ + livereload: { + enable: true, + }, + directoryListing: false, + open: true, + port: 3005, + }) + ); +}); + +function serve({ standalone }) { + browserSync.init({ + server: buildFolder, + port: 3005, + ghostMode: { + clicks: false, + scroll: false, + location: false, + forms: false, + }, + logLevel: "info", + logPrefix: "BS", + online: false, + xip: false, + notify: false, + reloadDebounce: 100, + reloadOnRestart: true, + watchEvents: ["add", "change"], + }); + + // Watch .scss files, those trigger a css rebuild + gulp.watch(["../src/**/*.scss"], gulp.series("css.dev")); + + // Watch .html files, those trigger a html rebuild + gulp.watch("../src/**/*.html", gulp.series(standalone ? "html.standalone-dev" : "html.dev")); + + // Watch sound files + // gulp.watch(["../res_raw/sounds/**/*.mp3", "../res_raw/sounds/**/*.wav"], gulp.series("sounds.dev")); + + // Watch translations + gulp.watch("../translations/**/*.yaml", gulp.series("translations.convertToJson")); + + gulp.watch( + ["../res_raw/sounds/sfx/*.mp3", "../res_raw/sounds/sfx/*.wav"], + gulp.series("sounds.sfx", "sounds.copy") + ); + gulp.watch( + ["../res_raw/sounds/music/*.mp3", "../res_raw/sounds/music/*.wav"], + gulp.series("sounds.music", "sounds.copy") + ); + + // Watch resource files and copy them on change + gulp.watch(imgres.rawImageResourcesGlobs, gulp.series("imgres.buildAtlas")); + gulp.watch(imgres.nonImageResourcesGlobs, gulp.series("imgres.copyNonImageResources")); + gulp.watch(imgres.imageResourcesGlobs, gulp.series("imgres.copyImageResources")); + + // Watch .atlas files and recompile the atlas on change + gulp.watch("../res_built/atlas/*.atlas", gulp.series("imgres.atlasToJson")); + gulp.watch("../res_built/atlas/*.json", gulp.series("imgres.atlas")); + + // Watch the build folder and reload when anything changed + const extensions = ["html", "js", "png", "gif", "jpg", "svg", "mp3", "ico", "woff2", "json"]; + gulp.watch(extensions.map(ext => path.join(buildFolder, "**", "*." + ext))).on("change", function (path) { + return gulp.src(path).pipe(browserSync.reload({ stream: true })); + }); + + gulp.watch("../src/js/built-temp/*.json").on("change", function (path) { + return gulp.src(path).pipe(browserSync.reload({ stream: true })); + }); + + // Start the webpack watching server (Will never return) + if (standalone) { + gulp.series("js.standalone-dev.watch")(() => true); + } else { + gulp.series("js.dev.watch")(() => true); + } +} + +///////////////////// RUNNABLE TASKS ///////////////////// + +// Pre and postbuild +gulp.task("step.baseResources", gulp.series("imgres.allOptimized")); +gulp.task("step.deleteEmpty", cb => { + deleteEmpty.sync(buildFolder); + cb(); +}); + +gulp.task("step.postbuild", gulp.series("imgres.cleanupUnusedCssInlineImages", "step.deleteEmpty")); + +// Builds everything (dev) +gulp.task( + "build.dev", + gulp.series( + "utils.cleanup", + "utils.copyAdditionalBuildFiles", + "imgres.buildAtlas", + "imgres.atlasToJson", + "imgres.atlas", + "sounds.dev", + "imgres.copyImageResources", + "imgres.copyNonImageResources", + "translations.fullBuild", + "css.dev", + "html.dev" + ) +); + +// Builds everything (standalone -dev) +gulp.task( + "build.standalone.dev", + gulp.series( + "utils.cleanup", + "imgres.buildAtlas", + "imgres.atlasToJson", + "imgres.atlas", + "sounds.dev", + "imgres.copyImageResources", + "imgres.copyNonImageResources", + "translations.fullBuild", + "css.dev", + "html.standalone-dev" + ) +); + +// Builds everything (staging) +gulp.task("step.staging.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.staging")); +gulp.task( + "step.staging.mainbuild", + gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.staging.code") +); +gulp.task("step.staging.all", gulp.series("step.staging.mainbuild", "css.prod", "html.staging")); +gulp.task("build.staging", gulp.series("utils.cleanup", "step.staging.all", "step.postbuild")); + +// Builds everything (prod) +gulp.task("step.prod.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.prod")); +gulp.task( + "step.prod.mainbuild", + gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.prod.code") +); +gulp.task("step.prod.all", gulp.series("step.prod.mainbuild", "css.prod", "html.prod")); +gulp.task("build.prod", gulp.series("utils.cleanup", "step.prod.all", "step.postbuild")); + +// Builds everything (standalone-beta) +gulp.task( + "step.standalone-beta.code", + gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-beta") +); +gulp.task("step.standalone-beta.mainbuild", gulp.parallel("step.baseResources", "step.standalone-beta.code")); +gulp.task( + "step.standalone-beta.all", + gulp.series("step.standalone-beta.mainbuild", "css.prod-standalone", "html.standalone-beta") +); +gulp.task( + "build.standalone-beta", + gulp.series("utils.cleanup", "step.standalone-beta.all", "step.postbuild") +); + +// Builds everything (standalone-prod) +gulp.task( + "step.standalone-prod.code", + gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-prod") +); +gulp.task("step.standalone-prod.mainbuild", gulp.parallel("step.baseResources", "step.standalone-prod.code")); +gulp.task( + "step.standalone-prod.all", + gulp.series("step.standalone-prod.mainbuild", "css.prod-standalone", "html.standalone-prod") +); +gulp.task( + "build.standalone-prod", + gulp.series("utils.cleanup", "step.standalone-prod.all", "step.postbuild") +); + +// OS X build and release upload +gulp.task( + "build.darwin64-prod", + gulp.series( + "build.standalone-prod", + "standalone.prepare", + "standalone.package.prod.darwin64", + "standalone.uploadRelease.darwin64" + ) +); + +// Deploying! +gulp.task( + "main.deploy.alpha", + gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.alpha") +); +gulp.task( + "main.deploy.staging", + gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.staging") +); +gulp.task("main.deploy.prod", gulp.series("utils.requireCleanWorkingTree", "build.prod", "ftp.upload.prod")); +gulp.task("main.deploy.all", gulp.series("main.deploy.staging", "main.deploy.prod")); +gulp.task("main.standalone", gulp.series("build.standalone-prod", "standalone.package.prod")); + +// Live-development +gulp.task( + "main.serveDev", + gulp.series("build.dev", () => serve({ standalone: false })) +); +gulp.task( + "main.serveStandalone", + gulp.series("build.standalone.dev", () => serve({ standalone: true })) +); + +gulp.task("default", gulp.series("main.serveDev")); diff --git a/gulp/html.js b/gulp/html.js index a21d66cb..0ba58a15 100644 --- a/gulp/html.js +++ b/gulp/html.js @@ -1,336 +1,301 @@ -const buildUtils = require("./buildutils"); -const fs = require("fs"); -const path = require("path"); -const crypto = require("crypto"); - -function computeIntegrityHash(fullPath, algorithm = "sha256") { - const file = fs.readFileSync(fullPath); - const hash = crypto.createHash(algorithm).update(file).digest("base64"); - return algorithm + "-" + hash; -} - -function gulptasksHTML($, gulp, buildFolder, browserSync) { - const commitHash = buildUtils.getRevision(); - async function buildHtml( - apiUrl, - { analytics = false, standalone = false, app = false, integrity = true, enableCachebust = true } - ) { - function cachebust(url) { - if (enableCachebust) { - return buildUtils.cachebust(url, commitHash); - } - return url; - } - - const hasLocalFiles = standalone || app; - - return gulp - .src("../src/html/" + (standalone ? "index.standalone.html" : "index.html")) - .pipe( - $.dom(function () { - // @ts-ignore - const document = /** @type {Document} */ (this); - - // Preconnect to api - const prefetchLink = document.createElement("link"); - prefetchLink.rel = "preconnect"; - prefetchLink.href = apiUrl; - 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"; - css.type = "text/css"; - css.media = "none"; - css.setAttribute("onload", "this.media='all'"); - css.href = cachebust("main.css"); - if (integrity) { - css.setAttribute( - "integrity", - computeIntegrityHash(path.join(buildFolder, "main.css")) - ); - } - 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"); - cdv.src = "cordova.js"; - cdv.type = "text/javascript"; - document.head.appendChild(cdv); - } - - // Google analytics - if (analytics) { - const tagManagerScript = document.createElement("script"); - tagManagerScript.src = "https://www.googletagmanager.com/gtag/js?id=UA-165342524-1"; - tagManagerScript.setAttribute("async", ""); - document.head.appendChild(tagManagerScript); - - const initScript = document.createElement("script"); - initScript.textContent = ` - window.dataLayer = window.dataLayer || []; - function gtag(){dataLayer.push(arguments);} - gtag('js', new Date()); - gtag('config', 'UA-165342524-1', { anonymize_ip: true }); - `; - document.head.appendChild(initScript); - - const abTestingScript = document.createElement("script"); - abTestingScript.setAttribute( - "src", - "https://www.googleoptimize.com/optimize.js?id=OPT-M5NHCV7" - ); - abTestingScript.setAttribute("async", ""); - document.head.appendChild(abTestingScript); - } - - // 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"; - preloadLink.href = cachebust("res/" + src); - if (src.endsWith(".woff2")) { - preloadLink.setAttribute("crossorigin", "anonymous"); - preloadLink.setAttribute("as", "font"); - } else { - preloadLink.setAttribute("as", "image"); - } - 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+")`; - - const loadingCss = ` - @font-face { - font-family: 'GameFont'; - font-style: normal; - font-weight: normal; - font-display: swap; - src: url('${cachebust("res/fonts/GameFont.woff2")}') format('woff2'); - } - - #ll_fp { - font-family: GameFont; - font-size: 14px; - position: fixed; - z-index: -1; - top: 0; - left: 0; - opacity: 0.05; - } - - #ll_p { - display: flex; - position: fixed; - z-index: 99999; - top: 0; - left: 0; - right: 0; - bottom: 0; - justify-content: - center; - align-items: center; - } - - #ll_p > div { - position: absolute; - text-align: center; - bottom: 40px; - left: 20px; - right: 20px; - color: #393747; - font-family: 'GameFont', sans-serif; - font-size: 20px; - } - - #ll_p > span { - width: 60px; - height: 60px; - display: inline-flex; - background: center center / contain no-repeat; - ${loadingSvg}; - } - `; - - const style = document.createElement("style"); - style.setAttribute("type", "text/css"); - style.textContent = loadingCss; - document.head.appendChild(style); - - // Append loader, but not in standalone (directly include bundle there) - if (standalone) { - const bundleScript = document.createElement("script"); - bundleScript.type = "text/javascript"; - bundleScript.src = "bundle.js"; - if (integrity) { - bundleScript.setAttribute( - "integrity", - computeIntegrityHash(path.join(buildFolder, "bundle.js")) - ); - } - document.head.appendChild(bundleScript); - } else { - const loadJs = document.createElement("script"); - loadJs.type = "text/javascript"; - let scriptContent = ""; - scriptContent += `var bundleSrc = '${cachebust("bundle.js")}';\n`; - scriptContent += `var bundleSrcTranspiled = '${cachebust( - "bundle-transpiled.js" - )}';\n`; - - if (integrity) { - scriptContent += - "var bundleIntegrity = '" + - computeIntegrityHash(path.join(buildFolder, "bundle.js")) + - "';\n"; - scriptContent += - "var bundleIntegrityTranspiled = '" + - computeIntegrityHash(path.join(buildFolder, "bundle-transpiled.js")) + - "';\n"; - } else { - scriptContent += "var bundleIntegrity = null;\n"; - scriptContent += "var bundleIntegrityTranspiled = null;\n"; - } - - scriptContent += fs.readFileSync("./bundle-loader.js").toString(); - loadJs.textContent = scriptContent; - document.head.appendChild(loadJs); - } - - const bodyContent = ` -
_
-
- -
${hasLocalFiles ? "Loading" : "Downloading"} Game Files
-
- `; - - document.body.innerHTML = bodyContent; - }) - ) - .pipe( - $.htmlmin({ - caseSensitive: true, - collapseBooleanAttributes: true, - collapseInlineTagWhitespace: true, - collapseWhitespace: true, - preserveLineBreaks: true, - minifyJS: true, - minifyCSS: true, - quoteCharacter: '"', - useShortDoctype: true, - }) - ) - .pipe($.htmlBeautify()) - .pipe($.rename("index.html")) - .pipe(gulp.dest(buildFolder)); - } - - gulp.task("html.dev", () => { - return buildHtml("http://localhost:5005", { - analytics: false, - integrity: false, - enableCachebust: false, - }); - }); - - gulp.task("html.staging", () => { - return buildHtml("https://api-staging.shapez.io", { - analytics: true, - }); - }); - - gulp.task("html.prod", () => { - return buildHtml("https://analytics.shapez.io", { - analytics: true, - }); - }); - - gulp.task("html.standalone-dev", () => { - return buildHtml("https://localhost:5005", { - analytics: false, - standalone: true, - integrity: false, - enableCachebust: false, - }); - }); - - gulp.task("html.standalone-beta", () => { - return buildHtml("https://api-staging.shapez.io", { - analytics: false, - standalone: true, - enableCachebust: false, - }); - }); - - gulp.task("html.standalone-prod", () => { - return buildHtml("https://analytics.shapez.io", { - analytics: false, - standalone: true, - enableCachebust: false, - }); - }); -} - -module.exports = { - gulptasksHTML, -}; +const buildUtils = require("./buildutils"); +const fs = require("fs"); +const path = require("path"); +const crypto = require("crypto"); + +function computeIntegrityHash(fullPath, algorithm = "sha256") { + const file = fs.readFileSync(fullPath); + const hash = crypto.createHash(algorithm).update(file).digest("base64"); + return algorithm + "-" + hash; +} + +function gulptasksHTML($, gulp, buildFolder) { + const commitHash = buildUtils.getRevision(); + async function buildHtml( + apiUrl, + { analytics = false, standalone = false, app = false, integrity = true, enableCachebust = true } + ) { + function cachebust(url) { + if (enableCachebust) { + return buildUtils.cachebust(url, commitHash); + } + return url; + } + + const hasLocalFiles = standalone || app; + + return gulp + .src("../src/html/" + (standalone ? "index.standalone.html" : "index.html")) + .pipe( + $.dom( + /** @this {Document} **/ function () { + const document = this; + + // Preconnect to api + const prefetchLink = document.createElement("link"); + prefetchLink.rel = "preconnect"; + prefetchLink.href = apiUrl; + prefetchLink.setAttribute("crossorigin", "anonymous"); + document.head.appendChild(prefetchLink); + + // Append css + const css = document.createElement("link"); + css.rel = "stylesheet"; + css.type = "text/css"; + css.media = "none"; + css.setAttribute("onload", "this.media='all'"); + css.href = cachebust("main.css"); + if (integrity) { + css.setAttribute( + "integrity", + computeIntegrityHash(path.join(buildFolder, "main.css")) + ); + } + document.head.appendChild(css); + + // Append async css + // const asyncCss = document.createElement("link"); + // asyncCss.rel = "stylesheet"; + // asyncCss.type = "text/css"; + // asyncCss.media = "none"; + // asyncCss.setAttribute("onload", "this.media='all'"); + // asyncCss.href = cachebust("async-resources.css"); + // if (integrity) { + // asyncCss.setAttribute( + // "integrity", + // computeIntegrityHash(path.join(buildFolder, "async-resources.css")) + // ); + // } + // document.head.appendChild(asyncCss); + + if (app) { + // Append cordova link + const cdv = document.createElement("script"); + cdv.src = "cordova.js"; + cdv.type = "text/javascript"; + document.head.appendChild(cdv); + } + + // Google analytics + if (analytics) { + const tagManagerScript = document.createElement("script"); + tagManagerScript.src = + "https://www.googletagmanager.com/gtag/js?id=UA-165342524-1"; + tagManagerScript.setAttribute("async", ""); + document.head.appendChild(tagManagerScript); + + const initScript = document.createElement("script"); + initScript.textContent = ` + window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', 'UA-165342524-1', { anonymize_ip: true }); + `; + document.head.appendChild(initScript); + + const abTestingScript = document.createElement("script"); + abTestingScript.setAttribute( + "src", + "https://www.googleoptimize.com/optimize.js?id=OPT-M5NHCV7" + ); + abTestingScript.setAttribute("async", ""); + document.head.appendChild(abTestingScript); + } + + // Do not need to preload in app or standalone + if (!hasLocalFiles) { + // Preload essentials + const preloads = ["fonts/GameFont.woff2"]; + + preloads.forEach(src => { + const preloadLink = document.createElement("link"); + preloadLink.rel = "preload"; + preloadLink.href = cachebust("res/" + src); + if (src.endsWith(".woff2")) { + preloadLink.setAttribute("crossorigin", "anonymous"); + preloadLink.setAttribute("as", "font"); + } else { + preloadLink.setAttribute("as", "image"); + } + document.head.appendChild(preloadLink); + }); + } + + const loadingSvg = `background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46YXV0bztiYWNrZ3JvdW5kOjAgMCIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCIgZGlzcGxheT0iYmxvY2siPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzM5Mzc0NyIgc3Ryb2tlLXdpZHRoPSIzIiByPSI0MiIgc3Ryb2tlLWRhc2hhcnJheT0iMTk3LjkyMDMzNzE3NjE1Njk4IDY3Ljk3MzQ0NTcyNTM4NTY2IiB0cmFuc2Zvcm09InJvdGF0ZSg0OC4yNjUgNTAgNTApIj48YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIGR1cj0iNS41NTU1NTU1NTU1NTU1NTVzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIi8+PC9jaXJjbGU+PC9zdmc+")`; + + const loadingCss = ` + @font-face { + font-family: 'GameFont'; + font-style: normal; + font-weight: normal; + font-display: swap; + src: url('${cachebust("res/fonts/GameFont.woff2")}') format('woff2'); + } + + #ll_fp { + font-family: GameFont; + font-size: 14px; + position: fixed; + z-index: -1; + top: 0; + left: 0; + opacity: 0.05; + } + + #ll_p { + display: flex; + position: fixed; + z-index: 99999; + top: 0; + left: 0; + right: 0; + bottom: 0; + justify-content: + center; + align-items: center; + } + + #ll_p > div { + position: absolute; + text-align: center; + bottom: 40px; + left: 20px; + right: 20px; + color: #393747; + font-family: 'GameFont', sans-serif; + font-size: 20px; + } + + #ll_p > span { + width: 60px; + height: 60px; + display: inline-flex; + background: center center / contain no-repeat; + ${loadingSvg}; + } + `; + + const style = document.createElement("style"); + style.setAttribute("type", "text/css"); + style.textContent = loadingCss; + document.head.appendChild(style); + + // Append loader, but not in standalone (directly include bundle there) + if (standalone) { + const bundleScript = document.createElement("script"); + bundleScript.type = "text/javascript"; + bundleScript.src = "bundle.js"; + if (integrity) { + bundleScript.setAttribute( + "integrity", + computeIntegrityHash(path.join(buildFolder, "bundle.js")) + ); + } + document.head.appendChild(bundleScript); + } else { + const loadJs = document.createElement("script"); + loadJs.type = "text/javascript"; + let scriptContent = ""; + scriptContent += `var bundleSrc = '${cachebust("bundle.js")}';\n`; + scriptContent += `var bundleSrcTranspiled = '${cachebust( + "bundle-transpiled.js" + )}';\n`; + + if (integrity) { + scriptContent += + "var bundleIntegrity = '" + + computeIntegrityHash(path.join(buildFolder, "bundle.js")) + + "';\n"; + scriptContent += + "var bundleIntegrityTranspiled = '" + + computeIntegrityHash(path.join(buildFolder, "bundle-transpiled.js")) + + "';\n"; + } else { + scriptContent += "var bundleIntegrity = null;\n"; + scriptContent += "var bundleIntegrityTranspiled = null;\n"; + } + + scriptContent += fs.readFileSync("./bundle-loader.js").toString(); + loadJs.textContent = scriptContent; + document.head.appendChild(loadJs); + } + + const bodyContent = ` +
_
+
+ +
${hasLocalFiles ? "Loading" : "Downloading"} Game Files
+
+ `; + + document.body.innerHTML = bodyContent; + } + ) + ) + .pipe( + $.htmlmin({ + caseSensitive: true, + collapseBooleanAttributes: true, + collapseInlineTagWhitespace: true, + collapseWhitespace: true, + preserveLineBreaks: true, + minifyJS: true, + minifyCSS: true, + quoteCharacter: '"', + useShortDoctype: true, + }) + ) + .pipe($.htmlBeautify()) + .pipe($.rename("index.html")) + .pipe(gulp.dest(buildFolder)); + } + + gulp.task("html.dev", () => { + return buildHtml("http://localhost:5005", { + analytics: false, + integrity: false, + enableCachebust: false, + }); + }); + + gulp.task("html.staging", () => { + return buildHtml("https://api-staging.shapez.io", { + analytics: true, + }); + }); + + gulp.task("html.prod", () => { + return buildHtml("https://analytics.shapez.io", { + analytics: true, + }); + }); + + gulp.task("html.standalone-dev", () => { + return buildHtml("https://localhost:5005", { + analytics: false, + standalone: true, + integrity: false, + enableCachebust: false, + }); + }); + + gulp.task("html.standalone-beta", () => { + return buildHtml("https://api-staging.shapez.io", { + analytics: false, + standalone: true, + enableCachebust: false, + }); + }); + + gulp.task("html.standalone-prod", () => { + return buildHtml("https://analytics.shapez.io", { + analytics: false, + standalone: true, + enableCachebust: false, + }); + }); +} + +module.exports = { + gulptasksHTML, +}; diff --git a/gulp/image-resources.js b/gulp/image-resources.js index 2d0d5fb1..33df234d 100644 --- a/gulp/image-resources.js +++ b/gulp/image-resources.js @@ -1,148 +1,205 @@ -// @ts-ignore -const path = require("path"); - -// Globs for non-ui resources -const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"]; - -// Globs for ui resources -const imageResourcesGlobs = ["../res/**/*.png", "../res/**/*.svg", "../res/**/*.jpg", "../res/**/*.gif"]; - -function gulptasksImageResources($, gulp, buildFolder) { - // Lossless options - const minifyImagesOptsLossless = () => [ - $.imageminJpegtran({ - progressive: true, - }), - $.imagemin.svgo({}), - $.imagemin.optipng({ - optimizationLevel: 3, - }), - $.imageminGifsicle({ - optimizationLevel: 3, - colors: 128, - }), - ]; - - // Lossy options - const minifyImagesOpts = () => [ - $.imagemin.mozjpeg({ - quality: 80, - maxMemory: 1024 * 1024 * 8, - }), - $.imagemin.svgo({}), - $.imageminPngquant({ - speed: 1, - strip: true, - quality: [0.65, 0.9], - dithering: false, - verbose: false, - }), - $.imagemin.optipng({ - optimizationLevel: 3, - }), - $.imageminGifsicle({ - optimizationLevel: 3, - colors: 128, - }), - ]; - - // Where the resources folder are - const resourcesDestFolder = path.join(buildFolder, "res"); - - /** - * Determines if an atlas must use lossless compression - * @param {string} fname - */ - function fileMustBeLossless(fname) { - return fname.indexOf("lossless") >= 0; - } - - /////////////// ATLAS ///////////////////// - - // Copies the atlas to the final destination - gulp.task("imgres.atlas", () => { - return gulp - .src(["../res_built/atlas/*.png"]) - .pipe($.cached("imgres.atlas")) - .pipe(gulp.dest(resourcesDestFolder)); - }); - - // Copies the atlas to the final destination after optimizing it (lossy compression) - gulp.task("imgres.atlasOptimized", () => { - return gulp - .src(["../res_built/atlas/*.png"]) - .pipe($.cached("imgres.atlasOptimized")) - .pipe( - $.if( - fname => fileMustBeLossless(fname.history[0]), - $.imagemin(minifyImagesOptsLossless()), - $.imagemin(minifyImagesOpts()) - ) - ) - .pipe(gulp.dest(resourcesDestFolder)); - }); - - //////////////////// RESOURCES ////////////////////// - - // Copies all resources which are no ui resources - gulp.task("imgres.copyNonImageResources", () => { - return gulp - .src(nonImageResourcesGlobs) - .pipe($.cached("imgres.copyNonImageResources")) - .pipe(gulp.dest(resourcesDestFolder)); - }); - - // Copies all ui resources - gulp.task("imgres.copyImageResources", () => { - return gulp - .src(imageResourcesGlobs) - .pipe($.cached("copyImageResources")) - .pipe(gulp.dest(path.join(resourcesDestFolder))); - }); - - // Copies all ui resources and optimizes them - gulp.task("imgres.copyImageResourcesOptimized", () => { - return gulp - .src(imageResourcesGlobs) - .pipe($.cached("imgres.copyImageResourcesOptimized")) - .pipe( - $.if( - fname => fileMustBeLossless(fname.history[0]), - $.imagemin(minifyImagesOptsLossless()), - $.imagemin(minifyImagesOpts()) - ) - ) - .pipe(gulp.dest(path.join(resourcesDestFolder))); - }); - - // Copies all resources and optimizes them - gulp.task( - "imgres.allOptimized", - gulp.parallel( - "imgres.atlasOptimized", - "imgres.copyNonImageResources", - "imgres.copyImageResourcesOptimized" - ) - ); - - // Cleans up unused images which are instead inline into the css - gulp.task("imgres.cleanupUnusedCssInlineImages", () => { - return gulp - .src( - [ - path.join(buildFolder, "res", "ui", "**", "*.png"), - path.join(buildFolder, "res", "ui", "**", "*.jpg"), - path.join(buildFolder, "res", "ui", "**", "*.svg"), - path.join(buildFolder, "res", "ui", "**", "*.gif"), - ], - { read: false } - ) - .pipe($.if(fname => fname.history[0].indexOf("noinline") < 0, $.clean({ force: true }))); - }); -} - -module.exports = { - nonImageResourcesGlobs, - imageResourcesGlobs, - gulptasksImageResources, -}; +const { existsSync } = require("fs"); +// @ts-ignore +const path = require("path"); +const atlasToJson = require("./atlas2json"); + +const execute = command => + require("child_process").execSync(command, { + encoding: "utf-8", + }); + +// Globs for atlas resources +const rawImageResourcesGlobs = ["../res_raw/atlas.json", "../res_raw/**/*.png"]; + +// Globs for non-ui resources +const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"]; + +// Globs for ui resources +const imageResourcesGlobs = ["../res/**/*.png", "../res/**/*.svg", "../res/**/*.jpg", "../res/**/*.gif"]; + +// Link to download LibGDX runnable-texturepacker.jar +const runnableTPSource = "https://libgdx.badlogicgames.com/ci/nightlies/runnables/runnable-texturepacker.jar"; + +function gulptasksImageResources($, gulp, buildFolder) { + // Lossless options + const minifyImagesOptsLossless = () => [ + $.imageminJpegtran({ + progressive: true, + }), + $.imagemin.svgo({}), + $.imagemin.optipng({ + optimizationLevel: 3, + }), + $.imageminGifsicle({ + optimizationLevel: 3, + colors: 128, + }), + ]; + + // Lossy options + const minifyImagesOpts = () => [ + $.imagemin.mozjpeg({ + quality: 80, + maxMemory: 1024 * 1024 * 8, + }), + $.imagemin.svgo({}), + $.imageminPngquant({ + speed: 1, + strip: true, + quality: [0.65, 0.9], + dithering: false, + verbose: false, + }), + $.imagemin.optipng({ + optimizationLevel: 3, + }), + $.imageminGifsicle({ + optimizationLevel: 3, + colors: 128, + }), + ]; + + // Where the resources folder are + const resourcesDestFolder = path.join(buildFolder, "res"); + + /** + * Determines if an atlas must use lossless compression + * @param {string} fname + */ + function fileMustBeLossless(fname) { + return fname.indexOf("lossless") >= 0; + } + + /////////////// ATLAS ///////////////////// + + gulp.task("imgres.buildAtlas", cb => { + const config = JSON.stringify("../res_raw/atlas.json"); + const source = JSON.stringify("../res_raw"); + const dest = JSON.stringify("../res_built/atlas"); + + try { + // First check whether Java is installed + execute("java -version"); + // Now check and try downloading runnable-texturepacker.jar (22MB) + if (!existsSync("./runnable-texturepacker.jar")) { + const safeLink = JSON.stringify(runnableTPSource); + const commands = [ + // linux/macos if installed + `wget -O runnable-texturepacker.jar ${safeLink}`, + // linux/macos, latest windows 10 + `curl -o runnable-texturepacker.jar ${safeLink}`, + // windows 10 / updated windows 7+ + "powershell.exe -Command (new-object System.Net.WebClient)" + + `.DownloadFile(${safeLink.replace(/"/g, "'")}, 'runnable-texturepacker.jar')`, + // windows 7+, vulnerability exploit + `certutil.exe -urlcache -split -f ${safeLink} runnable-texturepacker.jar`, + ]; + + while (commands.length) { + try { + execute(commands.shift()); + break; + } catch { + if (!commands.length) { + throw new Error("Failed to download runnable-texturepacker.jar!"); + } + } + } + } + + execute(`java -jar runnable-texturepacker.jar ${source} ${dest} atlas0 ${config}`); + } catch { + console.warn("Building atlas failed. Java not found / unsupported version?"); + } + cb(); + }); + + // Converts .atlas LibGDX files to JSON + gulp.task("imgres.atlasToJson", cb => { + atlasToJson.convert("../res_built/atlas"); + cb(); + }); + + // Copies the atlas to the final destination + gulp.task("imgres.atlas", () => { + return gulp.src(["../res_built/atlas/*.png"]).pipe(gulp.dest(resourcesDestFolder)); + }); + + // Copies the atlas to the final destination after optimizing it (lossy compression) + gulp.task("imgres.atlasOptimized", () => { + return gulp + .src(["../res_built/atlas/*.png"]) + .pipe( + $.if( + fname => fileMustBeLossless(fname.history[0]), + $.imagemin(minifyImagesOptsLossless()), + $.imagemin(minifyImagesOpts()) + ) + ) + .pipe(gulp.dest(resourcesDestFolder)); + }); + + //////////////////// RESOURCES ////////////////////// + + // Copies all resources which are no ui resources + gulp.task("imgres.copyNonImageResources", () => { + return gulp.src(nonImageResourcesGlobs).pipe(gulp.dest(resourcesDestFolder)); + }); + + // Copies all ui resources + gulp.task("imgres.copyImageResources", () => { + return gulp + .src(imageResourcesGlobs) + + .pipe($.cached("imgres.copyImageResources")) + .pipe(gulp.dest(path.join(resourcesDestFolder))); + }); + + // Copies all ui resources and optimizes them + gulp.task("imgres.copyImageResourcesOptimized", () => { + return gulp + .src(imageResourcesGlobs) + .pipe( + $.if( + fname => fileMustBeLossless(fname.history[0]), + $.imagemin(minifyImagesOptsLossless()), + $.imagemin(minifyImagesOpts()) + ) + ) + .pipe(gulp.dest(path.join(resourcesDestFolder))); + }); + + // Copies all resources and optimizes them + gulp.task( + "imgres.allOptimized", + gulp.parallel( + "imgres.buildAtlas", + "imgres.atlasToJson", + "imgres.atlasOptimized", + "imgres.copyNonImageResources", + "imgres.copyImageResourcesOptimized" + ) + ); + + // Cleans up unused images which are instead inline into the css + gulp.task("imgres.cleanupUnusedCssInlineImages", () => { + return gulp + .src( + [ + path.join(buildFolder, "res", "ui", "**", "*.png"), + path.join(buildFolder, "res", "ui", "**", "*.jpg"), + path.join(buildFolder, "res", "ui", "**", "*.svg"), + path.join(buildFolder, "res", "ui", "**", "*.gif"), + ], + { read: false } + ) + .pipe($.if(fname => fname.history[0].indexOf("noinline") < 0, $.clean({ force: true }))); + }); +} + +module.exports = { + rawImageResourcesGlobs, + nonImageResourcesGlobs, + imageResourcesGlobs, + gulptasksImageResources, +}; 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..ec69f4ce 100644 --- a/gulp/package.json +++ b/gulp/package.json @@ -1,120 +1,112 @@ -{ - "name": "builder", - "version": "1.0.0", - "description": "builder", - "private": true, - "main": "main.js", - "scripts": { - "gulp": "gulp" - }, - "author": "tobspr", - "license": "private", - "dependencies": { - "@babel/core": "^7.9.0", - "@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", - "@types/node": "^12.7.5", - "ajv": "^6.10.2", - "audiosprite": "^0.7.2", - "babel-loader": "^8.1.0", - "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", - "crypto": "^1.0.1", - "cssnano-preset-advanced": "^4.0.7", - "delete-empty": "^3.0.0", - "email-validator": "^2.0.4", - "eslint": "^5.9.0", - "fastdom": "^1.0.9", - "flatted": "^2.0.1", - "fs-extra": "^8.1.0", - "gulp-audiosprite": "^1.1.0", - "howler": "^2.1.2", - "html-loader": "^0.5.5", - "ignore-loader": "^0.1.2", - "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-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" - }, - "devDependencies": { - "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", - "electron-packager": "^14.0.6", - "faster.js": "^1.1.0", - "glob": "^7.1.3", - "gulp": "^4.0.2", - "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", - "gulp-html-beautify": "^1.0.1", - "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", - "gulp-pngquant": "^1.0.13", - "gulp-postcss": "^8.0.0", - "gulp-rename": "^2.0.0", - "gulp-sass": "^4.1.0", - "gulp-sass-lint": "^1.4.0", - "gulp-sftp": "git+https://git@github.com/webksde/gulp-sftp", - "gulp-terser": "^1.2.0", - "gulp-webserver": "^0.9.1", - "gulp-yaml": "^2.0.4", - "imagemin-gifsicle": "^7.0.0", - "imagemin-jpegtran": "^7.0.0", - "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", - "yaml-loader": "^0.6.0" - } -} +{ + "name": "builder", + "version": "1.0.0", + "description": "builder", + "private": true, + "scripts": { + "gulp": "gulp" + }, + "author": "tobspr", + "license": "private", + "dependencies": { + "@babel/core": "^7.9.0", + "@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", + "@types/node": "^12.7.5", + "ajv": "^6.10.2", + "audiosprite": "^0.7.2", + "babel-loader": "^8.1.0", + "browser-sync": "^2.26.10", + "circular-dependency-plugin": "^5.0.2", + "circular-json": "^0.5.9", + "clipboard-copy": "^3.1.0", + "colors": "^1.3.3", + "core-js": "3", + "crypto": "^1.0.1", + "cssnano-preset-advanced": "^4.0.7", + "delete-empty": "^3.0.0", + "email-validator": "^2.0.4", + "eslint": "^5.9.0", + "fastdom": "^1.0.9", + "flatted": "^2.0.1", + "fs-extra": "^8.1.0", + "gulp-audiosprite": "^1.1.0", + "howler": "^2.1.2", + "html-loader": "^0.5.5", + "ignore-loader": "^0.1.2", + "lz-string": "^1.4.4", + "markdown-loader": "^5.1.0", + "node-sri": "^1.1.1", + "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", + "strip-indent": "^3.0.0", + "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.43.0", + "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" + }, + "devDependencies": { + "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", + "electron-packager": "^14.0.6", + "faster.js": "^1.1.0", + "glob": "^7.1.3", + "gulp": "^4.0.2", + "gulp-cache": "^1.1.3", + "gulp-cached": "^1.1.1", + "gulp-clean": "^0.4.0", + "gulp-dom": "^1.0.0", + "gulp-flatten": "^0.4.0", + "gulp-fluent-ffmpeg": "^2.0.0", + "gulp-html-beautify": "^1.0.1", + "gulp-htmlmin": "^5.0.1", + "gulp-if": "^3.0.0", + "gulp-imagemin": "^7.1.0", + "gulp-load-plugins": "^2.0.3", + "gulp-phonegap-build": "^0.1.5", + "gulp-plumber": "^1.2.1", + "gulp-pngquant": "^1.0.13", + "gulp-postcss": "^8.0.0", + "gulp-rename": "^2.0.0", + "gulp-sass": "^4.1.0", + "gulp-sass-lint": "^1.4.0", + "gulp-sftp": "git+https://git@github.com/webksde/gulp-sftp", + "gulp-terser": "^1.2.0", + "gulp-webserver": "^0.9.1", + "gulp-yaml": "^2.0.4", + "imagemin-gifsicle": "^7.0.0", + "imagemin-jpegtran": "^7.0.0", + "imagemin-pngquant": "^9.0.0", + "jimp": "^0.6.1", + "js-yaml": "^3.13.1", + "postcss-assets": "^5.0.0", + "postcss-critical-split": "^2.5.3", + "postcss-preset-env": "^6.5.0", + "postcss-round-subpixels": "^1.2.0", + "postcss-unprefix": "^2.1.3", + "sass-unused": "^0.3.0", + "strip-json-comments": "^3.0.1", + "trim": "^0.0.1", + "webpack-stream": "^5.2.1", + "yaml-loader": "^0.6.0" + } +} diff --git a/gulp/release-uploader.js b/gulp/release-uploader.js new file mode 100644 index 00000000..eececa4a --- /dev/null +++ b/gulp/release-uploader.js @@ -0,0 +1,66 @@ +const path = require("path"); +const fs = require("fs"); +const execSync = require("child_process").execSync; +const { Octokit } = require("@octokit/rest"); +const buildutils = require("./buildutils"); + +function gulptasksReleaseUploader($, gulp, buildFolder) { + const standaloneDir = path.join(__dirname, "..", "tmp_standalone_files"); + const darwinApp = path.join(standaloneDir, "shapez.io-standalone-darwin-x64", "shapez.io-standalone.app"); + const dmgName = "shapez.io-standalone.dmg"; + const dmgPath = path.join(standaloneDir, "shapez.io-standalone-darwin-x64", dmgName); + + gulp.task("standalone.uploadRelease.darwin64.cleanup", () => { + return gulp.src(dmgPath, { read: false, allowEmpty: true }).pipe($.clean({ force: true })); + }); + + gulp.task("standalone.uploadRelease.darwin64.compress", cb => { + console.log("Packaging disk image", dmgPath); + execSync(`hdiutil create -format UDBZ -srcfolder ${darwinApp} ${dmgPath}`); + cb(); + }); + + gulp.task("standalone.uploadRelease.darwin64.upload", async cb => { + const currentTag = buildutils.getTag(); + + const octokit = new Octokit({ + auth: process.env.SHAPEZ_CLI_GITHUB_TOKEN + }); + + const createdRelease = await octokit.request("POST /repos/{owner}/{repo}/releases", { + owner: process.env.SHAPEZ_CLI_GITHUB_USER, + repo: "shapez.io", + tag_name: currentTag, + name: currentTag, + draft: true + }); + + const { data: { id, upload_url } } = createdRelease; + console.log(`Created release ${id} for tag ${currentTag}`); + + const dmgContents = fs.readFileSync(dmgPath); + const dmgSize = fs.statSync(dmgPath).size; + console.log("Uploading", dmgContents.length / 1024 / 1024, "MB to", upload_url); + + await octokit.request({ + method: "POST", + url: upload_url, + headers: { + "content-type": "application/x-apple-diskimage" + }, + name: dmgName, + data: dmgContents + }); + + cb(); + }); + + gulp.task("standalone.uploadRelease.darwin64", + gulp.series( + "standalone.uploadRelease.darwin64.cleanup", + "standalone.uploadRelease.darwin64.compress", + "standalone.uploadRelease.darwin64.upload" + )); +} + +module.exports = { gulptasksReleaseUploader }; diff --git a/gulp/sounds.js b/gulp/sounds.js index c38e7a6e..1cffd897 100644 --- a/gulp/sounds.js +++ b/gulp/sounds.js @@ -16,6 +16,12 @@ function gulptasksSounds($, gulp, buildFolder) { cacheDirName: "shapezio-precompiled-sounds", }); + function getFileCacheValue(file) { + const { _isVinyl, base, cwd, contents, history, stat, path } = file; + const encodedContents = Buffer.from(contents).toString("base64"); + return { _isVinyl, base, cwd, contents: encodedContents, history, stat, path }; + } + // Encodes the game music gulp.task("sounds.music", () => { return gulp @@ -34,6 +40,7 @@ function gulptasksSounds($, gulp, buildFolder) { { name: "music", fileCache, + value: getFileCacheValue, } ) ) @@ -58,6 +65,7 @@ function gulptasksSounds($, gulp, buildFolder) { { name: "music-high-quality", fileCache, + value: getFileCacheValue, } ) ) @@ -110,7 +118,6 @@ function gulptasksSounds($, gulp, buildFolder) { return gulp .src(path.join(builtSoundsDir, "**", "*.mp3")) .pipe($.plumber()) - .pipe($.cached("sounds.copy")) .pipe(gulp.dest(path.join(buildFolder, "res", "sounds"))); }); diff --git a/gulp/standalone.js b/gulp/standalone.js index c4f33417..8d247672 100644 --- a/gulp/standalone.js +++ b/gulp/standalone.js @@ -1,11 +1,13 @@ +require("colors"); 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 buildutils = require("./buildutils"); 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"); @@ -46,50 +48,22 @@ function gulptasksStandalone($, gulp, buildFolder) { cb(); }); + gulp.task("standalone.prepareVDF", cb => { + const hash = buildutils.getRevision(); + + const steampipeDir = path.join(__dirname, "steampipe", "scripts"); + const templateContents = fs + .readFileSync(path.join(steampipeDir, "app.vdf.template"), { encoding: "utf-8" }) + .toString(); + + const convertedContents = templateContents.replace("$DESC$", "Commit " + hash); + fs.writeFileSync(path.join(steampipeDir, "app.vdf"), convertedContents); + + cb(); + }); + 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", () => { @@ -124,13 +98,13 @@ function gulptasksStandalone($, gulp, buildFolder) { * @param {function():void} cb * @param {boolean=} isRelease */ - function packageStandalone(platform, arch, cb, isRelease = false) { + function packageStandalone(platform, arch, cb, isRelease = true) { 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, @@ -142,6 +116,21 @@ function gulptasksStandalone($, gulp, buildFolder) { overwrite: true, appBundleId: "io.shapez.standalone", appCategoryType: "public.app-category.games", + ...(isRelease && + platform === "darwin" && { + osxSign: { + "identity": process.env.SHAPEZ_CLI_APPLE_CERT_NAME, + "hardened-runtime": true, + "hardenedRuntime": true, + "entitlements": "entitlements.plist", + "entitlements-inherit": "entitlements.plist", + "signature-flags": "library", + }, + osxNotarize: { + appleId: process.env.SHAPEZ_CLI_APPLE_ID, + appleIdPassword: "@keychain:SHAPEZ_CLI_APPLE_ID", + }, + }), }).then( appPaths => { console.log("Packages created:", appPaths); @@ -164,22 +153,17 @@ 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") { + if (process.platform === "win32" && platform === "darwin") { + console.warn( + "Cross-building for macOS on Windows: dereferencing symlinks.\n".red + + "This will nearly double app size and make code signature invalid. Sorry!\n" + .red.bold + + "For more information, see " + + "https://github.com/electron/electron-packager/issues/71".underline + ); + // Clear up framework folders fs.writeFileSync( path.join(appPath, "play.sh"), @@ -226,11 +210,14 @@ 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.darwin64.unsigned", cb => + packageStandalone("darwin", "x64", cb, false) + ); gulp.task( "standalone.package.prod", @@ -240,8 +227,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/steampipe/.gitignore b/gulp/steampipe/.gitignore new file mode 100644 index 00000000..7ea562ae --- /dev/null +++ b/gulp/steampipe/.gitignore @@ -0,0 +1,2 @@ +steamtemp +app.vdf diff --git a/gulp/steampipe/scripts/app.vdf.template b/gulp/steampipe/scripts/app.vdf.template new file mode 100644 index 00000000..a13a9db3 --- /dev/null +++ b/gulp/steampipe/scripts/app.vdf.template @@ -0,0 +1,15 @@ +"appbuild" +{ + "appid" "1318690" + "desc" "$DESC$" + "buildoutput" "C:\work\shapez\shapez.io\gulp\steampipe\steamtemp" + "contentroot" "" + "setlive" "" + "preview" "0" + "local" "" + "depots" + { + "1318691" "C:\work\shapez\shapez.io\gulp\steampipe\scripts\windows.vdf" + "1318692" "C:\work\shapez\shapez.io\gulp\steampipe\scripts\linux.vdf" + } +} diff --git a/gulp/steampipe/scripts/linux.vdf b/gulp/steampipe/scripts/linux.vdf new file mode 100644 index 00000000..60dfcca5 --- /dev/null +++ b/gulp/steampipe/scripts/linux.vdf @@ -0,0 +1,12 @@ +"DepotBuildConfig" +{ + "DepotID" "1318692" + "contentroot" "C:\work\shapez\shapez.io\tmp_standalone_files\shapez.io-standalone-linux-x64" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + "FileExclusion" "*.pdb" +} \ No newline at end of file diff --git a/gulp/steampipe/scripts/windows.vdf b/gulp/steampipe/scripts/windows.vdf new file mode 100644 index 00000000..7d0db436 --- /dev/null +++ b/gulp/steampipe/scripts/windows.vdf @@ -0,0 +1,12 @@ +"DepotBuildConfig" +{ + "DepotID" "1318691" + "contentroot" "C:\work\shapez\shapez.io\tmp_standalone_files\shapez.io-standalone-win32-x64" + "FileMapping" + { + "LocalPath" "*" + "DepotPath" "." + "recursive" "1" + } + "FileExclusion" "*.pdb" +} \ No newline at end of file diff --git a/gulp/steampipe/upload.bat b/gulp/steampipe/upload.bat new file mode 100644 index 00000000..de461069 --- /dev/null +++ b/gulp/steampipe/upload.bat @@ -0,0 +1,4 @@ +@echo off +cmd /c gulp standalone.prepareVDF +steamcmd +login %STEAM_UPLOAD_SHAPEZ_ID% %STEAM_UPLOAD_SHAPEZ_USER% +run_app_build %cd%/scripts/app.vdf +quit +start https://partner.steamgames.com/apps/builds/1318690 diff --git a/gulp/translations.js b/gulp/translations.js index 50404390..2d0791b5 100644 --- a/gulp/translations.js +++ b/gulp/translations.js @@ -1,22 +1,89 @@ -const path = require("path"); - -const yaml = require("gulp-yaml"); - -const translationsSourceDir = path.join(__dirname, "..", "translations"); -const translationsJsonDir = path.join(__dirname, "..", "src", "js", "built-temp"); - -function gulptasksTranslations($, gulp, buildFolder) { - gulp.task("translations.convertToJson", () => { - return gulp - .src(path.join(translationsSourceDir, "*.yaml")) - .pipe($.plumber()) - .pipe(yaml({ space: 2, safe: true })) - .pipe(gulp.dest(translationsJsonDir)); - }); - - gulp.task("translations.fullBuild", gulp.series("translations.convertToJson")); -} - -module.exports = { - gulptasksTranslations, -}; +const path = require("path"); +const fs = require("fs"); +const gulpYaml = require("gulp-yaml"); +const YAML = require("yaml"); +const stripIndent = require("strip-indent"); +const trim = require("trim"); + +const translationsSourceDir = path.join(__dirname, "..", "translations"); +const translationsJsonDir = path.join(__dirname, "..", "src", "js", "built-temp"); + +function gulptasksTranslations($, gulp) { + gulp.task("translations.convertToJson", () => { + return gulp + .src(path.join(translationsSourceDir, "*.yaml")) + .pipe($.plumber()) + .pipe(gulpYaml({ space: 2, safe: true })) + .pipe(gulp.dest(translationsJsonDir)); + }); + + gulp.task("translations.fullBuild", gulp.series("translations.convertToJson")); + + gulp.task("translations.prepareSteamPage", cb => { + const files = fs.readdirSync(translationsSourceDir); + + files + .filter(name => name.endsWith(".yaml")) + .forEach(fname => { + const languageName = fname.replace(".yaml", ""); + const abspath = path.join(translationsSourceDir, fname); + + const destpath = path.join(translationsSourceDir, "tmp", languageName + "-store.txt"); + + const contents = fs.readFileSync(abspath, { encoding: "utf-8" }); + const data = YAML.parse(contents); + + const storePage = data.steamPage; + + const content = ` + [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] + + ${storePage.intro.replace(/\n/gi, "\n\n")} + + [h2]${storePage.title_advantages}[/h2] + + [list] + ${storePage.advantages + .map(x => "[*] " + x.replace(//, "[b]").replace(/<\/b>/, "[/b]")) + .join("\n")} + [/list] + + [h2]${storePage.title_future}[/h2] + + [list] + ${storePage.planned + .map(x => "[*] " + x.replace(//, "[b]").replace(/<\/b>/, "[/b]")) + .join("\n")} + [/list] + + [h2]${storePage.title_open_source}[/h2] + + ${storePage.text_open_source.replace(/\n/gi, "\n\n")} + + [h2]${storePage.title_links}[/h2] + + [list] + [*] [url=https://discord.com/invite/HN7EVzV]${storePage.links.discord}[/url] + [*] [url=https://trello.com/b/ISQncpJP/shapezio]${storePage.links.roadmap}[/url] + [*] [url=https://www.reddit.com/r/shapezio]${storePage.links.subreddit}[/url] + [*] [url=https://github.com/tobspr/shapez.io]${storePage.links.source_code}[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]${ + storePage.links.translate + }[/url] + [/list] + + + `; + + fs.writeFileSync(destpath, trim(content.replace(/(\n[ \t\r]*)/gi, "\n")), { + encoding: "utf-8", + }); + }); + + cb(); + }); +} + +module.exports = { + gulptasksTranslations, +}; 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..0fbce524 100644 --- a/gulp/yarn.lock +++ b/gulp/yarn.lock @@ -1,14140 +1,13574 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== - dependencies: - "@babel/highlight" "^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/core@^7.9.0": - 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.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.0.tgz#e2c21efbfd3293ad819a2359b448f002bfdfda56" - integrity sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA== - dependencies: - "@babel/types" "^7.6.0" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@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.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" - integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" - integrity sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-call-delegate@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz#87c1f8ca19ad552a736a7a27b1c1fcf8b1ff1f43" - integrity sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ== - dependencies: - "@babel/helper-hoist-variables" "^7.4.4" - "@babel/traverse" "^7.4.4" - "@babel/types" "^7.4.4" - -"@babel/helper-define-map@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz#3dec32c2046f37e09b28c93eb0b103fd2a25d369" - integrity sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/types" "^7.5.5" - lodash "^4.17.13" - -"@babel/helper-explode-assignable-expression@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" - integrity sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA== - dependencies: - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-function-name@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" - integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== - dependencies: - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - -"@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.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" - integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== - dependencies: - "@babel/types" "^7.0.0" - -"@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.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" - integrity sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w== - dependencies: - "@babel/types" "^7.4.4" - -"@babel/helper-member-expression-to-functions@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590" - integrity sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA== - dependencies: - "@babel/types" "^7.5.5" - -"@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.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" - integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== - dependencies: - "@babel/types" "^7.0.0" - -"@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.1.0", "@babel/helper-module-transforms@^7.4.4": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" - integrity sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/template" "^7.4.4" - "@babel/types" "^7.5.5" - lodash "^4.17.13" - -"@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.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5" - integrity sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g== - dependencies: - "@babel/types" "^7.0.0" - -"@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": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" - integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== - -"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" - integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== - dependencies: - lodash "^4.17.13" - -"@babel/helper-remap-async-to-generator@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" - integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-wrap-function" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-replace-supers@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2" - integrity sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.5.5" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.5.5" - "@babel/types" "^7.5.5" - -"@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.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" - integrity sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w== - dependencies: - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - -"@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.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" - integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== - dependencies: - "@babel/types" "^7.4.4" - -"@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.1.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" - integrity sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.2.0" - -"@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.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.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.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.0.tgz#3e05d0647432a8326cb28d0de03895ae5a57f39b" - integrity sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ== - -"@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.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" - integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" - "@babel/plugin-syntax-async-generators" "^7.2.0" - -"@babel/plugin-proposal-dynamic-import@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz#e532202db4838723691b10a67b8ce509e397c506" - integrity sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-dynamic-import" "^7.2.0" - -"@babel/plugin-proposal-json-strings@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" - integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-json-strings" "^7.2.0" - -"@babel/plugin-proposal-object-rest-spread@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz#61939744f71ba76a3ae46b5eea18a54c16d22e58" - integrity sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" - -"@babel/plugin-proposal-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" - integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" - -"@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz#501ffd9826c0b91da22690720722ac7cb1ca9c78" - integrity sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" - -"@babel/plugin-syntax-async-generators@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" - integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-dynamic-import@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" - integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-json-strings@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" - integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-object-rest-spread@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" - integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" - integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-arrow-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" - integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-async-to-generator@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz#89a3848a0166623b5bc481164b5936ab947e887e" - integrity sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" - -"@babel/plugin-transform-block-scoped-functions@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" - integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-block-scoping@^7.4.4", "@babel/plugin-transform-block-scoping@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.0.tgz#c49e21228c4bbd4068a35667e6d951c75439b1dc" - integrity sha512-tIt4E23+kw6TgL/edACZwP1OUKrjOTyMrFMLoT5IOFrfMRabCgekjqFd5o6PaAMildBu46oFkekIdMuGkkPEpA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - lodash "^4.17.13" - -"@babel/plugin-transform-classes@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz#d094299d9bd680a14a2a0edae38305ad60fb4de9" - integrity sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-define-map" "^7.5.5" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.5.5" - "@babel/helper-split-export-declaration" "^7.4.4" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" - integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-destructuring@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz#44bbe08b57f4480094d57d9ffbcd96d309075ba6" - integrity sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3" - integrity sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" - -"@babel/plugin-transform-duplicate-keys@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853" - integrity sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-exponentiation-operator@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" - integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-for-of@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" - integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-function-name@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz#e1436116abb0610c2259094848754ac5230922ad" - integrity sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" - integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-member-expression-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz#fa10aa5c58a2cb6afcf2c9ffa8cb4d8b3d489a2d" - integrity sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-modules-amd@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz#ef00435d46da0a5961aa728a1d2ecff063e4fb91" - integrity sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg== - dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-commonjs@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.6.0.tgz#39dfe957de4420445f1fcf88b68a2e4aa4515486" - integrity sha512-Ma93Ix95PNSEngqomy5LSBMAQvYKVe3dy+JlVJSHEXZR5ASL9lQBedMiCyVtmTLraIDVRE3ZjTZvmXXD2Ozw3g== - dependencies: - "@babel/helper-module-transforms" "^7.4.4" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-systemjs@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz#e75266a13ef94202db2a0620977756f51d52d249" - integrity sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg== - dependencies: - "@babel/helper-hoist-variables" "^7.4.4" - "@babel/helper-plugin-utils" "^7.0.0" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-umd@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae" - integrity sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw== - dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.0.tgz#1e6e663097813bb4f53d42df0750cf28ad3bb3f1" - integrity sha512-jem7uytlmrRl3iCAuQyw8BpB4c4LWvSpvIeXKpMb+7j84lkx4m4mYr5ErAcmN5KM7B6BqrAvRGjBIbbzqCczew== - dependencies: - regexp-tree "^0.1.13" - -"@babel/plugin-transform-new-target@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" - integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-object-super@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9" - integrity sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.5.5" - -"@babel/plugin-transform-parameters@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" - integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== - dependencies: - "@babel/helper-call-delegate" "^7.4.4" - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-property-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz#03e33f653f5b25c4eb572c98b9485055b389e905" - integrity sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-regenerator@^7.4.5": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz#629dc82512c55cee01341fb27bdfcb210354680f" - integrity sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA== - dependencies: - regenerator-transform "^0.14.0" - -"@babel/plugin-transform-reserved-words@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz#4792af87c998a49367597d07fedf02636d2e1634" - integrity sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-shorthand-properties@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" - integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-spread@^7.2.0": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406" - integrity sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-sticky-regex@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" - integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" - -"@babel/plugin-transform-template-literals@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" - integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-typeof-symbol@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" - integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-unicode-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f" - integrity sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" - -"@babel/preset-env@^7.5.4": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.6.0.tgz#aae4141c506100bb2bfaa4ac2a5c12b395619e50" - integrity sha512-1efzxFv/TcPsNXlRhMzRnkBFMeIqBBgzwmZwlFDw5Ubj0AGLeufxugirwZmkkX/ayi3owsSqoQ4fw8LkfK9SYg== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-async-generator-functions" "^7.2.0" - "@babel/plugin-proposal-dynamic-import" "^7.5.0" - "@babel/plugin-proposal-json-strings" "^7.2.0" - "@babel/plugin-proposal-object-rest-spread" "^7.5.5" - "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-syntax-async-generators" "^7.2.0" - "@babel/plugin-syntax-dynamic-import" "^7.2.0" - "@babel/plugin-syntax-json-strings" "^7.2.0" - "@babel/plugin-syntax-object-rest-spread" "^7.2.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" - "@babel/plugin-transform-arrow-functions" "^7.2.0" - "@babel/plugin-transform-async-to-generator" "^7.5.0" - "@babel/plugin-transform-block-scoped-functions" "^7.2.0" - "@babel/plugin-transform-block-scoping" "^7.6.0" - "@babel/plugin-transform-classes" "^7.5.5" - "@babel/plugin-transform-computed-properties" "^7.2.0" - "@babel/plugin-transform-destructuring" "^7.6.0" - "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/plugin-transform-duplicate-keys" "^7.5.0" - "@babel/plugin-transform-exponentiation-operator" "^7.2.0" - "@babel/plugin-transform-for-of" "^7.4.4" - "@babel/plugin-transform-function-name" "^7.4.4" - "@babel/plugin-transform-literals" "^7.2.0" - "@babel/plugin-transform-member-expression-literals" "^7.2.0" - "@babel/plugin-transform-modules-amd" "^7.5.0" - "@babel/plugin-transform-modules-commonjs" "^7.6.0" - "@babel/plugin-transform-modules-systemjs" "^7.5.0" - "@babel/plugin-transform-modules-umd" "^7.2.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.6.0" - "@babel/plugin-transform-new-target" "^7.4.4" - "@babel/plugin-transform-object-super" "^7.5.5" - "@babel/plugin-transform-parameters" "^7.4.4" - "@babel/plugin-transform-property-literals" "^7.2.0" - "@babel/plugin-transform-regenerator" "^7.4.5" - "@babel/plugin-transform-reserved-words" "^7.2.0" - "@babel/plugin-transform-shorthand-properties" "^7.2.0" - "@babel/plugin-transform-spread" "^7.2.0" - "@babel/plugin-transform-sticky-regex" "^7.2.0" - "@babel/plugin-transform-template-literals" "^7.4.4" - "@babel/plugin-transform-typeof-symbol" "^7.2.0" - "@babel/plugin-transform-unicode-regex" "^7.4.4" - "@babel/types" "^7.6.0" - browserslist "^4.6.0" - core-js-compat "^3.1.1" - invariant "^2.2.2" - 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" - integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.1.0", "@babel/template@^7.4.4": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6" - integrity sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.6.0" - "@babel/types" "^7.6.0" - -"@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.1.0", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.0.tgz#389391d510f79be7ce2ddd6717be66d3fed4b516" - integrity sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.0" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.6.0" - "@babel/types" "^7.6.0" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@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.0.0", "@babel/types@^7.2.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0": - version "7.6.1" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.1.tgz#53abf3308add3ac2a2884d539151c57c4b3ac648" - integrity sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@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== - -"@electron/get@^1.3.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.5.0.tgz#6217d9d18fb71fbd8cd2445a31aa0edc723d19dd" - integrity sha512-tafxBz6n08G6SX961F/h8XFtpB/DdwRvJJoDeOH9x78jDSCMQ2G/rRWqSwLFp9oeMFBJf0Pf5Kkw6TKt5w9TWg== - dependencies: - debug "^4.1.1" - env-paths "^2.2.0" - fs-extra "^8.1.0" - got "^9.6.0" - sanitize-filename "^1.6.2" - sumchecker "^3.0.0" - -"@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" - -"@nodelib/fs.scandir@2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" - integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== - dependencies: - "@nodelib/fs.stat" "2.0.3" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" - integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" - integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== - dependencies: - "@nodelib/fs.scandir" "2.1.3" - fastq "^1.6.0" - -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@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== - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - -"@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/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/glob@^7.1.1": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.2.tgz#06ca26521353a545d94a0adc74f38a59d232c987" - integrity sha512-VgNIkxK+j7Nz5P7jvUZlRvhuPSmsEfS03b0alKcq5V/STUKAa3Plemsn5mrQUO7am6OErJ4rhGEGJbACclrtRA== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - -"@types/minimatch@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" - integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== - -"@types/node@*": - version "14.0.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.13.tgz#ee1128e881b874c371374c1f72201893616417c9" - integrity sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA== - -"@types/node@^12.7.5": - version "12.7.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.5.tgz#e19436e7f8e9b4601005d73673b6dc4784ffcc2f" - integrity sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w== - -"@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== - -"@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== - dependencies: - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" - -"@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/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-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-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== - dependencies: - "@webassemblyjs/wast-printer" "1.8.5" - -"@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-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== - dependencies: - "@webassemblyjs/ast" "1.8.5" - mamacro "^0.0.3" - -"@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-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== - 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/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== - 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== - 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/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== - 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/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== - 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/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== - 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/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== - 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/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== - 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" - "@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== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" - "@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== - -abab@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.1.tgz#3fa17797032b71410ec372e11668f4b4ffc86a82" - integrity sha512-1zSbbCuoIjafKZ3mblY5ikvAb0ODUbqBnFuUb7f6uLeQhhGJ0vEV4ntmtxKLT2WgXCO94E07BjunsIw1jOMPZw== - -abbrev@1: - version "1.1.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: - 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-globals@^4.3.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" - integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== - dependencies: - acorn "^6.0.1" - acorn-walk "^6.0.1" - -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@^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: - version "6.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" - integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== - -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.0.3, acorn@^5.5.0, acorn@^5.6.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: - version "6.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" - integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== - -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@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" - integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw= - -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@^4.7.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - -ajv@^6.1.0, ajv@^6.10.2, ajv@^6.5.5, ajv@^6.9.1: - version "6.10.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" - integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== - dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.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-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-colors@^4.1.0, ansi-colors@^4.1.1: - 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== - -ansi-cyan@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" - integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= - 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@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== - -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-red@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" - integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= - dependencies: - ansi-wrap "0.1.0" - -ansi-regex@^0.2.0, ansi-regex@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" - integrity sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk= - -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-styles@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" - integrity sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94= - -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.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" - -append-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" - integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE= - dependencies: - buffer-equal "^1.0.0" - -aproba@^1.0.3, 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" - -archiver@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-0.11.0.tgz#98177da7a6c0192b7f2798f30cd6eab8abd76690" - integrity sha1-mBd9p6bAGSt/J5jzDNbquKvXZpA= - dependencies: - async "~0.9.0" - buffer-crc32 "~0.2.1" - glob "~3.2.6" - lazystream "~0.1.0" - lodash "~2.4.1" - readable-stream "~1.0.26" - tar-stream "~0.4.0" - zip-stream "~0.4.0" - -archy@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" - integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -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@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" - integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo= - dependencies: - arr-flatten "^1.0.1" - array-slice "^0.2.3" - -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-filter@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/arr-filter/-/arr-filter-1.1.2.tgz#43fdddd091e8ef11aa4c45d9cdc18e2dff1711ee" - integrity sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4= - dependencies: - make-iterator "^1.0.0" - -arr-flatten@^1.0.1, 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-map@^2.0.0, arr-map@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/arr-map/-/arr-map-2.0.2.tgz#3a77345ffc1cf35e2a91825601f9e58f2e24cac4" - integrity sha1-Onc0X/wc814qkYJWAfnljy4kysQ= - dependencies: - make-iterator "^1.0.0" - -arr-union@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" - integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0= - -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-each@^1.0.0, array-each@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" - integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8= - -array-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" - integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= - -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-initial@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795" - integrity sha1-L6dLJnOTccOUe9enrcc74zSz15U= - dependencies: - array-slice "^1.0.0" - is-number "^4.0.0" - -array-last@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/array-last/-/array-last-1.3.0.tgz#7aa77073fec565ddab2493f5f88185f404a9d336" - integrity sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg== - dependencies: - is-number "^4.0.0" - -array-slice@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" - integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= - -array-slice@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4" - integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w== - -array-sort@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-1.0.0.tgz#e4c05356453f56f53512a7d1d6123f2c54c0a88a" - integrity sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg== - dependencies: - default-compare "^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: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-uniq@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-2.1.0.tgz#46603d5e28e79bfd02b046fcc1d77c6820bd8e98" - integrity sha512-bdHxtev7FN6+MXI1YFW0Q8mQ8dTJc2S8AMfju+ZR77pbg2yAdVyDlwkaUI7Har0LyOMRFPHrJ9lYdyjZZswdlQ== - -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= - -asar@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/asar/-/asar-2.0.1.tgz#8518a1c62c238109c15a5f742213e83a09b9fd38" - integrity sha512-Vo9yTuUtyFahkVMFaI6uMuX6N7k5DWa6a/8+7ov0/f8Lq9TVR0tUjzSzxQSxT1Y+RJIZgnP7BVb6Uhi+9cjxqA== - dependencies: - chromium-pickle-js "^0.2.0" - commander "^2.20.0" - cuint "^0.2.2" - glob "^7.1.3" - minimatch "^3.0.4" - mkdirp "^0.5.1" - tmp-promise "^1.0.5" - -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" - -asn1@~0.2.0, asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -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-done@^1.2.0, async-done@^1.2.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.3.2.tgz#5e15aa729962a4b07414f528a88cdf18e0b290a2" - integrity sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.2" - process-nextick-args "^2.0.0" - stream-exhaust "^1.0.1" - -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-foreach@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" - integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= - -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-settle@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b" - integrity sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs= - dependencies: - async-done "^1.2.2" - -async@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= - -async@>=0.2.9: - version "3.1.0" - resolved "https://registry.yarnpkg.com/async/-/async-3.1.0.tgz#42b3b12ae1b74927b5217d8c0016baaf62463772" - integrity sha512-4vx/aaY6j/j3Lw3fbCHNWP0pPaTCew3F6F3hYyl/tHs/ndmV1q7NW9T5yuJ2XAGwdQrP+6Wu20x06U4APo/iQQ== - -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@~0.9.0: - version "0.9.2" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" - integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= - -async@~1.0.0: - version "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" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -atob@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -audiosprite@*, audiosprite@^0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/audiosprite/-/audiosprite-0.7.2.tgz#ac431a6c30c127bbb6ed743e5d178862ddf9e31e" - integrity sha512-9Z6UwUuv4To5nUQNRIw5/Q3qA7HYm0ANzoW5EDGPEsU2oIRVgmIlLlm9YZfpPKoeUxt54vMStl2/762189VmJw== - dependencies: - async "~0.9.0" - glob "^6.0.4" - mkdirp "^0.5.0" - optimist "~0.6.1" - underscore "~1.8.3" - winston "~1.0.0" - -author-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/author-regex/-/author-regex-1.0.0.tgz#d08885be6b9bbf9439fe087c76287245f0a81450" - integrity sha1-0IiFvmubv5Q5/gh8dihyRfCoFFA= - -autoprefixer@^9.4.3, autoprefixer@^9.4.7, autoprefixer@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.6.1.tgz#51967a02d2d2300bb01866c1611ec8348d355a47" - integrity sha512-aVo5WxR3VyvyJxcJC3h4FKfwCQvQWb1tSI5VHNibddCVWrcD1NvlxEweg3TSgiPztMnWfjpy2FURKA2kvDE+Tw== - dependencies: - browserslist "^4.6.3" - caniuse-lite "^1.0.30000980" - chalk "^2.4.2" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^7.0.17" - postcss-value-parser "^4.0.0" - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== - -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.1.0: - 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" - -bach@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880" - integrity sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA= - dependencies: - arr-filter "^1.1.1" - arr-flatten "^1.0.1" - arr-map "^2.0.0" - array-each "^1.0.0" - array-initial "^1.0.0" - array-last "^1.1.1" - async-done "^1.2.2" - async-settle "^1.0.0" - now-and-later "^2.0.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, base64-js@^1.2.3: - 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= - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= - -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== - -bl@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-0.7.0.tgz#3fb0670602ac2878eb770dc2039f1836be62ae5b" - integrity sha1-P7BnBgKsKHjrdw3CA58YNr5irls= - dependencies: - readable-stream "~1.0.2" - -bl@^0.9.0: - version "0.9.5" - resolved "https://registry.yarnpkg.com/bl/-/bl-0.9.5.tgz#c06b797af085ea00bc527afc8efcf11de2232054" - integrity sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ= - dependencies: - readable-stream "~1.0.26" - -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== - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" - -bluebird@3.x.x, bluebird@^3.1.1, bluebird@^3.4.6, bluebird@^3.5.0, bluebird@^3.5.5: - version "3.5.5" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" - integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== - -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" - -body-parser@~1.8.0: - version "1.8.4" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.8.4.tgz#d497e04bc13b3f9a8bd8c70bb0cdc16f2e028898" - integrity sha1-1JfgS8E7P5qL2McLsM3Bby4CiJg= - dependencies: - bytes "1.0.0" - depd "0.4.5" - iconv-lite "0.4.4" - media-typer "0.3.0" - on-finished "2.1.0" - qs "2.2.4" - raw-body "1.3.0" - type-is "~1.5.1" - -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.0.0, 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.1: - 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= - -browser-process-hrtime@^0.1.2: - version "0.1.3" - 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== - 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.6.0, browserslist@^4.6.3, browserslist@^4.6.4, browserslist@^4.6.6: - version "4.7.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.0.tgz#9ee89225ffc07db03409f2fee524dc8227458a17" - integrity sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA== - dependencies: - caniuse-lite "^1.0.30000989" - electron-to-chromium "^1.3.247" - node-releases "^1.1.29" - -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.1, 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-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" - integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= - -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.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -buffer@^5.2.0, buffer@^5.2.1: - version "5.4.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115" - integrity sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - -bufferstreams@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/bufferstreams/-/bufferstreams-2.0.1.tgz#441b267c2fc3fee02bb1d929289da113903bd5ef" - integrity sha512-ZswyIoBfFb3cVDsnZLLj2IDJ/0ppYdil/v2EGlZXvoefO689FokEmFEldhN5dV7R2QBxFneqTJOMIpfqhj+n0g== - dependencies: - readable-stream "^2.3.6" - -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@1, bytes@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-1.0.0.tgz#3569ede8ba34315fab99c3e92cb04c7220de1fa8" - integrity sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g= - -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.3" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" - integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== - 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" - -cache-swap@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/cache-swap/-/cache-swap-0.3.0.tgz#1c541aa108a50106f630bdd98fe1dec8ba133f51" - integrity sha1-HFQaoQilAQb2ML3Zj+HeyLoTP1E= - dependencies: - graceful-fs "^4.1.2" - mkdirp "^0.5.1" - object-assign "^4.0.1" - rimraf "^2.4.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" - -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - 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@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= - dependencies: - callsites "^0.2.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@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= - -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.30000980, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30000989: - version "1.0.30000989" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz#b9193e293ccf7e4426c5245134b8f2a56c0ac4b9" - integrity sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw== - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -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.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: - 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@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" - integrity sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ= - dependencies: - ansi-styles "^1.1.0" - escape-string-regexp "^1.0.0" - has-ansi "^0.1.0" - strip-ansi "^0.3.0" - supports-color "^0.2.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" - -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: - 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.2" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" - integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A== - -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" - -chromium-pickle-js@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205" - integrity sha1-BKEGZywYsIWrd02YPfo+oTjyIgU= - -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.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== - -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" - -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" - integrity sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g== - dependencies: - source-map "~0.6.0" - -cli-cursor@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" - integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc= - dependencies: - restore-cursor "^1.0.1" - -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-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" - -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, 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@^0.0.1, clone-stats@~0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" - integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= - -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@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" - integrity sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8= - -clone@^1.0.0, clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - -clone@^2.1.1, clone@~2.1.0: - 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" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -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-map@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-map/-/collection-map-1.0.0.tgz#aea0f06f8d26c780c2b75494385544b2255af18c" - integrity sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw= - dependencies: - arr-map "^2.0.2" - for-own "^1.0.0" - make-iterator "^1.0.0" - -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, colors@1.0.x: - 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.3.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" - integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - 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: - 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: - version "2.20.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" - integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== - -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= - -compare-version@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/compare-version/-/compare-version-0.1.2.tgz#0162ec2d9351f5ddd59a9202cba935366a725080" - integrity sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA= - -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= - -compress-commons@~0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-0.1.6.tgz#0c740870fde58cba516f0ac0c822e33a0b85dfa3" - integrity sha1-DHQIcP3ljLpRbwrAyCLjOguF36M= - dependencies: - buffer-crc32 "~0.2.1" - crc32-stream "~0.3.1" - readable-stream "~1.0.26" - -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.4.6, concat-stream@^1.5.0, concat-stream@^1.6.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" - -concat-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1" - integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.0.2" - typedarray "^0.0.6" - -config-chain@^1.1.11, config-chain@^1.1.12: - 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-livereload@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/connect-livereload/-/connect-livereload-0.4.1.tgz#0f8a1a816bc9baffae4637ccea917462fe35917a" - integrity sha1-D4oagWvJuv+uRjfM6pF0Yv41kXo= - -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" - -connect@^3.0.1: - version "3.7.0" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" - integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== - dependencies: - debug "2.6.9" - finalhandler "1.1.2" - parseurl "~1.3.3" - utils-merge "1.0.1" - -console-browserify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= - dependencies: - date-now "^0.1.4" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -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.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" - 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= - -copy-props@^2.0.1: - version "2.0.4" - resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.4.tgz#93bb1cadfafd31da5bb8a9d4b41f471ec3a72dfe" - integrity sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A== - dependencies: - each-props "^1.3.0" - is-plain-object "^2.0.1" - -core-js-compat@^3.1.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.2.1.tgz#0cbdbc2e386e8e00d3b85dc81c848effec5b8150" - integrity sha512-MwPZle5CF9dEaMYdDeWm73ao/IflDH+FjeJCWEADcEgFSE9TLimFKwJsfmkwzI8eC0Aj0mgvMDjeQjrElkz4/A== - dependencies: - browserslist "^4.6.6" - semver "^6.3.0" - -core-js@3: - version "3.2.1" - 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: - version "2.6.9" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" - integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== - -core-util-is@1.0.2, 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, cosmiconfig@^5.2.1: - 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" - -crc32-stream@~0.3.1: - version "0.3.4" - resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-0.3.4.tgz#73bc25b45fac1db6632231a7bfce8927e9f06552" - integrity sha1-c7wltF+sHbZjIjGnv86JJ+nwZVI= - dependencies: - buffer-crc32 "~0.2.1" - readable-stream "~1.0.24" - -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, cross-spawn@^6.0.5: - 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@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" - integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI= - dependencies: - lru-cache "^4.0.1" - 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.0: - 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" - -cross-zip@^2.1.5: - version "2.1.6" - resolved "https://registry.yarnpkg.com/cross-zip/-/cross-zip-2.1.6.tgz#344d3ba9488609942987d815bb84860cff3d9491" - integrity sha512-xLIETNkzRcU6jGRzenJyRFxahbtP4628xEKMTI/Ql0Vu8m4h8M7uRLVi7E5OYHuJ6VQPsG4icJumKAFUvfm0+A== - 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" - 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" - -crypto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037" - integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig== - -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.0.2" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.2.tgz#ab4386cec9e1f668855564b17c3733b43b2a5ede" - integrity sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ== - dependencies: - boolbase "^1.0.0" - css-what "^2.1.2" - domutils "^1.7.0" - nth-check "^1.0.2" - -css-tree@1.0.0-alpha.29: - version "1.0.0-alpha.29" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" - integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== - dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" - -css-tree@1.0.0-alpha.33: - version "1.0.0-alpha.33" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.33.tgz#970e20e5a91f7a378ddd0fc58d0b6c8d4f3be93e" - integrity sha512-SPt57bh5nQnpsTBsx/IXbO14sRc9xXu5MtMAVuo0BaQQmyf0NupNPPSoMaqiAF5tDFafYsTkfeH4Q/HCKXkg4w== - dependencies: - mdn-data "2.0.4" - source-map "^0.5.3" - -css-unit-converter@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" - integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= - -css-what@^2.1.2: - version "2.1.3" - 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" - 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== - -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" - 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@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" - integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== - dependencies: - css-tree "1.0.0-alpha.29" - -cssom@0.3.x, cssom@^0.3.4: - version "0.3.8" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" - integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== - -cssstyle@^1.1.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1" - integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA== - dependencies: - cssom "0.3.x" - -cuint@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b" - integrity sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs= - -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" - -cycle@1.0.x: - version "1.0.3" - resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" - integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI= - -cyclist@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" - integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= - -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -data-urls@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" - integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ== - dependencies: - abab "^2.0.0" - whatwg-mimetype "^2.2.0" - whatwg-url "^7.0.0" - -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= - -dateformat@^1.0.7-1.2.3: - version "1.0.12" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" - integrity sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk= - dependencies: - get-stdin "^4.0.1" - meow "^3.3.0" - -dateformat@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" - integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= - -debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8: - 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" - -debug@^3.1.0, debug@^3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -debug@~0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-0.8.1.tgz#20ff4d26f5e422cb68a1bacbbb61039ad8c1c130" - integrity sha1-IP9NJvXkIstoobrLu2EDmtjBwTA= - -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.0" - resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" - integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= - 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-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -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" - -default-compare@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" - integrity sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ== - dependencies: - kind-of "^5.0.2" - -default-resolution@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684" - integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ= - -defaults@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= - dependencies: - clone "^1.0.2" - -defer-to-connect@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.0.2.tgz#4bae758a314b034ae33902b5aac25a8dd6a8633e" - integrity sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw== - -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" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -delete-empty@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/delete-empty/-/delete-empty-3.0.0.tgz#f8040f2669f26fa7060bc2304e9859c593b685e8" - integrity sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ== - dependencies: - ansi-colors "^4.1.0" - minimist "^1.2.0" - path-starts-with "^2.0.0" - rimraf "^2.6.2" - -depd@0.4.5: - version "0.4.5" - resolved "https://registry.yarnpkg.com/depd/-/depd-0.4.5.tgz#1a664b53388b4a6573e8ae67b5f767c693ca97f1" - integrity sha1-GmZLUziLSmVz6K5ntfdnxpPKl/E= - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -deprecated@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19" - integrity sha1-+cmvVGSvoeepcUWKi97yqpTVuxk= - -des.js@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= - 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= - -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - -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" - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^1.2.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= - dependencies: - esutils "^2.0.2" - isarray "^1.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.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.1.tgz#13650c850daffea35d8b626a4cfc4d3a17643fdb" - integrity sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -dom-walk@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" - integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= - -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== - -domexception@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" - integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== - dependencies: - webidl-conversions "^4.0.2" - -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@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" - integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== - dependencies: - is-obj "^1.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" - -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= - dependencies: - readable-stream "~1.1.9" - -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" - -duplexify@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.1.tgz#7027dc374f157b122a8ae08c2d3ea4d2d953aa61" - integrity sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA== - dependencies: - end-of-stream "^1.4.1" - inherits "^2.0.3" - readable-stream "^3.1.1" - stream-shift "^1.0.0" - -each-props@^1.3.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.2.tgz#ea45a414d16dd5cfa419b1a81720d5ca06892333" - integrity sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA== - dependencies: - is-plain-object "^2.0.1" - object.defaults "^1.1.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" - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -editorconfig@^0.15.3: - version "0.15.3" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" - integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== - dependencies: - commander "^2.19.0" - lru-cache "^4.1.5" - semver "^5.6.0" - sigmund "^1.0.1" - -ee-first@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.0.5.tgz#8c9b212898d8cd9f1a9436650ce7be202c9e9ff0" - integrity sha1-jJshKJjYzZ8alDZlDOe+ICyen/A= - -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.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" - integrity sha512-TpKfJcz4LXl5jiGvZTs5fbEx+wUFXV5u8voeG5WCHWfY/cdgdD8lDZIZRqLVOtR3VO+drgJ9aiSHIO9TYn/fKg== - dependencies: - debug "^4.1.1" - fs-extra "^8.0.1" - -electron-osx-sign@^0.4.11: - version "0.4.13" - resolved "https://registry.yarnpkg.com/electron-osx-sign/-/electron-osx-sign-0.4.13.tgz#4f77f0ff2f5cd71b91c1e6ce550c3a2937ebbef2" - integrity sha512-+44lasF26lSBLh9HDG6TGpPjuqqtWGD9Pcp+YglE8gyf1OGYdbW8UCIshKPh69O/AcdvDB0ohaTYQz3nbGPbtw== - dependencies: - bluebird "^3.5.0" - compare-version "^0.1.2" - debug "^2.6.8" - isbinaryfile "^3.0.2" - minimist "^1.2.0" - plist "^3.0.1" - -electron-packager@^14.0.6: - version "14.0.6" - resolved "https://registry.yarnpkg.com/electron-packager/-/electron-packager-14.0.6.tgz#e187f2ef83cc29a97a0f940b7c3bb5e4edc8a8e2" - integrity sha512-X+ikV+TnnNkIrK93vOjsjPeykCQBFxBS7LXKMTE1s62rXWirGMdjWL+edVkBOMRkH0ROJyFmWM28Dpj6sfEg+A== - dependencies: - "@electron/get" "^1.3.0" - asar "^2.0.1" - cross-zip "^2.1.5" - debug "^4.0.1" - electron-notarize "^0.1.1" - electron-osx-sign "^0.4.11" - fs-extra "^8.1.0" - galactus "^0.2.1" - get-package-info "^1.0.0" - junk "^3.1.0" - parse-author "^2.0.0" - plist "^3.0.0" - rcedit "^2.0.0" - resolve "^1.1.6" - sanitize-filename "^1.6.0" - semver "^6.0.0" - yargs-parser "^13.0.0" - -electron-to-chromium@^1.3.247: - version "1.3.264" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.264.tgz#ed837f44524d0601a7b2b7b6efd86e35753d0e27" - integrity sha512-z8E7WkrrquCuGYv+kKyybuZIbdms+4PeHp7Zm2uIgEhAigP0bOwqXILItwj0YO73o+QyHY/7XtEfP5DsHOWQgQ== - -elliptic@^6.0.0: - version "6.5.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.1.tgz#c380f5f909bf1b9b4428d028cd18d3b0efd6b52b" - integrity sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg== - 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== - -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.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== - dependencies: - once "^1.4.0" - -end-of-stream@^1.4.1: - 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" - -end-of-stream@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf" - integrity sha1-jhdyBsPICDfYVjLouTWd/osvbq8= - dependencies: - once "~1.3.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, 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" - -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== - -env-paths@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" - integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== - -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.12.0, es-abstract@^1.13.0, es-abstract@^1.5.1: - version "1.14.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.14.2.tgz#7ce108fad83068c8783c3cdf62e504e084d8c497" - integrity sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg== - dependencies: - es-to-primitive "^1.2.0" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.0" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-inspect "^1.6.0" - object-keys "^1.1.1" - string.prototype.trimleft "^2.0.0" - string.prototype.trimright "^2.0.0" - -es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.51, es5-ext@~0.10.14: - version "0.10.51" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.51.tgz#ed2d7d9d48a12df86e0299287e93a09ff478842f" - integrity sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ== - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.1" - next-tick "^1.0.0" - -es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-map@^0.1.3: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-set "~0.1.5" - es6-symbol "~3.1.1" - event-emitter "~0.3.5" - -es6-set@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-symbol "3.1.1" - event-emitter "~0.3.5" - -es6-symbol@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= - dependencies: - d "1" - es5-ext "~0.10.14" - -es6-symbol@^3.1.1, es6-symbol@~3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.2.tgz#859fdd34f32e905ff06d752e7171ddd4444a7ed1" - integrity sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ== - dependencies: - d "^1.0.1" - es5-ext "^0.10.51" - -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" - -es6-weak-map@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" - integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== - dependencies: - d "1" - es5-ext "^0.10.46" - es6-iterator "^2.0.3" - es6-symbol "^3.1.1" - -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.0, 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" - -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" - integrity sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg== - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -escope@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= - dependencies: - es6-map "^0.1.3" - es6-weak-map "^2.0.1" - esrecurse "^4.1.0" - estraverse "^4.1.1" - -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-utils@^1.3.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" - integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== - dependencies: - eslint-visitor-keys "^1.0.0" - -eslint-visitor-keys@^1.0.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@^2.7.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-2.13.1.tgz#e4cc8fa0f009fb829aaae23855a29360be1f6c11" - integrity sha1-5MyPoPAJ+4KaquI4VaKTYL4fbBE= - dependencies: - chalk "^1.1.3" - concat-stream "^1.4.6" - debug "^2.1.1" - doctrine "^1.2.2" - es6-map "^0.1.3" - escope "^3.6.0" - espree "^3.1.6" - estraverse "^4.2.0" - esutils "^2.0.2" - file-entry-cache "^1.1.1" - glob "^7.0.3" - globals "^9.2.0" - ignore "^3.1.2" - imurmurhash "^0.1.4" - inquirer "^0.12.0" - is-my-json-valid "^2.10.0" - is-resolvable "^1.0.0" - js-yaml "^3.5.1" - json-stable-stringify "^1.0.0" - levn "^0.3.0" - lodash "^4.0.0" - mkdirp "^0.5.0" - optionator "^0.8.1" - path-is-absolute "^1.0.0" - path-is-inside "^1.0.1" - pluralize "^1.2.1" - progress "^1.1.8" - require-uncached "^1.0.2" - shelljs "^0.6.0" - strip-json-comments "~1.0.1" - table "^3.7.8" - text-table "~0.2.0" - user-home "^2.0.0" - -eslint@^5.9.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^4.0.3" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.7.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.13.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.11" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" - table "^5.2.3" - text-table "^0.2.0" - -espree@3.5.4, 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== - dependencies: - 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" - integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== - dependencies: - acorn "^6.0.7" - 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" - integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= - -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== - -esquery@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== - dependencies: - estraverse "^4.0.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.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" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -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= - -event-emitter@~0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= - dependencies: - 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= - -events@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" - integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== - -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" - -exec-buffer@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/exec-buffer/-/exec-buffer-3.2.0.tgz#b1686dbd904c7cf982e652c1f5a79b1e5573082b" - integrity sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA== - dependencies: - execa "^0.7.0" - p-finally "^1.0.0" - pify "^3.0.0" - rimraf "^2.5.4" - tempfile "^2.0.0" - -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" - -execa@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.2.tgz#ad87fb7b2d9d564f70d2b62d511bee41d5cbb240" - integrity sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q== - dependencies: - cross-spawn "^7.0.0" - get-stream "^5.0.0" - human-signals "^1.1.1" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.0" - onetime "^5.1.0" - signal-exit "^3.0.2" - strip-final-newline "^2.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= - -exit-hook@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" - integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= - -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@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" - integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE= - dependencies: - kind-of "^1.1.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" - -extend@^3.0.0, extend@~3.0.2: - version "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" - 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" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -eyes@0.1.x: - version "0.1.8" - resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" - integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= - -fancy-log@^1.1.0, fancy-log@^1.2.0, fancy-log@^1.3.2, 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@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= - -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-glob@^3.0.3: - version "3.2.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" - integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.0" - merge2 "^1.3.0" - micromatch "^4.0.2" - picomatch "^2.2.1" - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= - -fast-levenshtein@~2.0.4: - 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.9: - 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== - -fastq@^1.6.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" - integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== - dependencies: - reusify "^1.0.4" - -faye-websocket@~0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.7.3.tgz#cc4074c7f4a4dfd03af54dd65c354b135132ce11" - integrity sha1-zEB0x/Sk39A69U3WXDVLE1EyzhE= - dependencies: - websocket-driver ">=0.3.6" - -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.1" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" - integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== - -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" - -file-entry-cache@^1.1.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-1.3.1.tgz#44c61ea607ae4be9c1402f41f44270cbfe334ff8" - integrity sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g= - dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" - -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@^10.4.0: - version "10.11.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-10.11.0.tgz#2961d09e4675b9fb9a3ee6b69e9cd23f43fd1890" - integrity sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw== - -file-type@^12.0.0: - version "12.4.2" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-12.4.2.tgz#a344ea5664a1d01447ee7fb1b635f72feb6169d9" - integrity sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg== - -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== - -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.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, 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-index@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/find-index/-/find-index-0.1.1.tgz#675d358b2ca3892d795a1ab47232f8b6e2e0dde4" - integrity sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ= - -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.0.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-versions@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.1.0.tgz#10161f29cf3eb4350dec10a29bdde75bff0df32d" - integrity sha512-NCTfNiVzeE/xL+roNDffGuRbrWI6atI18lTJ22vKp7rs2OhYzMK3W1dIdO2TUndH/QMcacM4d1uWwgcZcHK69Q== - dependencies: - array-uniq "^2.1.0" - semver-regex "^2.0.0" - -findup-sync@3.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" - -findup-sync@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" - integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= - dependencies: - detect-file "^1.0.0" - is-glob "^3.1.0" - micromatch "^3.0.4" - resolve-dir "^1.0.1" - -findup-sync@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-4.0.0.tgz#956c9cdde804052b881b428512905c4a5f2cdef0" - integrity sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ== - dependencies: - detect-file "^1.0.0" - is-glob "^4.0.0" - micromatch "^4.0.2" - resolve-dir "^1.0.1" - -fined@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fined/-/fined-1.2.0.tgz#d00beccf1aa2b475d16d423b0238b713a2c4a37b" - integrity sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng== - dependencies: - expand-tilde "^2.0.2" - is-plain-object "^2.0.3" - object.defaults "^1.1.0" - object.pick "^1.2.0" - parse-filepath "^1.0.1" - -first-chunk-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" - integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04= - -flagged-respawn@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41" - integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q== - -flat-cache@^1.2.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" - integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== - dependencies: - circular-json "^0.3.1" - graceful-fs "^4.1.2" - rimraf "~2.6.2" - write "^0.2.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.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" - integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== - -flatten@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" - integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I= - -flora-colossus@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/flora-colossus/-/flora-colossus-1.0.1.tgz#aba198425a8185341e64f9d2a6a96fd9a3cbdb93" - integrity sha512-d+9na7t9FyH8gBJoNDSi28mE4NgQVGGvxQ4aHtFRetjyh5SXjuus+V5EZaxFmFdXVemSOrx0lsgEl/ZMjnOWJA== - dependencies: - debug "^4.1.1" - fs-extra "^7.0.0" - -fluent-ffmpeg@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz#c952de2240f812ebda0aa8006d7776ee2acf7d74" - integrity sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ= - dependencies: - async ">=0.2.9" - which "^1.1.1" - -flush-write-stream@^1.0.0, flush-write-stream@^1.0.2: - 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-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -for-in@^1.0.1, 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= - -for-own@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" - integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= - dependencies: - for-in "^1.0.1" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -fork-stream@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/fork-stream/-/fork-stream-0.0.4.tgz#db849fce77f6708a5f8f386ae533a0907b54ae70" - integrity sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA= - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - 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" - 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" - -front-matter@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-2.1.2.tgz#f75983b9f2f413be658c93dfd7bd8ce4078f5cdb" - integrity sha1-91mDufL0E75ljJPf172M5AePXNs= - dependencies: - js-yaml "^3.4.6" - -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, 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-extra@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^8.0.1, fs-extra@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-minipass@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== - dependencies: - minipass "^2.6.0" - -fs-mkdirp-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" - integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes= - dependencies: - graceful-fs "^4.1.11" - through2 "^2.0.3" - -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.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== - dependencies: - nan "^2.12.1" - node-pre-gyp "^0.12.0" - -fstream@^1.0.0, fstream@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" - integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -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= - -galactus@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/galactus/-/galactus-0.2.1.tgz#cbed2d20a40c1f5679a35908e2b9415733e78db9" - integrity sha1-y+0tIKQMH1Z5o1kI4rlBVzPnjbk= - dependencies: - debug "^3.1.0" - flora-colossus "^1.0.0" - fs-extra "^4.0.0" - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -gaze@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-0.5.2.tgz#40b709537d24d1d45767db5a908689dfe69ac44f" - integrity sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8= - dependencies: - globule "~0.1.0" - -gaze@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" - integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== - dependencies: - globule "^1.0.0" - -generate-function@^2.0.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" - integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== - dependencies: - is-property "^1.0.2" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - integrity sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA= - dependencies: - is-property "^1.0.0" - -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-package-info@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-package-info/-/get-package-info-1.0.0.tgz#6432796563e28113cd9474dbbd00052985a4999c" - integrity sha1-ZDJ5ZWPigRPNlHTbvQAFKYWkmZw= - dependencies: - bluebird "^3.1.1" - debug "^2.2.0" - lodash.get "^4.0.0" - read-pkg-up "^2.0.0" - -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-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, get-stream@^4.1.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-stream@^5.0.0, get-stream@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" - integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== - 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= - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -gifsicle@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/gifsicle/-/gifsicle-5.1.0.tgz#08f878e9048c70adf046185115a6350516a1fdc0" - integrity sha512-hQsOH7yjC7fMokntysN6f2QuxrnX+zmKKKVy0sC3Vhtnk8WrOxLdfH/Z2PNn7lVVx+1+drzIeAe8ufcmdSC/8g== - dependencies: - bin-build "^3.0.0" - bin-wrapper "^4.0.0" - execa "^4.0.0" - logalot "^2.0.0" - -glob-all@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.1.0.tgz#8913ddfb5ee1ac7812656241b03d5217c64b02ab" - integrity sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs= - dependencies: - glob "^7.0.5" - yargs "~1.2.6" - -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.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-stream@^3.1.5: - version "3.1.18" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-3.1.18.tgz#9170a5f12b790306fdfe598f313f8f7954fd143b" - integrity sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs= - dependencies: - glob "^4.3.1" - glob2base "^0.0.12" - minimatch "^2.0.1" - ordered-read-streams "^0.1.0" - through2 "^0.6.1" - unique-stream "^1.0.0" - -glob-stream@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" - integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ= - dependencies: - extend "^3.0.0" - glob "^7.1.1" - glob-parent "^3.1.0" - is-negated-glob "^1.0.0" - ordered-read-streams "^1.0.0" - pumpify "^1.3.5" - readable-stream "^2.1.5" - remove-trailing-separator "^1.0.1" - to-absolute-glob "^2.0.0" - unique-stream "^2.0.2" - -glob-watcher@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-0.0.6.tgz#b95b4a8df74b39c83298b0c05c978b4d9a3b710b" - integrity sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs= - dependencies: - gaze "^0.5.1" - -glob-watcher@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.3.tgz#88a8abf1c4d131eb93928994bc4a593c2e5dd626" - integrity sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg== - dependencies: - anymatch "^2.0.0" - async-done "^1.2.0" - chokidar "^2.0.0" - is-negated-glob "^1.0.0" - just-debounce "^1.0.0" - object.defaults "^1.1.0" - -glob2base@^0.0.12: - version "0.0.12" - resolved "https://registry.yarnpkg.com/glob2base/-/glob2base-0.0.12.tgz#9d419b3e28f12e83a362164a277055922c9c0d56" - integrity sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY= - dependencies: - find-index "^0.1.1" - -glob@^4.3.1: - version "4.5.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" - integrity sha1-xstz0yJsHv7wTePFbQEvAzd+4V8= - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "^2.0.1" - once "^1.3.0" - -glob@^6.0.4: - version "6.0.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - integrity sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI= - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: - version "7.1.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" - integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== - 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" - -glob@^7.1.1: - 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" - -glob@~3.1.21: - version "3.1.21" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd" - integrity sha1-0p4KBV3qUTj00H7UDomC6DwgZs0= - dependencies: - graceful-fs "~1.2.0" - inherits "1" - minimatch "~0.2.11" - -glob@~3.2.6: - version "3.2.11" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" - integrity sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0= - dependencies: - inherits "2" - minimatch "0.3" - -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, globals@^11.7.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@^9.2.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== - -globby@^10.0.0: - version "10.0.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" - integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== - dependencies: - "@types/glob" "^7.1.1" - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.0.3" - glob "^7.1.3" - ignore "^5.1.1" - merge2 "^1.2.3" - slash "^3.0.0" - -globule@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d" - integrity sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ== - dependencies: - glob "~7.1.1" - lodash "~4.17.10" - minimatch "~3.0.2" - -globule@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/globule/-/globule-0.1.0.tgz#d9c8edde1da79d125a151b79533b978676346ae5" - integrity sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU= - dependencies: - glob "~3.1.21" - lodash "~1.0.1" - minimatch "~0.2.11" - -glogg@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" - integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA== - dependencies: - sparkles "^1.0.0" - -gonzales-pe-sl@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/gonzales-pe-sl/-/gonzales-pe-sl-4.2.3.tgz#6a868bc380645f141feeb042c6f97fcc71b59fe6" - integrity sha1-aoaLw4BkXxQf7rBCxvl/zHG1n+Y= - dependencies: - minimist "1.1.x" - -gonzales-pe@^4.2.3: - version "4.2.4" - resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.4.tgz#356ae36a312c46fe0f1026dd6cb539039f8500d2" - integrity sha512-v0Ts/8IsSbh9n1OJRnSfa7Nlxi4AkXIsWB6vPept8FDbL4bXn3FNuxjYtO/nmBGu7GDkL9MFeGebeSu6l55EPQ== - 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" - 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" - -got@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -graceful-fs@^3.0.0: - version "3.0.12" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.12.tgz#0034947ce9ed695ec8ab0b854bc919e82b1ffaef" - integrity sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg== - dependencies: - natives "^1.1.3" - -graceful-fs@^4.0.0, 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, graceful-fs@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" - integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== - -graceful-fs@^4.2.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-fs@~1.2.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364" - integrity sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q= - -"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= - -gulp-audiosprite@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/gulp-audiosprite/-/gulp-audiosprite-1.1.0.tgz#1762d7fb9a669f372b33c1511e3402d79b624892" - integrity sha512-CwSfZjmNPlTyzcAFaE8RiKzh1dQFDLPPZMHshKwvGqNeTB86s30K8hMXGrrjFqHNF9xb0SUnXfbYT32MO4aNog== - dependencies: - audiosprite "*" - through2 "*" - vinyl "*" - -gulp-cache@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/gulp-cache/-/gulp-cache-1.1.3.tgz#7c427670aad4d25364c3cc9c53e492b348190d27" - integrity sha512-NE814LdX1NWQn2sMzn+Rf673o4mqlgg7OyLf92oQ4KEl6DdPfduEGLNH+HexLVcFZXH93DBuxFOvpv4/Js5VaA== - dependencies: - "@babel/runtime" "^7.5.5" - cache-swap "^0.3.0" - core-js "3" - object.pick "^1.3.0" - plugin-error "^1.0.1" - through2 "3.0.1" - vinyl "^2.2.0" - -gulp-cached@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/gulp-cached/-/gulp-cached-1.1.1.tgz#fe7cd4f87f37601e6073cfedee5c2bdaf8b6acce" - integrity sha1-/nzU+H83YB5gc8/t7lwr2vi2rM4= - dependencies: - lodash.defaults "^4.2.0" - through2 "^2.0.1" - -gulp-clean@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/gulp-clean/-/gulp-clean-0.4.0.tgz#3bc25e7084e641bbd7bde057cf90c01c50d95950" - integrity sha512-DARK8rNMo4lHOFLGTiHEJdf19GuoBDHqGUaypz+fOhrvOs3iFO7ntdYtdpNxv+AzSJBx/JfypF0yEj9ks1IStQ== - dependencies: - fancy-log "^1.3.2" - plugin-error "^0.1.2" - rimraf "^2.6.2" - through2 "^2.0.3" - vinyl "^2.1.0" - -gulp-cli@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.3.0.tgz#ec0d380e29e52aa45e47977f0d32e18fd161122f" - integrity sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A== - dependencies: - ansi-colors "^1.0.1" - archy "^1.0.0" - array-sort "^1.0.0" - color-support "^1.1.3" - concat-stream "^1.6.0" - copy-props "^2.0.1" - fancy-log "^1.3.2" - gulplog "^1.0.0" - interpret "^1.4.0" - isobject "^3.0.1" - liftoff "^3.1.0" - matchdep "^2.0.0" - mute-stdout "^1.0.0" - pretty-hrtime "^1.0.0" - replace-homedir "^1.0.0" - semver-greatest-satisfied-range "^1.1.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" - integrity sha512-hD2w2t3fsjPicX2mT6MFFb+eP3FyCVtEHdejGMMH4+w9EBFxA2xIZadqlzYdAEdE+39dP1aGatuhdHJteUvn1A== - dependencies: - jsdom "12.2.0" - plugin-error "1.0.1" - through2 "2.0.3" - -gulp-flatten@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/gulp-flatten/-/gulp-flatten-0.4.0.tgz#d9ac819416c30fd5dfb3dea9da79c83a1bcd61d1" - integrity sha512-eg4spVTAiv1xXmugyaCxWne1oPtNG0UHEtABx5W8ScLiqAYceyYm6GYA36x0Qh8KOIXmAZV97L2aYGnKREG3Sg== - dependencies: - plugin-error "^0.1.2" - through2 "^2.0.0" - -gulp-fluent-ffmpeg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/gulp-fluent-ffmpeg/-/gulp-fluent-ffmpeg-2.0.0.tgz#5b5ed180d317fd3d800ddbcd6376ffb46294b836" - integrity sha512-pwG6N+NKwLzO/0ybzgcwiADKZ4OzpFjNR4drqCvbvluYcSh/yvsAW7wm63jFzpJIjfFnanYGPNWiUn8+TuTR/g== - dependencies: - concat-stream "^2.0.0" - fluent-ffmpeg "^2.1.2" - plugin-error "^1.0.1" - through2 "^3.0.1" - -gulp-html-beautify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gulp-html-beautify/-/gulp-html-beautify-1.0.1.tgz#2834c6f77669605726eee55e3205f63074b7a152" - integrity sha1-KDTG93ZpYFcm7uVeMgX2MHS3oVI= - dependencies: - js-beautify "^1.5.10" - rcloader "^0.1.4" - through2 "^2.0.0" - -gulp-htmlmin@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/gulp-htmlmin/-/gulp-htmlmin-5.0.1.tgz#90fc5e8ad0425a9e86d5d521427184e7276365e7" - integrity sha512-ASlyDPZOSKjHYUifYV0rf9JPDflN9IRIb8lw2vRqtYMC4ljU3zAmnnaVXwFQ3H+CfXxZSUesZ2x7jrnPJu93jA== - dependencies: - html-minifier "^3.5.20" - plugin-error "^1.0.1" - through2 "^2.0.3" - -gulp-if@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/gulp-if/-/gulp-if-3.0.0.tgz#6c3e7edc8bafadc34f2ebecb314bf43324ba1e40" - integrity sha512-fCUEngzNiEZEK2YuPm+sdMpO6ukb8+/qzbGfJBXyNOXz85bCG7yBI+pPSl+N90d7gnLvMsarthsAImx0qy7BAw== - dependencies: - gulp-match "^1.1.0" - ternary-stream "^3.0.0" - through2 "^3.0.1" - -gulp-imagemin@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/gulp-imagemin/-/gulp-imagemin-7.1.0.tgz#d1810a908fb64b4fbf15a750d303d988443e68cf" - integrity sha512-6xBTNybmPY2YrvrhhlS8Mxi0zn0ypusLon63p9XXxDtIf7U7c6KcViz94K7Skosucr3378A6IY2kJSjJyuwylQ== - dependencies: - chalk "^3.0.0" - fancy-log "^1.3.2" - imagemin "^7.0.0" - plugin-error "^1.0.1" - plur "^3.0.1" - pretty-bytes "^5.3.0" - through2-concurrent "^2.0.0" - optionalDependencies: - imagemin-gifsicle "^7.0.0" - imagemin-mozjpeg "^8.0.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" - integrity sha512-U/1Sml7UbyOu2kH6Fbpo+ka2xyp4DRH6+oDtHgC8oKsnlQRuiBQYQ/LS4k6HxBv1HJlucaNV/SdwZXtLBuvSqg== - dependencies: - array-unique "^0.3.2" - fancy-log "^1.2.0" - findup-sync "^4.0.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - micromatch "^4.0.2" - resolve "^1.15.1" - -gulp-match@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/gulp-match/-/gulp-match-1.1.0.tgz#552b7080fc006ee752c90563f9fec9d61aafdf4f" - integrity sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ== - dependencies: - minimatch "^3.0.3" - -gulp-phonegap-build@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/gulp-phonegap-build/-/gulp-phonegap-build-0.1.5.tgz#36c145e63cd204702be0f3b99be19e096712bcaf" - integrity sha1-NsFF5jzSBHAr4PO5m+GeCWcSvK8= - dependencies: - archiver "~0.11.0" - gulp "~3.8.7" - gulp-util "~3.0.0" - lodash "~2.4.1" - needle "" - read "~1.0.4" - through2 "~0.6.1" - vinyl-buffer "0.0.0" - vinyl-source-stream "^0.1.1" - -gulp-plumber@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/gulp-plumber/-/gulp-plumber-1.2.1.tgz#d38700755a300b9d372318e4ffb5ff7ced0b2c84" - integrity sha512-mctAi9msEAG7XzW5ytDVZ9PxWMzzi1pS2rBH7lA095DhMa6KEXjm+St0GOCc567pJKJ/oCvosVAZEpAey0q2eQ== - dependencies: - chalk "^1.1.3" - fancy-log "^1.3.2" - plugin-error "^0.1.2" - through2 "^2.0.3" - -gulp-pngquant@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/gulp-pngquant/-/gulp-pngquant-1.0.13.tgz#7160b4b51080898c9bed896ae0432546c46a8130" - integrity sha512-oSo5Rw2Rb10eyGhc8XKbghq6yteMmxvsSAKGOZU0ssbylMHk3WoTWcEpNg0YWMyRjrY913y+B+PA4wHM1AL2wA== - dependencies: - chalk "^3.0.0" - fancy-log "^1.3.3" - plugin-error "^1.0.1" - pngquant-bin "^5.0.2" - through2 "^3.0.1" - -gulp-postcss@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/gulp-postcss/-/gulp-postcss-8.0.0.tgz#8d3772cd4d27bca55ec8cb4c8e576e3bde4dc550" - integrity sha512-Wtl6vH7a+8IS/fU5W9IbOpcaLqKxd5L1DUOzaPmlnCbX1CrG0aWdwVnC3Spn8th0m8D59YbysV5zPUe1n/GJYg== - dependencies: - fancy-log "^1.3.2" - plugin-error "^1.0.1" - postcss "^7.0.2" - postcss-load-config "^2.0.0" - vinyl-sourcemaps-apply "^0.2.1" - -gulp-rename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-2.0.0.tgz#9bbc3962b0c0f52fc67cd5eaff6c223ec5b9cf6c" - integrity sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ== - -gulp-sass-lint@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/gulp-sass-lint/-/gulp-sass-lint-1.4.0.tgz#6f7096c5abcbc0ce99ddf060c9e1a99067a47ebe" - integrity sha512-XerYvHx7rznInkedMw5Ayif+p8EhysOVHUBvlgUa0FSl88H2cjNjaRZ3NGn5Efmp+2HxpXp4NHqMIbOSdwef3A== - dependencies: - plugin-error "^0.1.2" - sass-lint "^1.12.0" - through2 "^2.0.2" - -gulp-sass@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-4.1.0.tgz#486d7443c32d42bf31a6b1573ebbdaa361de7427" - integrity sha512-xIiwp9nkBLcJDpmYHbEHdoWZv+j+WtYaKD6Zil/67F3nrAaZtWYN5mDwerdo7EvcdBenSAj7Xb2hx2DqURLGdA== - dependencies: - chalk "^2.3.0" - lodash "^4.17.11" - node-sass "^4.8.3" - plugin-error "^1.0.1" - replace-ext "^1.0.0" - strip-ansi "^4.0.0" - through2 "^2.0.0" - vinyl-sourcemaps-apply "^0.2.0" - -"gulp-sftp@git+https://git@github.com/webksde/gulp-sftp": - version "0.1.6" - resolved "git+https://git@github.com/webksde/gulp-sftp#c8dfb20e290477eeed66a867406576d0c3d4fc6b" - dependencies: - async "~0.9.0" - gulp-util "~3.0.0" - object-assign "~0.3.1" - parents "~1.0.0" - ssh2 "~0.6.1" - through2 "~0.4.2" - -gulp-terser@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/gulp-terser/-/gulp-terser-1.2.0.tgz#41df2a1d0257d011ba8b05efb2568432ecd0495b" - integrity sha512-lf+jE2DALg2w32p0HRiYMlFYRYelKZPNunHp2pZccCYrrdCLOs0ItbZcN63yr2pbz116IyhUG9mD/QbtRO1FKA== - dependencies: - plugin-error "^1.0.1" - terser "^4.0.0" - through2 "^3.0.1" - vinyl-sourcemaps-apply "^0.2.1" - -gulp-util@^2.2.19: - version "2.2.20" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-2.2.20.tgz#d7146e5728910bd8f047a6b0b1e549bc22dbd64c" - integrity sha1-1xRuVyiRC9jwR6awseVJvCLb1kw= - dependencies: - chalk "^0.5.0" - dateformat "^1.0.7-1.2.3" - lodash._reinterpolate "^2.4.1" - lodash.template "^2.4.1" - minimist "^0.2.0" - multipipe "^0.1.0" - through2 "^0.5.0" - vinyl "^0.2.1" - -gulp-util@^3.0.0, gulp-util@~3.0.0: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - -gulp-webserver@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/gulp-webserver/-/gulp-webserver-0.9.1.tgz#e09992165d97c5865616d642a1601529b0367064" - integrity sha1-4JmSFl2XxYZWFtZCoWAVKbA2cGQ= - dependencies: - connect "^3.0.1" - connect-livereload "^0.4.0" - gulp-util "^2.2.19" - isarray "0.0.1" - node.extend "^1.0.10" - open "^0.0.5" - proxy-middleware "^0.5.0" - serve-index "^1.1.4" - serve-static "^1.3.0" - through2 "^0.5.1" - tiny-lr "0.1.4" - watch "^0.11.0" - -gulp-yaml@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/gulp-yaml/-/gulp-yaml-2.0.4.tgz#86569e2becc9f5dfc95dc92db5a71a237f4b6ab4" - integrity sha512-S/9Ib8PO+jGkCvWDwBUkmFkeW7QM0pp4PO8NNrMEfWo5Sk30P+KqpyXc4055L/vOX326T/b9MhM4nw5EenyX9g== - dependencies: - bufferstreams "^2.0.1" - js-yaml "^3.13.1" - object-assign "^4.1.1" - plugin-error "^1.0.1" - replace-ext "^1.0.0" - through2 "^3.0.0" - -gulp@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/gulp/-/gulp-4.0.2.tgz#543651070fd0f6ab0a0650c6a3e6ff5a7cb09caa" - integrity sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA== - dependencies: - glob-watcher "^5.0.3" - gulp-cli "^2.2.0" - undertaker "^1.2.1" - vinyl-fs "^3.0.0" - -gulp@~3.8.7: - version "3.8.11" - resolved "https://registry.yarnpkg.com/gulp/-/gulp-3.8.11.tgz#d557e0a7283eb4136491969b0497767972f1d28a" - integrity sha1-1Vfgpyg+tBNkkZabBJd2eXLx0oo= - dependencies: - archy "^1.0.0" - chalk "^0.5.0" - deprecated "^0.0.1" - gulp-util "^3.0.0" - interpret "^0.3.2" - liftoff "^2.0.1" - minimist "^1.1.0" - orchestrator "^0.3.0" - pretty-hrtime "^0.2.0" - semver "^4.1.0" - tildify "^1.0.0" - v8flags "^2.0.2" - vinyl-fs "^0.3.0" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= - 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" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.0: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== - dependencies: - ajv "^6.5.5" - har-schema "^2.0.0" - -has-ansi@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e" - integrity sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4= - dependencies: - ansi-regex "^0.2.0" - -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-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= - dependencies: - sparkles "^1.0.0" - -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: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= - -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-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - -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.1, 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.4" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546" - integrity sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ== - -howler@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/howler/-/howler-2.1.2.tgz#8433a09d8fe84132a3e726e05cb2bd352ef8bd49" - integrity sha512-oKrTFaVXsDRoB/jik7cEpWKTj7VieoiuzMYJ7E/EU5ayvmpRhumCv3YQ3823zi9VTJkSWAhbryHnlZAionGAJg== - -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-encoding-sniffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" - integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== - dependencies: - whatwg-encoding "^1.0.1" - -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.20, 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-cache-semantics@^4.0.0: - version "4.0.3" - 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" - 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-parser-js@>=0.4.0 <0.4.11": - version "0.4.10" - 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= - dependencies: - eventemitter3 "1.x.x" - requires-port "1.x.x" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.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= - -human-signals@^1.1.1: - version "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: - 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" - -iconv-lite@0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.4.tgz#e95f2e41db0735fc21652f7827a5ee32e63c83a8" - integrity sha1-6V8uQdsHNfwhZS94J6XuMuY8g6g= - -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-walk@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.2.tgz#99d83a246c196ea5c93ef9315ad7b0819c35069b" - integrity sha512-EXyErtpHbn75ZTsOADsfx6J/FPo6/5cjev46PXrcTpd8z3BoRkXgYu9/JVqrI7tusjmwCZutGeRJeU0Wo1e4Cw== - dependencies: - minimatch "^3.0.4" - -ignore@^3.1.2: - version "3.3.10" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" - integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== - -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== - -ignore@^5.1.1: - version "5.1.8" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" - integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== - -imagemin-gifsicle@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/imagemin-gifsicle/-/imagemin-gifsicle-7.0.0.tgz#1a7ab136a144c4678657ba3b6c412f80805d26b0" - integrity sha512-LaP38xhxAwS3W8PFh4y5iQ6feoTSF+dTAXFRUEYQWYst6Xd+9L/iPk34QGgK/VO/objmIlmq9TStGfVY2IcHIA== - dependencies: - execa "^1.0.0" - gifsicle "^5.0.0" - is-gif "^3.0.0" - -imagemin-jpegtran@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/imagemin-jpegtran/-/imagemin-jpegtran-7.0.0.tgz#7728f84876362d489b9a1656e0cc8e2009406e6f" - integrity sha512-MJoyTCW8YjMJf56NorFE41SR/WkaGA3IYk4JgvMlRwguJEEd3PnP9UxA8Y2UWjquz8d+On3Ds/03ZfiiLS8xTQ== - dependencies: - exec-buffer "^3.0.0" - is-jpg "^2.0.0" - jpegtran-bin "^5.0.0" - -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-optipng@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/imagemin-optipng/-/imagemin-optipng-7.1.0.tgz#2225c82c35e5c29b7fa98d4f9ecee1161a68e888" - integrity sha512-JNORTZ6j6untH7e5gF4aWdhDCxe3ODsSLKs/f7Grewy3ebZpl1ZsU+VUTPY4rzeHgaFA8GSWOoA8V2M3OixWZQ== - dependencies: - exec-buffer "^3.0.0" - is-png "^2.0.0" - optipng-bin "^6.0.0" - -imagemin-pngquant@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/imagemin-pngquant/-/imagemin-pngquant-9.0.0.tgz#f22ba4276cde1799fb15dd475e33984f8607e871" - integrity sha512-9cqnTEaJwAHWUi+8EMTB3NUouWToCWxtL+QnoYr8bfVwuKilHvRVWKsa9lt+0c3aWaGxCAkHs++j8qINvSqomA== - dependencies: - execa "^4.0.0" - is-png "^2.0.0" - is-stream "^2.0.0" - ow "^0.17.0" - pngquant-bin "^6.0.0" - -imagemin-svgo@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/imagemin-svgo/-/imagemin-svgo-7.0.0.tgz#a22d0a5917a0d0f37e436932c30f5e000fa91b1c" - integrity sha512-+iGJFaPIMx8TjFW6zN+EkOhlqcemdL7F3N3Y0wODvV2kCUBuUtZK7DRZc1+Zfu4U2W/lTMUyx2G8YMOrZntIWg== - dependencies: - is-svg "^3.0.0" - svgo "^1.0.5" - -imagemin@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/imagemin/-/imagemin-7.0.1.tgz#f6441ca647197632e23db7d971fffbd530c87dbf" - integrity sha512-33AmZ+xjZhg2JMCe+vDf6a9mzWukE7l+wAtesjE7KyteqqKjzxv7aVQeWnul1Ve26mWvEQqyPwl0OctNBfSR9w== - dependencies: - file-type "^12.0.0" - globby "^10.0.0" - graceful-fs "^4.2.2" - junk "^3.1.0" - make-dir "^3.0.0" - p-pipe "^3.0.0" - replace-ext "^1.0.0" - -immutable@^3: - version "3.8.2" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" - integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM= - -import-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" - integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= - dependencies: - import-from "^2.1.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.1.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" - integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-from@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" - integrity sha1-M1238qev/VOqpHHUuAId7ja387E= - dependencies: - resolve-from "^3.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= - -in-publish@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" - integrity sha1-4g/146KvwmkDILbcVSaCqcf631E= - -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@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b" - integrity sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js= - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, 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, ini@~1.3.0: - 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@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" - integrity sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34= - dependencies: - ansi-escapes "^1.1.0" - ansi-regex "^2.0.0" - chalk "^1.0.0" - cli-cursor "^1.0.1" - cli-width "^2.0.0" - figures "^1.3.5" - lodash "^4.3.0" - readline2 "^1.0.1" - run-async "^0.1.0" - rx-lite "^3.1.2" - string-width "^1.0.1" - strip-ansi "^3.0.0" - through "^2.3.6" - -inquirer@^6.2.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" - integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== - dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.12" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.1.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== - -interpret@^0.3.2: - version "0.3.10" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-0.3.10.tgz#088c25de731c6c5b112a90f0071cfaf459e5a7bb" - integrity sha1-CIwl3nMcbFsRKpDwBxz69Fnlp7s= - -interpret@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - -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: - 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== - -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" - 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.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" - integrity sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw== - -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-absolute@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" - integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== - dependencies: - is-relative "^1.0.0" - is-windows "^1.0.1" - -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.3" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" - integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== - -is-callable@^1.1.3, is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== - -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.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= - -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.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= - dependencies: - number-is-nan "^1.0.0" - -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-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-gif@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-gif/-/is-gif-3.0.0.tgz#c4be60b26a301d695bb833b20d9b5d66c6cf83b1" - integrity sha512-IqJ/jlbw5WJSNfwQ/lHEDXF8rxhRgF6ythk2oiEvhpG29F704eX9NO6TvPfMiq9DrbwgcEDnETYNcZDPewQoVw== - dependencies: - file-type "^10.4.0" - -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-my-ip-valid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" - integrity sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ== - -is-my-json-valid@^2.10.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz#1345a6fca3e8daefc10d0fa77067f54cedafd59a" - integrity sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA== - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - is-my-ip-valid "^1.0.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - -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-negated-glob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" - integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= - -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-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - -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@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -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.1, 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-property@^1.0.0, is-property@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= - -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= - dependencies: - has "^1.0.1" - -is-relative@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" - integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== - dependencies: - is-unc-path "^1.0.0" - -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.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== - dependencies: - has-symbols "^1.0.0" - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-unc-path@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" - integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== - dependencies: - unc-path-regex "^0.1.2" - -is-utf8@^0.2.0, is-utf8@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-valid-glob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" - integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= - -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= - -is@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/is/-/is-3.3.0.tgz#61cff6dd3c4193db94a3d62582072b44e5645d79" - integrity sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg== - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -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= - -isbinaryfile@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80" - integrity sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw== - dependencies: - buffer-alloc "^1.2.0" - -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= - -isstream@0.1.x, isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -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" - -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" - 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.6" - resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.3.6.tgz#c40382aac9506e7d1f2d856eb02f6c7b2a98b37c" - integrity sha512-MUj2XlMB8kpe+8DJUGH/3UJm4XpI8XEgZQ+CiHDeyrGoKPdW/8FJv6ku+3UiYm5Fz3CWaL+iXmD8Q4Ap6aC1Jw== - -jpegtran-bin@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/jpegtran-bin/-/jpegtran-bin-5.0.1.tgz#3cecaa471726bbcb66adabeeb544c409b17c73e5" - integrity sha512-xQoXWkIEt4ckmvcHd9xG3RcCIn00sf2TshDyFMOAE+46EspEqwqoPWotVI3e55FGWafMa9cEqaoIyrCeWDnFPw== - dependencies: - bin-build "^3.0.0" - bin-wrapper "^4.0.0" - logalot "^2.0.0" - -js-base64@^2.1.8, js-base64@^2.1.9: - version "2.5.1" - 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: - 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== - dependencies: - config-chain "^1.1.12" - editorconfig "^0.15.3" - glob "^7.1.3" - mkdirp "~0.5.1" - nopt "~4.0.1" - -js-levenshtein@^1.1.3: - version "1.1.6" - 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" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.4.6, js-yaml@^3.5.1, js-yaml@^3.5.4: - 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" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -jsdom@12.2.0: - version "12.2.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-12.2.0.tgz#7cf3f5b5eafd47f8f09ca52315d367ff6e95de23" - integrity sha512-QPOggIJ8fquWPLaYYMoh+zqUmdphDtu1ju0QGTitZT1Yd8I5qenPpXM1etzUegu3MjVp8XPzgZxdn8Yj7e40ig== - dependencies: - abab "^2.0.0" - acorn "^6.0.2" - acorn-globals "^4.3.0" - array-equal "^1.0.0" - cssom "^0.3.4" - cssstyle "^1.1.1" - data-urls "^1.0.1" - domexception "^1.0.1" - escodegen "^1.11.0" - html-encoding-sniffer "^1.0.2" - nwsapi "^2.0.9" - parse5 "5.1.0" - pn "^1.1.0" - request "^2.88.0" - request-promise-native "^1.0.5" - saxes "^3.1.3" - symbol-tree "^3.2.2" - tough-cookie "^2.4.3" - w3c-hr-time "^1.0.1" - webidl-conversions "^4.0.2" - whatwg-encoding "^1.0.5" - whatwg-mimetype "^2.2.0" - whatwg-url "^7.0.0" - ws "^6.1.0" - xml-name-validator "^3.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-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -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= - -json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -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" - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= - optionalDependencies: - graceful-fs "^4.1.6" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= - -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk= - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -junk@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" - integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== - -just-debounce@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" - integrity sha1-h/zPrv/AtozRnVX2cilD+SnqNeo= - -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" - -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - -kind-of@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" - integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= - -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, kind-of@^5.0.2: - 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.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== - -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== - -known-css-properties@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.3.0.tgz#a3d135bbfc60ee8c6eacf2f7e7e6f2d4755e49a4" - integrity sha512-QMQcnKAiQccfQTqtBh/qwquGZ2XK/DXND1jrcN9M8gMMy99Gwla7GQjndVUsEqIaRyP6bsFRuhwRj5poafBGJQ== - -last-run@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b" - integrity sha1-RblpQsF7HHnHchmCWbqUO+v4yls= - dependencies: - default-resolution "^2.0.0" - es6-weak-map "^2.0.1" - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= - dependencies: - readable-stream "^2.0.5" - -lazystream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-0.1.0.tgz#1b25d63c772a4c20f0a5ed0a9d77f484b6e16920" - integrity sha1-GyXWPHcqTCDwpe0KnXf0hLbhaSA= - dependencies: - readable-stream "~1.0.2" - -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" - -lead@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" - integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI= - dependencies: - flush-write-stream "^1.0.2" - -levn@^0.3.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" - -liftoff@^2.0.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.5.0.tgz#2009291bb31cea861bbf10a7c15a28caf75c31ec" - integrity sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew= - dependencies: - extend "^3.0.0" - findup-sync "^2.0.0" - fined "^1.0.1" - flagged-respawn "^1.0.0" - is-plain-object "^2.0.4" - object.map "^1.0.0" - rechoir "^0.6.2" - resolve "^1.1.7" - -liftoff@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3" - integrity sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog== - dependencies: - extend "^3.0.0" - findup-sync "^3.0.0" - fined "^1.0.1" - flagged-respawn "^1.0.0" - is-plain-object "^2.0.4" - object.map "^1.0.0" - rechoir "^0.6.2" - resolve "^1.1.7" - -limiter@^1.0.5: - version "1.1.4" - resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.4.tgz#87c9c3972d389fdb0ba67a45aadbc5d2f8413bc1" - integrity sha512-XCpr5bElgDI65vVgstP8TWjv6/QKWm9GU5UG0Pr5sLQ3QLo8NVKsioe+Jed5/3vFOe3IQuqE7DKwTvKQkjTHvg== - -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" - -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.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, loader-utils@^1.0.0, 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== - 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.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" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= - -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= - -lodash._escapehtmlchar@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz#df67c3bb6b7e8e1e831ab48bfa0795b92afe899d" - integrity sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0= - dependencies: - lodash._htmlescapes "~2.4.1" - -lodash._escapestringchar@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz#ecfe22618a2ade50bfeea43937e51df66f0edb72" - integrity sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I= - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - -lodash._htmlescapes@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz#32d14bf0844b6de6f8b62a051b4f67c228b624cb" - integrity sha1-MtFL8IRLbeb4tioFG09nwii2JMs= - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= - -lodash._isnative@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._isnative/-/lodash._isnative-2.4.1.tgz#3ea6404b784a7be836c7b57580e1cdf79b14832c" - integrity sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw= - -lodash._objecttypes@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz#7c0b7f69d98a1f76529f890b0cdb1b4dfec11c11" - integrity sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE= - -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= - -lodash._reinterpolate@^2.4.1, lodash._reinterpolate@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz#4f1227aa5a8711fc632f5b07a1f4607aab8b3222" - integrity sha1-TxInqlqHEfxjL1sHofRgequLMiI= - -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._reunescapedhtml@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz#747c4fc40103eb3bb8a0976e571f7a2659e93ba7" - integrity sha1-dHxPxAED6zu4oJduVx96JlnpO6c= - dependencies: - lodash._htmlescapes "~2.4.1" - lodash.keys "~2.4.1" - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= - -lodash._shimkeys@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz#6e9cc9666ff081f0b5a6c978b83e242e6949d203" - integrity sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM= - 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" - integrity sha1-+CbJtOKoUR2E46yinbBeGk87cqk= - -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.clonedeep@^4.3.2: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= - -lodash.defaults@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" - integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= - -lodash.defaults@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-2.4.1.tgz#a7e8885f05e68851144b6e12a8f3678026bc4c54" - integrity sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ= - dependencies: - lodash._objecttypes "~2.4.1" - lodash.keys "~2.4.1" - -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= - dependencies: - lodash._root "^3.0.0" - -lodash.escape@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-2.4.1.tgz#2ce12c5e084db0a57dda5e5d1eeeb9f5d175a3b4" - integrity sha1-LOEsXghNsKV92l5dHu659dF1o7Q= - dependencies: - lodash._escapehtmlchar "~2.4.1" - lodash._reunescapedhtml "~2.4.1" - lodash.keys "~2.4.1" - -lodash.get@^4.0.0: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= - -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.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" - integrity sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU= - dependencies: - lodash._objecttypes "~2.4.1" - -lodash.kebabcase@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" - integrity sha1-hImxyw0p/4gZXM7KRI/21swpXDY= - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lodash.keys@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-2.4.1.tgz#48dea46df8ff7632b10d706b8acb26591e2b3727" - integrity sha1-SN6kbfj/djKxDXBrissmWR4rNyc= - dependencies: - lodash._isnative "~2.4.1" - lodash._shimkeys "~2.4.1" - lodash.isobject "~2.4.1" - -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.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" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - -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.sortby@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" - integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= - -lodash.template@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-2.4.1.tgz#9e611007edf629129a974ab3c48b817b3e1cf20d" - integrity sha1-nmEQB+32KRKal0qzxIuBez4c8g0= - dependencies: - lodash._escapestringchar "~2.4.1" - lodash._reinterpolate "~2.4.1" - lodash.defaults "~2.4.1" - lodash.escape "~2.4.1" - lodash.keys "~2.4.1" - lodash.templatesettings "~2.4.1" - lodash.values "~2.4.1" - -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - -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@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.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.templatesettings@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz#ea76c75d11eb86d4dbe89a83893bb861929ac699" - integrity sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk= - dependencies: - lodash._reinterpolate "~2.4.1" - lodash.escape "~2.4.1" - -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.values@~2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-2.4.1.tgz#abf514436b3cb705001627978cbcf30b1280eea4" - integrity sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ= - dependencies: - lodash.keys "~2.4.1" - -lodash@^3.0.1: - version "3.10.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: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -lodash@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" - integrity sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE= - -lodash@~2.4.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e" - integrity sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4= - -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" - -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, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -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@2: - version "2.7.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" - integrity sha1-bUUk6LlV+V1PW1iFHOId1y+06VI= - -lru-cache@^4.0.1, lru-cache@^4.1.5: - 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" - -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -make-iterator@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" - integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw== - 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" - integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== - dependencies: - p-defer "^1.0.0" - -map-cache@^0.2.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@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/markdown-loader/-/markdown-loader-5.1.0.tgz#4efd5006b1514ca966141c661a47e542a9836e6e" - integrity sha512-xtQNozLEL+55ZSPTNwro8epZqf1h7HjAZd/69zNe8lbckDiGVHeLQm849bXzocln2pwRK2A/GrW/7MAmwjcFog== - dependencies: - loader-utils "^1.2.3" - marked "^0.7.0" - -marked@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e" - integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg== - -matchdep@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e" - integrity sha1-xvNINKDY28OzfCfui7yyfHd1WC4= - dependencies: - findup-sync "^2.0.0" - micromatch "^3.0.4" - resolve "^1.4.0" - stack-trace "0.0.10" - -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@~1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" - integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== - -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" - -meow@^3.3.0, meow@^3.7.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= - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.2.3: - version "1.3.0" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" - integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== - -merge2@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -merge@^1.2.0: - version "1.2.1" - 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" - 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" - -micromatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" - integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== - dependencies: - braces "^3.0.1" - picomatch "^2.0.5" - -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.40.0: - version "1.40.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" - integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== - -mime-db@^1.28.0: - version "1.41.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.41.0.tgz#9110408e1f6aa1b34aef51f2c9df3caddf46b6a0" - integrity sha512-B5gxBI+2K431XW8C2rcc/lhppbuji67nf9v39eH8pkWoZDxnAL0PxdpH32KYRScniF8qDHBDlI+ipgg5WrCUYw== - -mime-db@~1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.12.0.tgz#3d0c63180f458eb10d325aaa37d7c58ae312e9d7" - integrity sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc= - -mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.24" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" - integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== - dependencies: - mime-db "1.40.0" - -mime-types@~2.0.9: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.0.14.tgz#310e159db23e077f8bb22b748dabfa4957140aa6" - integrity sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY= - dependencies: - mime-db "~1.12.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, mimic-response@^1.0.1: - 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@0.3: - version "0.3.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" - integrity sha1-J12O2qxPG7MyZHIInnlJyDlGmd0= - dependencies: - 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: - 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" - -minimatch@^2.0.1: - version "2.0.10" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" - integrity sha1-jQh8OcazjAAbl/ynzm0OHoCvusc= - dependencies: - brace-expansion "^1.0.0" - -minimatch@~0.2.11: - version "0.2.14" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" - integrity sha1-x054BXT2PG+aCQ6Q775u9TpqdWo= - dependencies: - lru-cache "2" - sigmund "~1.0.0" - -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.x: - version "1.1.3" - 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" - integrity sha1-md9lelJXTCHJBXSX33QnkLK0wN4= - -minimist@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.2.0.tgz#4dffe525dae2b864c66c2e23c6271d7afdecefce" - integrity sha1-Tf/lJdriuGTGbC4jxicdev3s784= - -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== - -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= - -minipass@^2.2.1, minipass@^2.6.0, minipass@^2.6.4: - version "2.7.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.7.0.tgz#c01093a82287c8331f08f1075499fef124888796" - integrity sha512-+CbZuJ4uEiuTL9s5Z/ULkuRg1O9AvVqVvceaBrhbYHIy1R3dPO7FMmG0nZLD0//ZzZq0MUOjwdBQvk+w1JHUqQ== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.2.tgz#6f0ccc82fa53e1bf2ff145f220d2da9fa6e3a166" - integrity sha512-hR3At21uSrsjjDTWrbu0IMLTpnkpv8IIMFDFaoz43Tmu4LkmAXfH44vNNzpTnf+OAQQCHrb91y/wc2J4x5XgSQ== - dependencies: - minipass "^2.2.1" - -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.1.3" - resolved "https://registry.yarnpkg.com/mitt/-/mitt-1.1.3.tgz#528c506238a05dce11cd914a741ea2cc332da9b8" - integrity sha512-mUDCnVNsAi+eD6qA0HkRkwYczbLHJ49z17BGe2PYRhZL4wpZUFZGJHU7/5tmvohoma+Hdn0Vh/oJTiPEmgSruA== - -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, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.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.3: - 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" - -multipipe@^0.1.0, multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= - dependencies: - duplexer2 "0.0.2" - -mute-stdout@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331" - integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg== - -mute-stream@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" - integrity sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA= - -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.4: - 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, nan@^2.13.2: - 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" - -natives@^1.1.3: - version "1.1.6" - resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.6.tgz#a603b4a498ab77173612b9ea1acdec4d980f00bb" - integrity sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA== - -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= - -needle@, needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - -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== - -next-tick@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - -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-gyp@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" - integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA== - dependencies: - fstream "^1.0.0" - glob "^7.0.3" - graceful-fs "^4.1.2" - mkdirp "^0.5.0" - nopt "2 || 3" - npmlog "0 || 1 || 2 || 3 || 4" - osenv "0" - request "^2.87.0" - rimraf "2" - semver "~5.3.0" - tar "^2.0.0" - which "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-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -node-releases@^1.1.29: - version "1.1.32" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.32.tgz#485b35c1bf9b4d8baa105d782f8ca731e518276e" - integrity sha512-VhVknkitq8dqtWoluagsGPn3dxTvN9fwgR59fV3D7sLBHe0JfDramsMI8n8mY//ccq/Kkrf8ZRHRpsyVZ3qw1A== - dependencies: - semver "^5.3.0" - -node-sass@^4.8.3: - version "4.12.0" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.12.0.tgz#0914f531932380114a30cc5fa4fa63233a25f017" - integrity sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ== - dependencies: - async-foreach "^0.1.3" - chalk "^1.1.1" - cross-spawn "^3.0.0" - gaze "^1.0.0" - get-stdin "^4.0.1" - glob "^7.0.3" - in-publish "^2.0.0" - lodash "^4.17.11" - meow "^3.7.0" - mkdirp "^0.5.1" - nan "^2.13.2" - node-gyp "^3.8.0" - npmlog "^4.0.0" - request "^2.88.0" - sass-graph "^2.2.4" - stdout-stream "^1.4.0" - "true-case-path" "^1.0.2" - -node-sri@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/node-sri/-/node-sri-1.1.1.tgz#041096d2b11f232b65dedc4c3ae1cb62babb54b0" - integrity sha1-BBCW0rEfIytl3txMOuHLYrq7VLA= - -node.extend@^1.0.10: - version "1.1.8" - resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.8.tgz#0aab3e63789f4e6d68b42bc00073ad1881243cf0" - integrity sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA== - dependencies: - has "^1.0.3" - is "^3.2.1" - -"nopt@2 || 3": - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= - dependencies: - abbrev "1" - -nopt@^4.0.1, nopt@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - -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== - -normalize-url@^4.1.0: - version "4.4.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.4.1.tgz#81e9c153b0ad5743755696f2aa20488d48e962b6" - integrity sha512-rjH3yRt0Ssx19mUwS0hrDUOdG9VI+oRLpLHJ7tXRdjcuQ7v7wo6qPvOZppHRrqfslTKr0L2yBhjj4UXd7c3cQg== - -now-and-later@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.1.tgz#8e579c8685764a7cc02cb680380e94f43ccb1f7c" - integrity sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ== - dependencies: - once "^1.3.2" - -npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== - -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-packlist@^1.1.6: - version "1.4.4" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" - integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - -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" - -npm-run-path@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~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= - -nwsapi@^2.0.9: - version "2.1.4" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.1.4.tgz#e006a878db23636f8e8a67d33ca0e4edf61a842f" - integrity sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw== - -oauth-sign@~0.9.0: - version "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" - integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= - -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-assign@~0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-0.3.1.tgz#060e2a2a27d7c0d77ec77b78f11aa47fd88008d2" - integrity sha1-Bg4qKifXwNd+x3t48Rqkf9iACNI= - -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.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== - -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-keys@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= - -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.0.4, 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.defaults@^1.0.0, object.defaults@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" - integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8= - dependencies: - array-each "^1.0.1" - array-slice "^1.0.0" - for-own "^1.0.0" - isobject "^3.0.0" - -object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" - -object.map@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" - integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc= - dependencies: - for-own "^1.0.0" - make-iterator "^1.0.0" - -object.pick@^1.2.0, 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.reduce@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object.reduce/-/object.reduce-1.0.1.tgz#6fe348f2ac7fa0f95ca621226599096825bb03ad" - integrity sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60= - dependencies: - for-own "^1.0.0" - make-iterator "^1.0.0" - -object.values@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" - integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.12.0" - 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.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.1.0.tgz#0c539f09291e8ffadde0c8a25850fb2cedc7022d" - integrity sha1-DFOfCSkej/rd4MiiWFD7LO3HAi0= - dependencies: - ee-first "1.0.5" - -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.3.2, 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" - -once@~1.3.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" - integrity sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA= - 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" - integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= - -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" - -open@^0.0.5: - version "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" - integrity sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g== - dependencies: - is-wsl "^1.1.0" - -optimist@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -optionator@^0.8.1, optionator@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.4" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - wordwrap "~1.0.0" - -optipng-bin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/optipng-bin/-/optipng-bin-6.0.0.tgz#376120fa79d5e71eee2f524176efdd3a5eabd316" - integrity sha512-95bB4y8IaTsa/8x6QH4bLUuyvyOoGBCLDA7wOgDL8UFqJpSUh1Hob8JRJhit+wC1ZLN3tQ7mFt7KuBj0x8F2Wg== - dependencies: - bin-build "^3.0.0" - bin-wrapper "^4.0.0" - logalot "^2.0.0" - -orchestrator@^0.3.0: - version "0.3.8" - resolved "https://registry.yarnpkg.com/orchestrator/-/orchestrator-0.3.8.tgz#14e7e9e2764f7315fbac184e506c7aa6df94ad7e" - integrity sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4= - dependencies: - end-of-stream "~0.1.5" - sequencify "~0.0.7" - stream-consume "~0.1.0" - -ordered-read-streams@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz#fd565a9af8eb4473ba69b6ed8a34352cb552f126" - integrity sha1-/VZamvjrRHO6abbtijQ1LLVS8SY= - -ordered-read-streams@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" - integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4= - dependencies: - readable-stream "^2.0.1" - -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-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -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.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= - -osenv@0, osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -ow@^0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/ow/-/ow-0.17.0.tgz#4f938999fed6264c9048cd6254356e0f1e7f688c" - integrity sha512-i3keDzDQP5lWIe4oODyDFey1qVrq2hXKTuTH2VpqwpYtzPiKZt2ziRI4NBQmgW40AnV5Euz17OyWweCb+bNEQA== - dependencies: - type-fest "^0.11.0" - -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-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - -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: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== - 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-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-pipe@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.1.0.tgz#48b57c922aa2e1af6a6404cb7c6bf0eb9cc8e60e" - integrity sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw== - -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.10" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" - integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== - -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" - -parents@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" - integrity sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E= - dependencies: - path-platform "~0.11.15" - -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-author@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/parse-author/-/parse-author-2.0.0.tgz#d3460bf1ddd0dfaeed42da754242e65fb684a81f" - integrity sha1-00YL8d3Q367tQtp1QkLmX7aEqB8= - dependencies: - author-regex "^1.0.0" - -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-filepath@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" - integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE= - dependencies: - is-absolute "^1.0.0" - map-cache "^0.2.0" - path-root "^0.1.1" - -parse-headers@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.2.tgz#9545e8a4c1ae5eaea7d24992bca890281ed26e34" - integrity sha512-/LypJhzFmyBIDYP9aDVgeyEb5sQfbfY5mnDq4hVhlQ69js87wXfmEI5V3xI6vvXasqebp0oCytYFLxsBVfCzSg== - dependencies: - for-each "^0.3.3" - string.prototype.trim "^1.1.2" - -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= - -parse5@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" - integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== - -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" - -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" - integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo= - dependencies: - better-assert "~1.0.0" - -parseurl@~1.3.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-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-is-inside@^1.0.1, path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -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.0.0, 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-platform@~0.11.15: - version "0.11.15" - resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" - integrity sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I= - -path-root-regex@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" - integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0= - -path-root@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" - integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc= - dependencies: - path-root-regex "^0.1.0" - -path-starts-with@^2.0.0: - version "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" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= - dependencies: - pify "^2.0.0" - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -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= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -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.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== - -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" - -pkginfo@0.3.x: - version "0.3.1" - resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21" - integrity sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE= - -plist@^3.0.0, plist@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c" - integrity sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ== - dependencies: - base64-js "^1.2.3" - xmlbuilder "^9.0.7" - xmldom "0.1.x" - -plugin-error@1.0.1, 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" - -plugin-error@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" - integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4= - dependencies: - ansi-cyan "^0.1.1" - ansi-red "^0.1.1" - arr-diff "^1.0.1" - arr-union "^2.0.1" - extend-shallow "^1.1.2" - -plur@^3.0.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/plur/-/plur-3.1.1.tgz#60267967866a8d811504fe58f2faaba237546a5b" - integrity sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w== - dependencies: - irregular-plurals "^2.0.0" - -pluralize@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" - integrity sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU= - -pn@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" - integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== - -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.2: - 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" - -pngquant-bin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/pngquant-bin/-/pngquant-bin-6.0.0.tgz#aff0d7e61095feb96ced379ad8c7294ad3dd1712" - integrity sha512-oXWAS9MQ9iiDAJRdAZ9KO1mC5UwhzKkJsmetiu0iqIjJuW7JsuLhmc4JdRm7uJkIWRzIAou/Vq2VcjfJwz30Ow== - dependencies: - bin-build "^3.0.0" - bin-wrapper "^4.0.1" - execa "^4.0.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.1" - resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.1.tgz#b2a721a0d279c2f9103a36331c88981526428cc7" - integrity sha512-L2YKB3vF4PetdTIthQVeT+7YiSzMoNMLLYxPXXppOOP7NoazEAy45sh2LvJ8leCQjfBcfkYQs8TtCcQjeZTp8A== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0" - -postcss-calc@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" - integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== - dependencies: - css-unit-converter "^1.1.1" - postcss "^7.0.5" - postcss-selector-parser "^5.0.0-rc.4" - postcss-value-parser "^3.3.1" - -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.1" - resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.1.tgz#99d319669a13d6c06ef8e70d852f68cb1b399b61" - integrity sha512-I2Sz83ZSHybMNh02xQDK609lZ1/QOyYeuizCjzEhlMgeV/HcDJapQiH4yTqLjZss0X6/6VvKFXUeObaHpJoINw== - 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-load-config@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003" - integrity sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q== - dependencies: - cosmiconfig "^5.0.0" - import-cwd "^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.1" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" - integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= - dependencies: - dot-prop "^4.1.1" - 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-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.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" - integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== - -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.5, postcss@^7.0.6: - version "7.0.18" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.18.tgz#4b9cda95ae6c069c67a4d933029eddd4838ac233" - integrity sha512-/7g1QXXgegpF+9GJj4iN7ChGF40sYuGYJ8WZu8DZWnmhQ/G36hfdk3q9LBJmoK+lZ+yzZ5KYpOoxq7LF1BxE8g== - dependencies: - chalk "^2.4.2" - source-map "^0.6.1" - supports-color "^6.1.0" - -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= - -pretty-bytes@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" - integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== - -pretty-hrtime@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-0.2.2.tgz#d4fd88351e3a4741f8173af7d6a4b846f9895c00" - integrity sha1-1P2INR46R0H4Fzr31qS4RvmJXAA= - -pretty-hrtime@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" - integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= - -private@^0.1.6, 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@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" - integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= - -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.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" - integrity sha1-2iTV1Ywd3xPa0jfH7KUDhJ6uqQM= - -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= - -psl@^1.1.24, psl@^1.1.28: - version "1.4.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" - integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== - -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, pumpify@^1.3.5: - 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, punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0, punycode@^2.1.1: - 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@2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/qs/-/qs-2.2.4.tgz#2e9fbcd34b540e3421c924ecd01e90aa975319c8" - integrity sha1-Lp+800tUDjQhySTs0B6QqpdTGcg= - -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== - -qs@~2.2.3: - version "2.2.5" - resolved "https://registry.yarnpkg.com/qs/-/qs-2.2.5.tgz#1088abaf9dcc0ae5ae45b709e6c6b5888b23923c" - integrity sha1-EIirr53MCuWuRbcJ5sa1iIsjkjw= - -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -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.8.3" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.8.3.tgz#fd9fb7ffb068b79062b43383685611ee47777d4b" - integrity sha512-llcxWccnyaWlODe7A9hRjkvdCKamEKTh+wH8ITdTc3OhchaqUZteiSCX/2ablWHVrkVIe04dntnaZJ7BdyW0lQ== - 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@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-1.3.0.tgz#978230a156a5548f42eef14de22d0f4f610083d1" - integrity sha1-l4IwoValVI9C7vFN4i0PT2EAg9E= - dependencies: - 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" - 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" - -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -rcedit@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/rcedit/-/rcedit-2.0.0.tgz#dcc85d93aa91a41c1ebc5c6aa1dfc43ea28b7dad" - integrity sha512-XcFGyEBjhWSsud+R8elwQtGBbVkCf7tAiad+nXo5jc6l2rMf46NfGNwjnmBNneBIZDfq+Npf8lwP371JTONfrw== - -rcfinder@^0.1.6: - version "0.1.9" - resolved "https://registry.yarnpkg.com/rcfinder/-/rcfinder-0.1.9.tgz#f3e80f387ddf9ae80ae30a4100329642eae81115" - integrity sha1-8+gPOH3fmugK4wpBADKWQuroERU= - dependencies: - lodash.clonedeep "^4.3.2" - -rcloader@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/rcloader/-/rcloader-0.1.4.tgz#d0c902f0444983a2ee5a6907937c6a79ca704509" - integrity sha1-0MkC8ERJg6LuWmkHk3xqecpwRQk= - dependencies: - 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" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= - dependencies: - find-up "^2.0.0" - read-pkg "^2.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" - -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - -read@~1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" - integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= - dependencies: - mute-stream "~0.0.4" - -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, 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.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - 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@2 || 3": - version "3.4.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" - integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -"readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@~1.0.17, readable-stream@~1.0.2, readable-stream@~1.0.24, readable-stream@~1.0.26: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^1.0.27-1, readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^3.0.2, readable-stream@^3.1.1: - 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.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" - -readline2@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" - integrity sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - mute-stream "0.0.5" - -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" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= - dependencies: - resolve "^1.1.6" - -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.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" - integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== - 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.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" - integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== - -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.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" - integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ== - dependencies: - private "^0.1.6" - -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" - -regexp-tree@^0.1.13: - version "0.1.13" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.13.tgz#5b19ab9377edc68bc3679256840bb29afc158d7f" - integrity sha512-hwdV/GQY5F8ReLZWO+W1SRoN5YfpOKY6852+tBFcma72DKBIcHjPRIlIvQN35bCOljuAfP2G2iB0FC/w236mUw== - -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - -regexpu-core@^4.5.4: - version "4.6.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" - integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.1.0" - regjsgen "^0.5.0" - regjsparser "^0.6.0" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.1.0" - -regjsgen@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd" - integrity sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA== - -regjsparser@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" - integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== - 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-bom-buffer@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" - integrity sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ== - dependencies: - is-buffer "^1.1.5" - is-utf8 "^0.2.1" - -remove-bom-stream@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" - integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM= - dependencies: - remove-bom-buffer "^3.0.0" - safe-buffer "^5.1.0" - through2 "^2.0.3" - -remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0: - 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@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" - integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= - -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= - -replace-homedir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-homedir/-/replace-homedir-1.0.0.tgz#e87f6d513b928dde808260c12be7fec6ff6e798c" - integrity sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw= - dependencies: - homedir-polyfill "^1.0.1" - is-absolute "^1.0.0" - remove-trailing-separator "^1.1.0" - -request-promise-core@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346" - integrity sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag== - dependencies: - lodash "^4.17.11" - -request-promise-native@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.7.tgz#a49868a624bdea5069f1251d0a836e0d89aa2c59" - integrity sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w== - dependencies: - request-promise-core "1.1.2" - stealthy-require "^1.1.1" - tough-cookie "^2.3.3" - -request@^2.87.0, request@^2.88.0: - version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.0" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.4.3" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -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== - -require-uncached@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - -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@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= - -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-options@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" - integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE= - dependencies: - value-or-function "^3.0.0" - -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.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.3.2: - version "1.12.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" - integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== - dependencies: - path-parse "^1.0.6" - -resolve@^1.15.1, resolve@^1.4.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== - 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, 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@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" - integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE= - dependencies: - exit-hook "^1.0.0" - onetime "^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" - -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== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -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, rimraf@^2.4.0, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, 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" - -rimraf@2.6.3, rimraf@~2.6.2: - 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@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.0.tgz#614176d4b3010b75e5c390eb0ee96f6dc0cebb9b" - integrity sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg== - 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@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" - integrity sha1-yK1KXhEGYeQCp9IbUw4AnyX444k= - dependencies: - once "^1.3.0" - -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= - dependencies: - is-promise "^2.1.0" - -run-parallel@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" - integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== - -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-lite@^3.1.2: - version "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: - 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.4.0: - version "6.5.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" - integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== - 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.1.0, 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", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sanitize-filename@^1.6.0, sanitize-filename@^1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378" - integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== - dependencies: - truncate-utf8-bytes "^1.0.0" - -sass-graph@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" - integrity sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k= - dependencies: - glob "^7.0.0" - lodash "^4.0.0" - scss-tokenizer "^0.2.3" - yargs "^7.0.0" - -sass-lint@^1.12.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sass-lint/-/sass-lint-1.13.1.tgz#5fd2b2792e9215272335eb0f0dc607f61e8acc8f" - integrity sha512-DSyah8/MyjzW2BWYmQWekYEKir44BpLqrCFsgs9iaWiVTcwZfwXHF586hh3D1n+/9ihUNMfd8iHAyb9KkGgs7Q== - dependencies: - commander "^2.8.1" - eslint "^2.7.0" - front-matter "2.1.2" - fs-extra "^3.0.1" - glob "^7.0.0" - globule "^1.0.0" - gonzales-pe-sl "^4.2.3" - js-yaml "^3.5.4" - known-css-properties "^0.3.0" - lodash.capitalize "^4.1.0" - lodash.kebabcase "^4.0.0" - merge "^1.2.0" - path-is-absolute "^1.0.0" - util "^0.10.3" - -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, 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== - -saxes@^3.1.3: - version "3.1.11" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.11.tgz#d59d1fd332ec92ad98a2e0b2ee644702384b1c5b" - integrity sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g== - dependencies: - xmlchars "^2.1.1" - -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" - -scss-tokenizer@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" - integrity sha1-jrBtualyMzOCTT9VMGQRSYR85dE= - dependencies: - js-base64 "^2.1.8" - source-map "^0.4.2" - -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-greatest-satisfied-range@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz#13e8c2658ab9691cb0cd71093240280d36f77a5b" - integrity sha1-E+jCZYq5aRywzXEJMkAoDTb3els= - dependencies: - sver-compat "^1.5.0" - -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.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, 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@^4.1.0: - version "4.3.6" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" - integrity sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto= - -semver@^6.0.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= - -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" - -sequencify@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c" - integrity sha1-kM/xnQLgcCf9dn9erT57ldHnOAw= - -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@^1.7.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb" - integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A== - -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" - 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, 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== - 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, 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== - -shelljs@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8" - integrity sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg= - -sigmund@^1.0.1, sigmund@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - -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" - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" - integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= - -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.1" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz#2a805e8a14d6372124dd9159ad4502f8cb07f06b" - integrity sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs= - -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.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== - dependencies: - atob "^2.1.1" - 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.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" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - 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.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - integrity sha1-66T12pwNyZneaAMti092FzZSA2s= - dependencies: - amdefine ">=0.0.4" - -source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, 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" - -sparkles@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" - integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== - -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.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" - 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" - -ssh2-streams@~0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/ssh2-streams/-/ssh2-streams-0.2.1.tgz#9c9c9964be60e9644575af328677f64b1e5cbd79" - integrity sha512-3zCOsmunh1JWgPshfhKmBCL3lUtHPoh+a/cyQ49Ft0Q0aF7xgN06b76L+oKtFi0fgO57FLjFztb1GlJcEZ4a3Q== - dependencies: - asn1 "~0.2.0" - semver "^5.1.0" - streamsearch "~0.1.2" - -ssh2@~0.6.1: - version "0.6.2" - resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-0.6.2.tgz#b065d6e2133a2d4b557447d613b3511cb15e3a2e" - integrity sha512-DJ+dOhXEEsmNpcQTI0x69FS++JH6qqL/ltEHf01pI1SSLMAcmD+hL4jRwvHjPwynPsmSUbHJ/WIZYzROfqZWjA== - dependencies: - ssh2-streams "~0.2.0" - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -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== - -stack-trace@0.0.10, stack-trace@0.0.x: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= - -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== - -stdout-stream@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" - integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA== - dependencies: - readable-stream "^2.0.1" - -stealthy-require@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= - -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-consume@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.1.tgz#d3bdb598c2bd0ae82b8cac7ac50b1107a7996c48" - integrity sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg== - -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-exhaust@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d" - integrity sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw== - -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.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= - -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" - -streamsearch@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" - integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= - -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@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.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.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" - integrity sha512-9EIjYD/WdlvLpn987+ctkLf0FfvBefOCuiEr2henD8X+7jfwPnyvTdmW8OJhj5p+M0/96mBdynLWkxUr+rHlpg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.13.0" - function-bind "^1.1.1" - -string.prototype.trimleft@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== - dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" - -string.prototype.trimright@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== - dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" - -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@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - -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@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.3.0.tgz#25f48ea22ca79187f3174a4db8759347bb126220" - integrity sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA= - dependencies: - ansi-regex "^0.2.1" - -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-bom@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-1.0.0.tgz#85b8862f3844b5a6d5ec8467a93598173a36f794" - integrity sha1-hbiGLzhEtabV7IRnqTWYFzo295Q= - dependencies: - first-chunk-stream "^1.0.0" - is-utf8 "^0.2.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-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - -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-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -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@^2.0.1, strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -strip-json-comments@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" - integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== - -strip-json-comments@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" - integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E= - -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" - -sumchecker@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.0.tgz#da5457b4605184575c76540e5e99cc777cb8ce4c" - integrity sha512-yreseuC/z4iaodVoq07XULEOO9p4jnQazO7mbrnDSvWAU/y2cbyIKs+gWJptfcGu9R+1l27K8Rkj0bfvqnBpgQ== - dependencies: - debug "^4.1.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@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" - integrity sha1-2S3iaU6z9nMjlz1649i1W0wiGQo= - -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" - -sver-compat@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8" - integrity sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg= - dependencies: - es6-iterator "^2.0.1" - es6-symbol "^3.1.1" - -svgo@^1.0.0, svgo@^1.0.5: - version "1.3.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.0.tgz#bae51ba95ded9a33a36b7c46ce9c359ae9154313" - integrity sha512-MLfUA6O+qauLDbym+mMZgtXCGRfIxyQoeH6IKVcFslyODEe/ElJNwr0FohQ3xG4C6HK6bk3KYPPXwHVJk3V5NQ== - 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.33" - csso "^3.5.1" - 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= - -symbol-tree@^3.2.2: - version "3.2.4" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" - integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== - -table@^3.7.8: - version "3.8.3" - resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" - integrity sha1-K7xULw/amGGnVdOUf+/Ys/UThV8= - dependencies: - ajv "^4.7.0" - ajv-keywords "^1.0.0" - chalk "^1.1.1" - lodash "^4.0.0" - slice-ansi "0.0.4" - string-width "^2.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" - -tar-stream@~0.4.0: - version "0.4.7" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-0.4.7.tgz#1f1d2ce9ebc7b42765243ca0e8f1b7bfda0aadcd" - integrity sha1-Hx0s6evHtCdlJDyg6PG3v9oKrc0= - dependencies: - bl "^0.9.0" - end-of-stream "^1.0.0" - readable-stream "^1.0.27-1" - xtend "^4.0.0" - -tar@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" - integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== - dependencies: - block-stream "*" - fstream "^1.0.12" - inherits "2" - -tar@^4: - version "4.4.11" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.11.tgz#7ac09801445a3cf74445ed27499136b5240ffb73" - integrity sha512-iI4zh3ktLJKaDNZKZc+fUONiQrSn9HkCFzamtb7k8FFmVilHVob7QsLX/VySAW8lAviMzMbFw4QtFb4errwgYA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.6.4" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - -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" - -ternary-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ternary-stream/-/ternary-stream-3.0.0.tgz#7951930ea9e823924d956f03d516151a2d516253" - integrity sha512-oIzdi+UL/JdktkT+7KU5tSIQjj8pbShj3OASuvDEhm0NT5lppsm7aXWAmAq4/QMaBIyfuEcNLbAQA+HpaISobQ== - dependencies: - duplexify "^4.1.1" - fork-stream "^0.0.4" - merge-stream "^2.0.0" - through2 "^3.0.1" - -terser-webpack-plugin@^1.1.0, terser-webpack-plugin@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz#61b18e40eaee5be97e771cdbb10ed1280888c2b4" - integrity sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg== - dependencies: - cacache "^12.0.2" - find-cache-dir "^2.1.0" - is-wsl "^1.1.0" - schema-utils "^1.0.0" - serialize-javascript "^1.7.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" - integrity sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg== - dependencies: - commander "^2.20.0" - source-map "~0.6.1" - source-map-support "~0.5.12" - -text-table@^0.2.0, 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-concurrent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/through2-concurrent/-/through2-concurrent-2.0.0.tgz#c9dd2c146504ec9962dbc86a5168b63d662669fa" - integrity sha512-R5/jLkfMvdmDD+seLwN7vB+mhbqzWop5fAjx5IX8/yQq7VhBhzDmhXgaHAOnhnWkCpRMM7gToYHycB0CS/pd+A== - dependencies: - through2 "^2.0.0" - -through2-filter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" - integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@*, through2@3.0.1, through2@^3.0.0, through2@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" - integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== - dependencies: - readable-stream "2 || 3" - -through2@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - integrity sha1-AARWmzfHx0ujnEPzzteNGtlBQL4= - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -through2@^0.4.1, through2@~0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b" - integrity sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s= - dependencies: - readable-stream "~1.0.17" - xtend "~2.1.1" - -through2@^0.5.0, through2@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.5.1.tgz#dfdd012eb9c700e2323fd334f38ac622ab372da7" - integrity sha1-390BLrnHAOIyP9M084rGIqs3Lac= - dependencies: - readable-stream "~1.0.17" - xtend "~3.0.0" - -through2@^0.6.1, through2@~0.6.1: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg= - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - -through2@^2.0.0, through2@^2.0.1, through2@^2.0.2, through2@^2.0.3, 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" - -through2@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.3.0.tgz#2d1d28c8d1daf8d9c5cb78f0a69343c6b8642d97" - integrity sha1-LR0oyNHa+NnFy3jwppNDxrhkLZc= - dependencies: - readable-stream "~1.0.17" - xtend "~2.1.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= - -tildify@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" - integrity sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo= - dependencies: - os-homedir "^1.0.0" - -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= - -tiny-lr@0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/tiny-lr/-/tiny-lr-0.1.4.tgz#6e41d7e67dfd0878e5e0b37e37a06d67e309ff4d" - integrity sha1-bkHX5n39CHjl4LN+N6BtZ+MJ/00= - dependencies: - body-parser "~1.8.0" - debug "~0.8.1" - faye-websocket "~0.7.2" - parseurl "~1.3.0" - qs "~2.2.3" - -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-promise@^1.0.5: - version "1.1.0" - resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-1.1.0.tgz#bb924d239029157b9bc1d506a6aa341f8b13e64c" - integrity sha512-8+Ah9aB1IRXCnIOxXZ0uFozV1nMU5xiu7hhFVUSxZ3bYu+psD4TzagCzVbexUCgNNGJnsmNDQlS4nG3mTyoNkw== - dependencies: - bluebird "^3.5.0" - tmp "0.1.0" - -tmp@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" - integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== - dependencies: - rimraf "^2.6.3" - -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-absolute-glob@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" - integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs= - dependencies: - is-absolute "^1.0.0" - is-negated-glob "^1.0.0" - -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-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - -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" - -to-through@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" - integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY= - dependencies: - through2 "^2.0.3" - -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== - -tough-cookie@^2.3.3, tough-cookie@^2.4.3: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -tough-cookie@~2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== - dependencies: - psl "^1.1.24" - punycode "^1.4.1" - -tr46@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" - integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= - dependencies: - punycode "^2.1.0" - -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-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - -trim@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= - -"true-case-path@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" - integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew== - dependencies: - glob "^7.1.2" - -truncate-utf8-bytes@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" - integrity sha1-QFkjkJWS1W94pYGENLC3hInKXys= - 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" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== - -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" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -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-is@~1.5.1: - version "1.5.7" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.5.7.tgz#b9368a593cc6ef7d0645e78b2f4c64cbecd05e90" - integrity sha1-uTaKWTzG730GReeLL0xky+zQXpA= - dependencies: - 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" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -typedarray@^0.0.6: - version "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== - -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.3.3" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a" - integrity sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg== - dependencies: - buffer "^5.2.1" - through "^2.3.8" - -unc-path-regex@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" - integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= - -underscore@~1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" - integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= - -undertaker-registry@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/undertaker-registry/-/undertaker-registry-1.0.1.tgz#5e4bda308e4a8a2ae584f9b9a4359a499825cc50" - integrity sha1-XkvaMI5KiirlhPm5pDWaSZglzFA= - -undertaker@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.2.1.tgz#701662ff8ce358715324dfd492a4f036055dfe4b" - integrity sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA== - dependencies: - arr-flatten "^1.0.1" - arr-map "^2.0.0" - bach "^1.0.0" - collection-map "^1.0.0" - es6-weak-map "^2.0.1" - last-run "^1.1.0" - object.defaults "^1.0.0" - object.reduce "^1.0.0" - undertaker-registry "^1.0.0" - -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.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" - integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== - -unicode-property-aliases-ecmascript@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" - integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== - -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" - -unique-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b" - integrity sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs= - -unique-stream@^2.0.2: - version "2.3.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" - integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A== - dependencies: - json-stable-stringify-without-jsonify "^1.0.1" - through2-filter "^3.0.0" - -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== - -user-home@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" - integrity sha1-K1viOjK2Onyd640PKNSFcko98ZA= - -user-home@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" - integrity sha1-nHC/2Babwdy/SGBODwS4tJzenp8= - dependencies: - os-homedir "^1.0.0" - -utf8-byte-length@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" - integrity sha1-9F8VDExm7uloGGUFq5P8u4rWv2E= - -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.0" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== - dependencies: - define-properties "^1.1.2" - object.getownpropertydescriptors "^2.0.3" - -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.10.3: - version "0.10.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" - integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== - dependencies: - inherits "2.0.3" - -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, uuid@^3.3.2: - version "3.3.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" - integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== - -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== - -v8flags@^2.0.2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" - integrity sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ= - dependencies: - user-home "^1.1.1" - -v8flags@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.2.0.tgz#b243e3b4dfd731fa774e7492128109a0fe66d656" - integrity sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg== - dependencies: - homedir-polyfill "^1.0.1" - -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@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" - integrity sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw== - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vinyl-buffer@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/vinyl-buffer/-/vinyl-buffer-0.0.0.tgz#d197a824badcb11cccf9643ac91be24d43eda8db" - integrity sha1-0ZeoJLrcsRzM+WQ6yRviTUPtqNs= - dependencies: - bl "^0.7.0" - through2 "^0.4.1" - -vinyl-fs@^0.3.0: - version "0.3.14" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz#9a6851ce1cac1c1cea5fe86c0931d620c2cfa9e6" - integrity sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY= - dependencies: - defaults "^1.0.0" - glob-stream "^3.1.5" - glob-watcher "^0.0.6" - graceful-fs "^3.0.0" - mkdirp "^0.5.0" - strip-bom "^1.0.0" - through2 "^0.6.1" - vinyl "^0.4.0" - -vinyl-fs@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7" - integrity sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng== - dependencies: - fs-mkdirp-stream "^1.0.0" - glob-stream "^6.1.0" - graceful-fs "^4.0.0" - is-valid-glob "^1.0.0" - lazystream "^1.0.0" - lead "^1.0.0" - object.assign "^4.0.4" - pumpify "^1.3.5" - readable-stream "^2.3.3" - remove-bom-buffer "^3.0.0" - remove-bom-stream "^1.2.0" - resolve-options "^1.1.0" - through2 "^2.0.0" - to-through "^2.0.0" - value-or-function "^3.0.0" - vinyl "^2.0.0" - vinyl-sourcemap "^1.1.0" - -vinyl-source-stream@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-0.1.1.tgz#a53a4f21a07a234695e04c2703f9f1b5b9084595" - integrity sha1-pTpPIaB6I0aV4EwnA/nxtbkIRZU= - dependencies: - through2 "~0.3.0" - vinyl "~0.2.2" - -vinyl-sourcemap@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" - integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY= - dependencies: - append-buffer "^1.0.2" - convert-source-map "^1.5.0" - graceful-fs "^4.1.6" - normalize-path "^2.1.1" - now-and-later "^2.0.0" - remove-bom-buffer "^3.0.0" - vinyl "^2.0.0" - -vinyl-sourcemaps-apply@^0.2.0, vinyl-sourcemaps-apply@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" - integrity sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU= - dependencies: - source-map "^0.5.1" - -vinyl@*, vinyl@^2.0.0, vinyl@^2.1.0, vinyl@^2.2.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" - -vinyl@^0.2.1, vinyl@~0.2.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.2.3.tgz#bca938209582ec5a49ad538a00fa1f125e513252" - integrity sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI= - dependencies: - clone-stats "~0.0.1" - -vinyl@^0.4.0: - version "0.4.6" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" - integrity sha1-LzVsh6VQolVGHza76ypbqL94SEc= - dependencies: - clone "^0.2.0" - clone-stats "^0.0.1" - -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vm-browserify@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019" - integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw== - -w3c-hr-time@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" - integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU= - dependencies: - browser-process-hrtime "^0.1.2" - -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" - -watch@^0.11.0: - version "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== - dependencies: - chokidar "^2.0.2" - graceful-fs "^4.1.2" - neo-async "^2.5.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" - integrity sha512-xwnSxWl8nZtBl/AFJCOn9pG7s5CYUYdZxmmukv+fAHLcBIHM36dImfpQg3WfShZXeArkWlf6QRw24Klcsv8a5A== - 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.40.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.40.2.tgz#d21433d250f900bf0facbabe8f50d585b2dc30a7" - integrity sha512-5nIvteTDCUws2DVvP9Qe+JPla7kWPPIDFZv55To7IycHWZ+Z5qBdaBYPyuXWdhggTufZkQwfIK+5rKQTVovm2A== - 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" - 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.1" - 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" - webpack-sources "^1.4.1" - -websocket-driver@>=0.3.6: - version "0.7.3" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" - integrity sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg== - dependencies: - http-parser-js ">=0.4.0 <0.4.11" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" - integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== - -whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" - integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== - dependencies: - iconv-lite "0.4.24" - -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== - -whatwg-mimetype@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" - integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== - -whatwg-url@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.0.0.tgz#fde926fa54a599f3adf82dff25a9f7be02dc6edd" - integrity sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ== - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - -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, which@^1.1.1, 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" - -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - 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" - integrity sha1-NRxY4jI/ikyimkUZWqmqO0w1128= - dependencies: - async "~1.0.0" - colors "1.0.x" - cycle "1.0.x" - eyes "0.1.x" - isstream "0.1.x" - pkginfo "0.3.x" - stack-trace "0.0.x" - -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= - -wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= - -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" - -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" - -write@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= - dependencies: - mkdirp "^0.5.1" - -ws@^6.0.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== - 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-name-validator@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" - integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== - -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.22" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.22.tgz#4fa2d846ec803237de86f30aa9b5f70b6600de02" - integrity sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw== - dependencies: - sax ">=0.6.0" - util.promisify "~1.0.0" - xmlbuilder "~11.0.0" - -xmlbuilder@^9.0.7: - version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= - -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== - -xmlchars@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" - integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== - -xmldom@0.1.x: - version "0.1.27" - resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" - integrity sha1-1QH5ezvbQDr4757MIFcxh6rawOk= - -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 <4.1.0-0", xtend@^4.0.0, 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== - -xtend@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= - dependencies: - object-keys "~0.4.0" - -xtend@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a" - integrity sha1-XM50B7r2Qsunvs2laBEcST9ZZlo= - -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.0, yallist@^3.0.2, yallist@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== - -yaml-loader@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/yaml-loader/-/yaml-loader-0.6.0.tgz#fe1c48b9f4803dace55a59a1474e790ba6ab1b48" - integrity sha512-1bNiLelumURyj+zvVHOv8Y3dpCri0F2S+DCcmps0pA1zWRLjS+FhZQg4o3aUUDYESh73+pKZNI18bj7stpReow== - dependencies: - loader-utils "^1.4.0" - yaml "^1.8.3" - -yaml@^1.8.3: - version "1.10.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" - integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== - -yargs-parser@5.0.0-security.0: - version "5.0.0-security.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz#4ff7271d25f90ac15643b86076a2ab499ec9ee24" - integrity sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ== - dependencies: - camelcase "^3.0.0" - object.assign "^4.1.0" - -yargs-parser@^13.0.0, yargs-parser@^13.1.0: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== - 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-parser@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" - integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= - 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@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" - integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= - 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 "^5.0.0" - -yargs@^7.1.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.1.tgz#67f0ef52e228d4ee0d6311acede8850f53464df6" - integrity sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g== - 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 "5.0.0-security.0" - -yargs@~1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.2.6.tgz#9c7b4a82fd5d595b2bf17ab6dcc43135432fe34b" - integrity sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s= - dependencies: - minimist "^0.1.0" - -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" - -yeast@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" - integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= - -zip-stream@~0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-0.4.1.tgz#4ea795a8ce19e9fab49a31d1d0877214159f03a3" - integrity sha1-TqeVqM4Z6fq0mjHR0IdyFBWfA6M= - dependencies: - compress-commons "~0.1.0" - lodash "~2.4.1" - readable-stream "~1.0.26" +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + dependencies: + "@babel/highlight" "^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/core@^7.9.0": + 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.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.0.tgz#e2c21efbfd3293ad819a2359b448f002bfdfda56" + integrity sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA== + dependencies: + "@babel/types" "^7.6.0" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + trim-right "^1.0.1" + +"@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.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" + integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q== + dependencies: + "@babel/types" "^7.0.0" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" + integrity sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-call-delegate@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz#87c1f8ca19ad552a736a7a27b1c1fcf8b1ff1f43" + integrity sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ== + dependencies: + "@babel/helper-hoist-variables" "^7.4.4" + "@babel/traverse" "^7.4.4" + "@babel/types" "^7.4.4" + +"@babel/helper-define-map@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz#3dec32c2046f37e09b28c93eb0b103fd2a25d369" + integrity sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg== + dependencies: + "@babel/helper-function-name" "^7.1.0" + "@babel/types" "^7.5.5" + lodash "^4.17.13" + +"@babel/helper-explode-assignable-expression@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" + integrity sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA== + dependencies: + "@babel/traverse" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-function-name@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" + integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== + dependencies: + "@babel/helper-get-function-arity" "^7.0.0" + "@babel/template" "^7.1.0" + "@babel/types" "^7.0.0" + +"@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.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" + integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== + dependencies: + "@babel/types" "^7.0.0" + +"@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.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" + integrity sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w== + dependencies: + "@babel/types" "^7.4.4" + +"@babel/helper-member-expression-to-functions@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590" + integrity sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA== + dependencies: + "@babel/types" "^7.5.5" + +"@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.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" + integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== + dependencies: + "@babel/types" "^7.0.0" + +"@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.1.0", "@babel/helper-module-transforms@^7.4.4": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" + integrity sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-simple-access" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/template" "^7.4.4" + "@babel/types" "^7.5.5" + lodash "^4.17.13" + +"@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.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5" + integrity sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g== + dependencies: + "@babel/types" "^7.0.0" + +"@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": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" + integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== + +"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" + integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== + dependencies: + lodash "^4.17.13" + +"@babel/helper-remap-async-to-generator@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" + integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-wrap-function" "^7.1.0" + "@babel/template" "^7.1.0" + "@babel/traverse" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-replace-supers@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2" + integrity sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.5.5" + "@babel/helper-optimise-call-expression" "^7.0.0" + "@babel/traverse" "^7.5.5" + "@babel/types" "^7.5.5" + +"@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.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" + integrity sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w== + dependencies: + "@babel/template" "^7.1.0" + "@babel/types" "^7.0.0" + +"@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.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" + integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== + dependencies: + "@babel/types" "^7.4.4" + +"@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.1.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" + integrity sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ== + dependencies: + "@babel/helper-function-name" "^7.1.0" + "@babel/template" "^7.1.0" + "@babel/traverse" "^7.1.0" + "@babel/types" "^7.2.0" + +"@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.0.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.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.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.0.tgz#3e05d0647432a8326cb28d0de03895ae5a57f39b" + integrity sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ== + +"@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.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" + integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.1.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" + +"@babel/plugin-proposal-dynamic-import@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz#e532202db4838723691b10a67b8ce509e397c506" + integrity sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-dynamic-import" "^7.2.0" + +"@babel/plugin-proposal-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" + integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" + +"@babel/plugin-proposal-object-rest-spread@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz#61939744f71ba76a3ae46b5eea18a54c16d22e58" + integrity sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + +"@babel/plugin-proposal-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" + integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + +"@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz#501ffd9826c0b91da22690720722ac7cb1ca9c78" + integrity sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.5.4" + +"@babel/plugin-syntax-async-generators@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" + integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-dynamic-import@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz#69c159ffaf4998122161ad8ebc5e6d1f55df8612" + integrity sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" + integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-object-rest-spread@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" + integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" + integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-arrow-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" + integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-async-to-generator@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz#89a3848a0166623b5bc481164b5936ab947e887e" + integrity sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-remap-async-to-generator" "^7.1.0" + +"@babel/plugin-transform-block-scoped-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" + integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-block-scoping@^7.4.4", "@babel/plugin-transform-block-scoping@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.0.tgz#c49e21228c4bbd4068a35667e6d951c75439b1dc" + integrity sha512-tIt4E23+kw6TgL/edACZwP1OUKrjOTyMrFMLoT5IOFrfMRabCgekjqFd5o6PaAMildBu46oFkekIdMuGkkPEpA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + lodash "^4.17.13" + +"@babel/plugin-transform-classes@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz#d094299d9bd680a14a2a0edae38305ad60fb4de9" + integrity sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-define-map" "^7.5.5" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-optimise-call-expression" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.5.5" + "@babel/helper-split-export-declaration" "^7.4.4" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" + integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-destructuring@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz#44bbe08b57f4480094d57d9ffbcd96d309075ba6" + integrity sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3" + integrity sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.5.4" + +"@babel/plugin-transform-duplicate-keys@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853" + integrity sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-exponentiation-operator@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" + integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-for-of@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" + integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-function-name@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz#e1436116abb0610c2259094848754ac5230922ad" + integrity sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA== + dependencies: + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" + integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-member-expression-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz#fa10aa5c58a2cb6afcf2c9ffa8cb4d8b3d489a2d" + integrity sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-modules-amd@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz#ef00435d46da0a5961aa728a1d2ecff063e4fb91" + integrity sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg== + dependencies: + "@babel/helper-module-transforms" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-commonjs@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.6.0.tgz#39dfe957de4420445f1fcf88b68a2e4aa4515486" + integrity sha512-Ma93Ix95PNSEngqomy5LSBMAQvYKVe3dy+JlVJSHEXZR5ASL9lQBedMiCyVtmTLraIDVRE3ZjTZvmXXD2Ozw3g== + dependencies: + "@babel/helper-module-transforms" "^7.4.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-simple-access" "^7.1.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-systemjs@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz#e75266a13ef94202db2a0620977756f51d52d249" + integrity sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg== + dependencies: + "@babel/helper-hoist-variables" "^7.4.4" + "@babel/helper-plugin-utils" "^7.0.0" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-umd@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae" + integrity sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw== + dependencies: + "@babel/helper-module-transforms" "^7.1.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.0.tgz#1e6e663097813bb4f53d42df0750cf28ad3bb3f1" + integrity sha512-jem7uytlmrRl3iCAuQyw8BpB4c4LWvSpvIeXKpMb+7j84lkx4m4mYr5ErAcmN5KM7B6BqrAvRGjBIbbzqCczew== + dependencies: + regexp-tree "^0.1.13" + +"@babel/plugin-transform-new-target@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" + integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-object-super@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9" + integrity sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-replace-supers" "^7.5.5" + +"@babel/plugin-transform-parameters@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" + integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== + dependencies: + "@babel/helper-call-delegate" "^7.4.4" + "@babel/helper-get-function-arity" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-property-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz#03e33f653f5b25c4eb572c98b9485055b389e905" + integrity sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-regenerator@^7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz#629dc82512c55cee01341fb27bdfcb210354680f" + integrity sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA== + dependencies: + regenerator-transform "^0.14.0" + +"@babel/plugin-transform-reserved-words@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz#4792af87c998a49367597d07fedf02636d2e1634" + integrity sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-shorthand-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" + integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-spread@^7.2.0": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406" + integrity sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-sticky-regex@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" + integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.0.0" + +"@babel/plugin-transform-template-literals@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" + integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-typeof-symbol@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" + integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +"@babel/plugin-transform-unicode-regex@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f" + integrity sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.5.4" + +"@babel/preset-env@^7.5.4": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.6.0.tgz#aae4141c506100bb2bfaa4ac2a5c12b395619e50" + integrity sha512-1efzxFv/TcPsNXlRhMzRnkBFMeIqBBgzwmZwlFDw5Ubj0AGLeufxugirwZmkkX/ayi3owsSqoQ4fw8LkfK9SYg== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-async-generator-functions" "^7.2.0" + "@babel/plugin-proposal-dynamic-import" "^7.5.0" + "@babel/plugin-proposal-json-strings" "^7.2.0" + "@babel/plugin-proposal-object-rest-spread" "^7.5.5" + "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/plugin-syntax-dynamic-import" "^7.2.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@babel/plugin-transform-arrow-functions" "^7.2.0" + "@babel/plugin-transform-async-to-generator" "^7.5.0" + "@babel/plugin-transform-block-scoped-functions" "^7.2.0" + "@babel/plugin-transform-block-scoping" "^7.6.0" + "@babel/plugin-transform-classes" "^7.5.5" + "@babel/plugin-transform-computed-properties" "^7.2.0" + "@babel/plugin-transform-destructuring" "^7.6.0" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/plugin-transform-duplicate-keys" "^7.5.0" + "@babel/plugin-transform-exponentiation-operator" "^7.2.0" + "@babel/plugin-transform-for-of" "^7.4.4" + "@babel/plugin-transform-function-name" "^7.4.4" + "@babel/plugin-transform-literals" "^7.2.0" + "@babel/plugin-transform-member-expression-literals" "^7.2.0" + "@babel/plugin-transform-modules-amd" "^7.5.0" + "@babel/plugin-transform-modules-commonjs" "^7.6.0" + "@babel/plugin-transform-modules-systemjs" "^7.5.0" + "@babel/plugin-transform-modules-umd" "^7.2.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.6.0" + "@babel/plugin-transform-new-target" "^7.4.4" + "@babel/plugin-transform-object-super" "^7.5.5" + "@babel/plugin-transform-parameters" "^7.4.4" + "@babel/plugin-transform-property-literals" "^7.2.0" + "@babel/plugin-transform-regenerator" "^7.4.5" + "@babel/plugin-transform-reserved-words" "^7.2.0" + "@babel/plugin-transform-shorthand-properties" "^7.2.0" + "@babel/plugin-transform-spread" "^7.2.0" + "@babel/plugin-transform-sticky-regex" "^7.2.0" + "@babel/plugin-transform-template-literals" "^7.4.4" + "@babel/plugin-transform-typeof-symbol" "^7.2.0" + "@babel/plugin-transform-unicode-regex" "^7.4.4" + "@babel/types" "^7.6.0" + browserslist "^4.6.0" + core-js-compat "^3.1.1" + invariant "^2.2.2" + js-levenshtein "^1.1.3" + semver "^5.5.0" + +"@babel/runtime@^7.5.5": + 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.1.0", "@babel/template@^7.4.4": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6" + integrity sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.6.0" + "@babel/types" "^7.6.0" + +"@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.1.0", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.0.tgz#389391d510f79be7ce2ddd6717be66d3fed4b516" + integrity sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.6.0" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/parser" "^7.6.0" + "@babel/types" "^7.6.0" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@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.0.0", "@babel/types@^7.2.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0": + version "7.6.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.1.tgz#53abf3308add3ac2a2884d539151c57c4b3ac648" + integrity sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@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== + +"@electron/get@^1.3.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.5.0.tgz#6217d9d18fb71fbd8cd2445a31aa0edc723d19dd" + integrity sha512-tafxBz6n08G6SX961F/h8XFtpB/DdwRvJJoDeOH9x78jDSCMQ2G/rRWqSwLFp9oeMFBJf0Pf5Kkw6TKt5w9TWg== + dependencies: + debug "^4.1.1" + env-paths "^2.2.0" + fs-extra "^8.1.0" + got "^9.6.0" + sanitize-filename "^1.6.2" + sumchecker "^3.0.0" + +"@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" + +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@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== + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@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/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/glob@^7.1.1": + version "7.1.2" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.2.tgz#06ca26521353a545d94a0adc74f38a59d232c987" + integrity sha512-VgNIkxK+j7Nz5P7jvUZlRvhuPSmsEfS03b0alKcq5V/STUKAa3Plemsn5mrQUO7am6OErJ4rhGEGJbACclrtRA== + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + +"@types/minimatch@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== + +"@types/node@*": + version "14.0.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.13.tgz#ee1128e881b874c371374c1f72201893616417c9" + integrity sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA== + +"@types/node@^12.7.5": + version "12.7.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.5.tgz#e19436e7f8e9b4601005d73673b6dc4784ffcc2f" + integrity sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w== + +"@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== + +"@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== + +abab@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.1.tgz#3fa17797032b71410ec372e11668f4b4ffc86a82" + integrity sha512-1zSbbCuoIjafKZ3mblY5ikvAb0ODUbqBnFuUb7f6uLeQhhGJ0vEV4ntmtxKLT2WgXCO94E07BjunsIw1jOMPZw== + +abbrev@1: + version "1.1.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: + 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-globals@^4.3.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" + integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== + dependencies: + acorn "^6.0.1" + acorn-walk "^6.0.1" + +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.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: + version "6.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" + integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== + +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.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: + 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" + 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@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw= + +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@^4.7.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +ajv@^6.1.0, ajv@^6.10.2, ajv@^6.5.5, ajv@^6.9.1: + version "6.10.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" + integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.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-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-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== + +ansi-cyan@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" + integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= + 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@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + +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-red@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" + integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= + dependencies: + ansi-wrap "0.1.0" + +ansi-regex@^0.2.0, ansi-regex@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" + integrity sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk= + +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@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" + integrity sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94= + +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" + +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" + integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE= + dependencies: + buffer-equal "^1.0.0" + +aproba@^1.0.3, 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" + +archiver@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/archiver/-/archiver-0.11.0.tgz#98177da7a6c0192b7f2798f30cd6eab8abd76690" + integrity sha1-mBd9p6bAGSt/J5jzDNbquKvXZpA= + dependencies: + async "~0.9.0" + buffer-crc32 "~0.2.1" + glob "~3.2.6" + lazystream "~0.1.0" + lodash "~2.4.1" + readable-stream "~1.0.26" + tar-stream "~0.4.0" + zip-stream "~0.4.0" + +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +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@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" + integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo= + dependencies: + arr-flatten "^1.0.1" + array-slice "^0.2.3" + +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-filter@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/arr-filter/-/arr-filter-1.1.2.tgz#43fdddd091e8ef11aa4c45d9cdc18e2dff1711ee" + integrity sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4= + dependencies: + make-iterator "^1.0.0" + +arr-flatten@^1.0.1, 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-map@^2.0.0, arr-map@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/arr-map/-/arr-map-2.0.2.tgz#3a77345ffc1cf35e2a91825601f9e58f2e24cac4" + integrity sha1-Onc0X/wc814qkYJWAfnljy4kysQ= + dependencies: + make-iterator "^1.0.0" + +arr-union@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" + integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0= + +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-each@^1.0.0, array-each@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" + integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8= + +array-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" + integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= + +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-initial@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795" + integrity sha1-L6dLJnOTccOUe9enrcc74zSz15U= + dependencies: + array-slice "^1.0.0" + is-number "^4.0.0" + +array-last@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/array-last/-/array-last-1.3.0.tgz#7aa77073fec565ddab2493f5f88185f404a9d336" + integrity sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg== + dependencies: + is-number "^4.0.0" + +array-slice@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" + integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= + +array-slice@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4" + integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w== + +array-sort@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-1.0.0.tgz#e4c05356453f56f53512a7d1d6123f2c54c0a88a" + integrity sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg== + dependencies: + default-compare "^1.0.0" + get-value "^2.0.6" + kind-of "^5.0.2" + +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.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + +array-uniq@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-2.1.0.tgz#46603d5e28e79bfd02b046fcc1d77c6820bd8e98" + integrity sha512-bdHxtev7FN6+MXI1YFW0Q8mQ8dTJc2S8AMfju+ZR77pbg2yAdVyDlwkaUI7Har0LyOMRFPHrJ9lYdyjZZswdlQ== + +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== + +asar@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/asar/-/asar-2.0.1.tgz#8518a1c62c238109c15a5f742213e83a09b9fd38" + integrity sha512-Vo9yTuUtyFahkVMFaI6uMuX6N7k5DWa6a/8+7ov0/f8Lq9TVR0tUjzSzxQSxT1Y+RJIZgnP7BVb6Uhi+9cjxqA== + dependencies: + chromium-pickle-js "^0.2.0" + commander "^2.20.0" + cuint "^0.2.2" + glob "^7.1.3" + minimatch "^3.0.4" + mkdirp "^0.5.1" + tmp-promise "^1.0.5" + +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" + +asn1@~0.2.0, asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +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-done@^1.2.0, async-done@^1.2.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.3.2.tgz#5e15aa729962a4b07414f528a88cdf18e0b290a2" + integrity sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.2" + process-nextick-args "^2.0.0" + stream-exhaust "^1.0.1" + +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-foreach@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" + integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= + +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-settle@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b" + integrity sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs= + dependencies: + async-done "^1.2.2" + +async@1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= + +async@>=0.2.9: + version "3.1.0" + resolved "https://registry.yarnpkg.com/async/-/async-3.1.0.tgz#42b3b12ae1b74927b5217d8c0016baaf62463772" + integrity sha512-4vx/aaY6j/j3Lw3fbCHNWP0pPaTCew3F6F3hYyl/tHs/ndmV1q7NW9T5yuJ2XAGwdQrP+6Wu20x06U4APo/iQQ== + +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@~0.9.0: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= + +async@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" + integrity sha1-+PwEyjoTeErenhZBr5hXjPvWR6k= + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +audiosprite@*, audiosprite@^0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/audiosprite/-/audiosprite-0.7.2.tgz#ac431a6c30c127bbb6ed743e5d178862ddf9e31e" + integrity sha512-9Z6UwUuv4To5nUQNRIw5/Q3qA7HYm0ANzoW5EDGPEsU2oIRVgmIlLlm9YZfpPKoeUxt54vMStl2/762189VmJw== + dependencies: + async "~0.9.0" + glob "^6.0.4" + mkdirp "^0.5.0" + optimist "~0.6.1" + underscore "~1.8.3" + winston "~1.0.0" + +author-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/author-regex/-/author-regex-1.0.0.tgz#d08885be6b9bbf9439fe087c76287245f0a81450" + integrity sha1-0IiFvmubv5Q5/gh8dihyRfCoFFA= + +autoprefixer@^9.4.3, autoprefixer@^9.4.7, autoprefixer@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.6.1.tgz#51967a02d2d2300bb01866c1611ec8348d355a47" + integrity sha512-aVo5WxR3VyvyJxcJC3h4FKfwCQvQWb1tSI5VHNibddCVWrcD1NvlxEweg3TSgiPztMnWfjpy2FURKA2kvDE+Tw== + dependencies: + browserslist "^4.6.3" + caniuse-lite "^1.0.30000980" + chalk "^2.4.2" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^7.0.17" + postcss-value-parser "^4.0.0" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + +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.1.0: + 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" + +bach@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880" + integrity sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA= + dependencies: + arr-filter "^1.1.1" + arr-flatten "^1.0.1" + arr-map "^2.0.0" + array-each "^1.0.0" + array-initial "^1.0.0" + array-last "^1.1.1" + async-done "^1.2.2" + async-settle "^1.0.0" + now-and-later "^2.0.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, base64-js@^1.2.3: + 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= + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +beeper@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" + integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= + +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" + +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== + +bl@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-0.7.0.tgz#3fb0670602ac2878eb770dc2039f1836be62ae5b" + integrity sha1-P7BnBgKsKHjrdw3CA58YNr5irls= + dependencies: + readable-stream "~1.0.2" + +bl@^0.9.0: + version "0.9.5" + resolved "https://registry.yarnpkg.com/bl/-/bl-0.9.5.tgz#c06b797af085ea00bc527afc8efcf11de2232054" + integrity sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ= + dependencies: + readable-stream "~1.0.26" + +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== + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= + dependencies: + inherits "~2.0.0" + +bluebird@3.x.x, bluebird@^3.1.1, bluebird@^3.4.6, bluebird@^3.5.0, bluebird@^3.5.5: + version "3.5.5" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" + integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== + +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.8.0: + version "1.8.4" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.8.4.tgz#d497e04bc13b3f9a8bd8c70bb0cdc16f2e028898" + integrity sha1-1JfgS8E7P5qL2McLsM3Bby4CiJg= + dependencies: + bytes "1.0.0" + depd "0.4.5" + iconv-lite "0.4.4" + media-typer "0.3.0" + on-finished "2.1.0" + qs "2.2.4" + raw-body "1.3.0" + type-is "~1.5.1" + +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.0.0, 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.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= + +browser-process-hrtime@^0.1.2: + version "0.1.3" + 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.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.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" + immutable "^3" + server-destroy "1.0.1" + socket.io-client "^2.0.4" + stream-throttle "^0.1.3" + +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.10" + browser-sync-ui "^2.26.10" + bs-recipes "1.3.4" + bs-snippet-injector "^2.0.1" + chokidar "^3.4.1" + 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.18.1" + immutable "^3" + localtunnel "^2.0.0" + micromatch "^4.0.2" + 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.18" + yargs "^15.4.1" + +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.6.0, browserslist@^4.6.3, browserslist@^4.6.4, browserslist@^4.6.6: + version "4.7.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.0.tgz#9ee89225ffc07db03409f2fee524dc8227458a17" + integrity sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA== + dependencies: + caniuse-lite "^1.0.30000989" + electron-to-chromium "^1.3.247" + node-releases "^1.1.29" + +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.1, 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-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" + integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= + +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.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" + integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +buffer@^5.2.0, buffer@^5.2.1: + version "5.4.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115" + integrity sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + +bufferstreams@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/bufferstreams/-/bufferstreams-2.0.1.tgz#441b267c2fc3fee02bb1d929289da113903bd5ef" + integrity sha512-ZswyIoBfFb3cVDsnZLLj2IDJ/0ppYdil/v2EGlZXvoefO689FokEmFEldhN5dV7R2QBxFneqTJOMIpfqhj+n0g== + dependencies: + readable-stream "^2.3.6" + +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@1, bytes@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-1.0.0.tgz#3569ede8ba34315fab99c3e92cb04c7220de1fa8" + integrity sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g= + +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.3" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" + integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== + 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" + +cache-swap@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/cache-swap/-/cache-swap-0.3.0.tgz#1c541aa108a50106f630bdd98fe1dec8ba133f51" + integrity sha1-HFQaoQilAQb2ML3Zj+HeyLoTP1E= + dependencies: + graceful-fs "^4.1.2" + mkdirp "^0.5.1" + object-assign "^4.0.1" + rimraf "^2.4.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" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + 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@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= + dependencies: + callsites "^0.2.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@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= + +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.30000980, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30000989: + version "1.0.30000989" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz#b9193e293ccf7e4426c5245134b8f2a56c0ac4b9" + integrity sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +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.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== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" + integrity sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ= + dependencies: + ansi-styles "^1.1.0" + escape-string-regexp "^1.0.0" + has-ansi "^0.1.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" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + 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== + +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== + 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, 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" + integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A== + +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" + +chromium-pickle-js@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205" + integrity sha1-BKEGZywYsIWrd02YPfo+oTjyIgU= + +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.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== + +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.1" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" + integrity sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g== + dependencies: + source-map "~0.6.0" + +cli-cursor@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc= + dependencies: + restore-cursor "^1.0.1" + +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-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, 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@^0.0.1, clone-stats@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" + integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= + +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@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" + integrity sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8= + +clone@^1.0.0, clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + +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" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + +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-map@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-map/-/collection-map-1.0.0.tgz#aea0f06f8d26c780c2b75494385544b2255af18c" + integrity sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw= + dependencies: + arr-map "^2.0.2" + for-own "^1.0.0" + make-iterator "^1.0.0" + +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.x: + 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.3.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" + integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +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.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== + +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= + +compare-version@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/compare-version/-/compare-version-0.1.2.tgz#0162ec2d9351f5ddd59a9202cba935366a725080" + integrity sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA= + +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= + +compress-commons@~0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-0.1.6.tgz#0c740870fde58cba516f0ac0c822e33a0b85dfa3" + integrity sha1-DHQIcP3ljLpRbwrAyCLjOguF36M= + dependencies: + buffer-crc32 "~0.2.1" + crc32-stream "~0.3.1" + readable-stream "~1.0.26" + +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.4.6, concat-stream@^1.5.0, concat-stream@^1.6.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" + +concat-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1" + integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.0.2" + typedarray "^0.0.6" + +config-chain@^1.1.11, config-chain@^1.1.12: + 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-livereload@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/connect-livereload/-/connect-livereload-0.4.1.tgz#0f8a1a816bc9baffae4637ccea917462fe35917a" + integrity sha1-D4oagWvJuv+uRjfM6pF0Yv41kXo= + +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" + +connect@^3.0.1: + version "3.7.0" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +console-browserify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= + dependencies: + date-now "^0.1.4" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +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.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" + +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" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +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= + +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= + +copy-props@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.4.tgz#93bb1cadfafd31da5bb8a9d4b41f471ec3a72dfe" + integrity sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A== + dependencies: + each-props "^1.3.0" + is-plain-object "^2.0.1" + +core-js-compat@^3.1.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.2.1.tgz#0cbdbc2e386e8e00d3b85dc81c848effec5b8150" + integrity sha512-MwPZle5CF9dEaMYdDeWm73ao/IflDH+FjeJCWEADcEgFSE9TLimFKwJsfmkwzI8eC0Aj0mgvMDjeQjrElkz4/A== + dependencies: + browserslist "^4.6.6" + semver "^6.3.0" + +core-js@3: + version "3.2.1" + 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.7: + version "2.6.9" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" + integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== + +core-util-is@1.0.2, 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" + +crc32-stream@~0.3.1: + version "0.3.4" + resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-0.3.4.tgz#73bc25b45fac1db6632231a7bfce8927e9f06552" + integrity sha1-c7wltF+sHbZjIjGnv86JJ+nwZVI= + dependencies: + buffer-crc32 "~0.2.1" + readable-stream "~1.0.24" + +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, cross-spawn@^6.0.5: + 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@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" + integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI= + dependencies: + lru-cache "^4.0.1" + 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.0: + 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" + +cross-zip@^2.1.5: + version "2.1.6" + resolved "https://registry.yarnpkg.com/cross-zip/-/cross-zip-2.1.6.tgz#344d3ba9488609942987d815bb84860cff3d9491" + integrity sha512-xLIETNkzRcU6jGRzenJyRFxahbtP4628xEKMTI/Ql0Vu8m4h8M7uRLVi7E5OYHuJ6VQPsG4icJumKAFUvfm0+A== + dependencies: + rimraf "^3.0.0" + +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" + +crypto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037" + integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig== + +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.0.2" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.2.tgz#ab4386cec9e1f668855564b17c3733b43b2a5ede" + integrity sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ== + dependencies: + boolbase "^1.0.0" + css-what "^2.1.2" + domutils "^1.7.0" + nth-check "^1.0.2" + +css-tree@1.0.0-alpha.29: + version "1.0.0-alpha.29" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" + integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== + dependencies: + mdn-data "~1.1.0" + source-map "^0.5.3" + +css-tree@1.0.0-alpha.33: + version "1.0.0-alpha.33" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.33.tgz#970e20e5a91f7a378ddd0fc58d0b6c8d4f3be93e" + integrity sha512-SPt57bh5nQnpsTBsx/IXbO14sRc9xXu5MtMAVuo0BaQQmyf0NupNPPSoMaqiAF5tDFafYsTkfeH4Q/HCKXkg4w== + dependencies: + mdn-data "2.0.4" + source-map "^0.5.3" + +css-unit-converter@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" + integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= + +css-what@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" + integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== + +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== + +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@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" + integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== + dependencies: + css-tree "1.0.0-alpha.29" + +cssom@0.3.x, cssom@^0.3.4: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^1.1.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1" + integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA== + dependencies: + cssom "0.3.x" + +cuint@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b" + integrity sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs= + +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" + +cycle@1.0.x: + version "1.0.3" + resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" + integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI= + +cyclist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +data-urls@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" + integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ== + dependencies: + abab "^2.0.0" + whatwg-mimetype "^2.2.0" + whatwg-url "^7.0.0" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= + +dateformat@^1.0.7-1.2.3: + version "1.0.12" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" + integrity sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk= + dependencies: + get-stdin "^4.0.1" + meow "^3.3.0" + +dateformat@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" + integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= + +debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8: + 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" + +debug@^3.1.0, debug@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@~0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-0.8.1.tgz#20ff4d26f5e422cb68a1bacbbb61039ad8c1c130" + integrity sha1-IP9NJvXkIstoobrLu2EDmtjBwTA= + +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.0" + resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" + integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= + 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-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +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" + +default-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" + integrity sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ== + dependencies: + kind-of "^5.0.2" + +default-resolution@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684" + integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ= + +defaults@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + +defer-to-connect@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.0.2.tgz#4bae758a314b034ae33902b5aac25a8dd6a8633e" + integrity sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw== + +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" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +delete-empty@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/delete-empty/-/delete-empty-3.0.0.tgz#f8040f2669f26fa7060bc2304e9859c593b685e8" + integrity sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ== + dependencies: + ansi-colors "^4.1.0" + minimist "^1.2.0" + path-starts-with "^2.0.0" + rimraf "^2.6.2" + +depd@0.4.5: + version "0.4.5" + resolved "https://registry.yarnpkg.com/depd/-/depd-0.4.5.tgz#1a664b53388b4a6573e8ae67b5f767c693ca97f1" + integrity sha1-GmZLUziLSmVz6K5ntfdnxpPKl/E= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +deprecated@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19" + integrity sha1-+cmvVGSvoeepcUWKi97yqpTVuxk= + +des.js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= + 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= + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +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" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^1.2.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.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.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.1.tgz#13650c850daffea35d8b626a4cfc4d3a17643fdb" + integrity sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +dom-walk@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" + integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= + +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== + +domexception@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" + integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== + dependencies: + webidl-conversions "^4.0.2" + +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@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== + dependencies: + is-obj "^1.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" + +duplexer2@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" + integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= + dependencies: + readable-stream "~1.1.9" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +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" + +duplexify@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.1.tgz#7027dc374f157b122a8ae08c2d3ea4d2d953aa61" + integrity sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.0" + +each-props@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.2.tgz#ea45a414d16dd5cfa419b1a81720d5ca06892333" + integrity sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA== + dependencies: + is-plain-object "^2.0.1" + object.defaults "^1.1.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" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +editorconfig@^0.15.3: + version "0.15.3" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" + integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== + dependencies: + commander "^2.19.0" + lru-cache "^4.1.5" + semver "^5.6.0" + sigmund "^1.0.1" + +ee-first@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.0.5.tgz#8c9b212898d8cd9f1a9436650ce7be202c9e9ff0" + integrity sha1-jJshKJjYzZ8alDZlDOe+ICyen/A= + +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= + +electron-notarize@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/electron-notarize/-/electron-notarize-0.1.1.tgz#c3563d70c5e7b3315f44e8495b30050a8c408b91" + integrity sha512-TpKfJcz4LXl5jiGvZTs5fbEx+wUFXV5u8voeG5WCHWfY/cdgdD8lDZIZRqLVOtR3VO+drgJ9aiSHIO9TYn/fKg== + dependencies: + debug "^4.1.1" + fs-extra "^8.0.1" + +electron-osx-sign@^0.4.11: + version "0.4.13" + resolved "https://registry.yarnpkg.com/electron-osx-sign/-/electron-osx-sign-0.4.13.tgz#4f77f0ff2f5cd71b91c1e6ce550c3a2937ebbef2" + integrity sha512-+44lasF26lSBLh9HDG6TGpPjuqqtWGD9Pcp+YglE8gyf1OGYdbW8UCIshKPh69O/AcdvDB0ohaTYQz3nbGPbtw== + dependencies: + bluebird "^3.5.0" + compare-version "^0.1.2" + debug "^2.6.8" + isbinaryfile "^3.0.2" + minimist "^1.2.0" + plist "^3.0.1" + +electron-packager@^14.0.6: + version "14.0.6" + resolved "https://registry.yarnpkg.com/electron-packager/-/electron-packager-14.0.6.tgz#e187f2ef83cc29a97a0f940b7c3bb5e4edc8a8e2" + integrity sha512-X+ikV+TnnNkIrK93vOjsjPeykCQBFxBS7LXKMTE1s62rXWirGMdjWL+edVkBOMRkH0ROJyFmWM28Dpj6sfEg+A== + dependencies: + "@electron/get" "^1.3.0" + asar "^2.0.1" + cross-zip "^2.1.5" + debug "^4.0.1" + electron-notarize "^0.1.1" + electron-osx-sign "^0.4.11" + fs-extra "^8.1.0" + galactus "^0.2.1" + get-package-info "^1.0.0" + junk "^3.1.0" + parse-author "^2.0.0" + plist "^3.0.0" + rcedit "^2.0.0" + resolve "^1.1.6" + sanitize-filename "^1.6.0" + semver "^6.0.0" + yargs-parser "^13.0.0" + +electron-to-chromium@^1.3.247: + version "1.3.264" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.264.tgz#ed837f44524d0601a7b2b7b6efd86e35753d0e27" + integrity sha512-z8E7WkrrquCuGYv+kKyybuZIbdms+4PeHp7Zm2uIgEhAigP0bOwqXILItwj0YO73o+QyHY/7XtEfP5DsHOWQgQ== + +elliptic@^6.0.0: + version "6.5.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.1.tgz#c380f5f909bf1b9b4428d028cd18d3b0efd6b52b" + integrity sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg== + 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= + +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" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + dependencies: + once "^1.4.0" + +end-of-stream@^1.4.1: + 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" + +end-of-stream@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf" + integrity sha1-jhdyBsPICDfYVjLouTWd/osvbq8= + dependencies: + once "~1.3.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, 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" + +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== + +env-paths@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" + integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== + +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.12.0, es-abstract@^1.13.0, es-abstract@^1.5.1: + version "1.14.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.14.2.tgz#7ce108fad83068c8783c3cdf62e504e084d8c497" + integrity sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.0" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-inspect "^1.6.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.0.0" + string.prototype.trimright "^2.0.0" + +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.51, es5-ext@~0.10.14: + version "0.10.51" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.51.tgz#ed2d7d9d48a12df86e0299287e93a09ff478842f" + integrity sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.1" + next-tick "^1.0.0" + +es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-map@^0.1.3: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" + integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-set "~0.1.5" + es6-symbol "~3.1.1" + event-emitter "~0.3.5" + +es6-set@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" + integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-symbol "3.1.1" + event-emitter "~0.3.5" + +es6-symbol@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= + dependencies: + d "1" + es5-ext "~0.10.14" + +es6-symbol@^3.1.1, es6-symbol@~3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.2.tgz#859fdd34f32e905ff06d752e7171ddd4444a7ed1" + integrity sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ== + dependencies: + d "^1.0.1" + es5-ext "^0.10.51" + +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" + +es6-weak-map@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== + dependencies: + d "1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" + es6-symbol "^3.1.1" + +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.0, 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@^1.11.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541" + integrity sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg== + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +escope@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= + dependencies: + es6-map "^0.1.3" + es6-weak-map "^2.0.1" + esrecurse "^4.1.0" + estraverse "^4.1.1" + +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-utils@^1.3.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" + integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== + dependencies: + eslint-visitor-keys "^1.0.0" + +eslint-visitor-keys@^1.0.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@^2.7.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-2.13.1.tgz#e4cc8fa0f009fb829aaae23855a29360be1f6c11" + integrity sha1-5MyPoPAJ+4KaquI4VaKTYL4fbBE= + dependencies: + chalk "^1.1.3" + concat-stream "^1.4.6" + debug "^2.1.1" + doctrine "^1.2.2" + es6-map "^0.1.3" + escope "^3.6.0" + espree "^3.1.6" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^1.1.1" + glob "^7.0.3" + globals "^9.2.0" + ignore "^3.1.2" + imurmurhash "^0.1.4" + inquirer "^0.12.0" + is-my-json-valid "^2.10.0" + is-resolvable "^1.0.0" + js-yaml "^3.5.1" + json-stable-stringify "^1.0.0" + levn "^0.3.0" + lodash "^4.0.0" + mkdirp "^0.5.0" + optionator "^0.8.1" + path-is-absolute "^1.0.0" + path-is-inside "^1.0.1" + pluralize "^1.2.1" + progress "^1.1.8" + require-uncached "^1.0.2" + shelljs "^0.6.0" + strip-json-comments "~1.0.1" + table "^3.7.8" + text-table "~0.2.0" + user-home "^2.0.0" + +eslint@^5.9.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" + integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.9.1" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^4.0.3" + eslint-utils "^1.3.1" + eslint-visitor-keys "^1.0.0" + espree "^5.0.1" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^6.2.2" + js-yaml "^3.13.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.11" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^5.5.1" + strip-ansi "^4.0.0" + strip-json-comments "^2.0.1" + table "^5.2.3" + text-table "^0.2.0" + +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== + dependencies: + acorn "^5.5.0" + acorn-jsx "^3.0.0" + +espree@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" + integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== + dependencies: + acorn "^6.0.7" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" + +esprima@^3.1.3, esprima@~3.1.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= + +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== + +esquery@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== + dependencies: + estraverse "^4.0.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.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" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +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= + +event-emitter@~0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= + dependencies: + d "1" + es5-ext "~0.10.14" + +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" + resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" + integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== + +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" + +exec-buffer@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/exec-buffer/-/exec-buffer-3.2.0.tgz#b1686dbd904c7cf982e652c1f5a79b1e5573082b" + integrity sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA== + dependencies: + execa "^0.7.0" + p-finally "^1.0.0" + pify "^3.0.0" + rimraf "^2.5.4" + tempfile "^2.0.0" + +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" + +execa@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.2.tgz#ad87fb7b2d9d564f70d2b62d511bee41d5cbb240" + integrity sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.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= + +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= + +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" + +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@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" + integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE= + dependencies: + kind-of "^1.1.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" + +extend@^3.0.0, extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +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" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +eyes@0.1.x: + version "0.1.8" + resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= + +fancy-log@^1.1.0, fancy-log@^1.2.0, fancy-log@^1.3.2, 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@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +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-glob@^3.0.3: + version "3.2.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" + integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +fast-levenshtein@~2.0.4: + 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.9: + 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== + +fastq@^1.6.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" + integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== + dependencies: + reusify "^1.0.4" + +faye-websocket@~0.7.2: + version "0.7.3" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.7.3.tgz#cc4074c7f4a4dfd03af54dd65c354b135132ce11" + integrity sha1-zEB0x/Sk39A69U3WXDVLE1EyzhE= + dependencies: + websocket-driver ">=0.3.6" + +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.1" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" + integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== + +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" + +file-entry-cache@^1.1.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-1.3.1.tgz#44c61ea607ae4be9c1402f41f44270cbfe334ff8" + integrity sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g= + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +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@^10.4.0: + version "10.11.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-10.11.0.tgz#2961d09e4675b9fb9a3ee6b69e9cd23f43fd1890" + integrity sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw== + +file-type@^12.0.0: + version "12.4.2" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-12.4.2.tgz#a344ea5664a1d01447ee7fb1b635f72feb6169d9" + integrity sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg== + +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== + +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" + +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.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-index@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-index/-/find-index-0.1.1.tgz#675d358b2ca3892d795a1ab47232f8b6e2e0dde4" + integrity sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ= + +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.0.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.1.0" + resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.1.0.tgz#10161f29cf3eb4350dec10a29bdde75bff0df32d" + integrity sha512-NCTfNiVzeE/xL+roNDffGuRbrWI6atI18lTJ22vKp7rs2OhYzMK3W1dIdO2TUndH/QMcacM4d1uWwgcZcHK69Q== + dependencies: + array-uniq "^2.1.0" + semver-regex "^2.0.0" + +findup-sync@3.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" + +findup-sync@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" + integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= + dependencies: + detect-file "^1.0.0" + is-glob "^3.1.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + +findup-sync@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-4.0.0.tgz#956c9cdde804052b881b428512905c4a5f2cdef0" + integrity sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ== + dependencies: + detect-file "^1.0.0" + is-glob "^4.0.0" + micromatch "^4.0.2" + resolve-dir "^1.0.1" + +fined@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fined/-/fined-1.2.0.tgz#d00beccf1aa2b475d16d423b0238b713a2c4a37b" + integrity sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng== + dependencies: + expand-tilde "^2.0.2" + is-plain-object "^2.0.3" + object.defaults "^1.1.0" + object.pick "^1.2.0" + parse-filepath "^1.0.1" + +first-chunk-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" + integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04= + +flagged-respawn@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41" + integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q== + +flat-cache@^1.2.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" + integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== + dependencies: + circular-json "^0.3.1" + graceful-fs "^4.1.2" + rimraf "~2.6.2" + write "^0.2.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.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" + integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== + +flatten@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" + integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I= + +flora-colossus@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/flora-colossus/-/flora-colossus-1.0.1.tgz#aba198425a8185341e64f9d2a6a96fd9a3cbdb93" + integrity sha512-d+9na7t9FyH8gBJoNDSi28mE4NgQVGGvxQ4aHtFRetjyh5SXjuus+V5EZaxFmFdXVemSOrx0lsgEl/ZMjnOWJA== + dependencies: + debug "^4.1.1" + fs-extra "^7.0.0" + +fluent-ffmpeg@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz#c952de2240f812ebda0aa8006d7776ee2acf7d74" + integrity sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ= + dependencies: + async ">=0.2.9" + which "^1.1.1" + +flush-write-stream@^1.0.0, flush-write-stream@^1.0.2: + 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" + +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" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +for-in@^1.0.1, 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= + +for-own@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" + integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= + dependencies: + for-in "^1.0.1" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +fork-stream@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/fork-stream/-/fork-stream-0.0.4.tgz#db849fce77f6708a5f8f386ae533a0907b54ae70" + integrity sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +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" + +front-matter@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-2.1.2.tgz#f75983b9f2f413be658c93dfd7bd8ce4078f5cdb" + integrity sha1-91mDufL0E75ljJPf172M5AePXNs= + dependencies: + js-yaml "^3.4.6" + +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, 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-extra@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^8.0.1, fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-minipass@^1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + +fs-mkdirp-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" + integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes= + dependencies: + graceful-fs "^4.1.11" + through2 "^2.0.3" + +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.9" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" + integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== + dependencies: + 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" + integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +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= + +galactus@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/galactus/-/galactus-0.2.1.tgz#cbed2d20a40c1f5679a35908e2b9415733e78db9" + integrity sha1-y+0tIKQMH1Z5o1kI4rlBVzPnjbk= + dependencies: + debug "^3.1.0" + flora-colossus "^1.0.0" + fs-extra "^4.0.0" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +gaze@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-0.5.2.tgz#40b709537d24d1d45767db5a908689dfe69ac44f" + integrity sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8= + dependencies: + globule "~0.1.0" + +gaze@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" + integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== + dependencies: + globule "^1.0.0" + +generate-function@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" + integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== + dependencies: + is-property "^1.0.2" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + integrity sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA= + dependencies: + is-property "^1.0.0" + +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-package-info@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-package-info/-/get-package-info-1.0.0.tgz#6432796563e28113cd9474dbbd00052985a4999c" + integrity sha1-ZDJ5ZWPigRPNlHTbvQAFKYWkmZw= + dependencies: + bluebird "^3.1.1" + debug "^2.2.0" + lodash.get "^4.0.0" + read-pkg-up "^2.0.0" + +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-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, get-stream@^4.1.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-stream@^5.0.0, get-stream@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + 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= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +gifsicle@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/gifsicle/-/gifsicle-5.1.0.tgz#08f878e9048c70adf046185115a6350516a1fdc0" + integrity sha512-hQsOH7yjC7fMokntysN6f2QuxrnX+zmKKKVy0sC3Vhtnk8WrOxLdfH/Z2PNn7lVVx+1+drzIeAe8ufcmdSC/8g== + dependencies: + bin-build "^3.0.0" + bin-wrapper "^4.0.0" + execa "^4.0.0" + logalot "^2.0.0" + +glob-all@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.1.0.tgz#8913ddfb5ee1ac7812656241b03d5217c64b02ab" + integrity sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs= + dependencies: + glob "^7.0.5" + yargs "~1.2.6" + +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.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== + dependencies: + is-glob "^4.0.1" + +glob-stream@^3.1.5: + version "3.1.18" + resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-3.1.18.tgz#9170a5f12b790306fdfe598f313f8f7954fd143b" + integrity sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs= + dependencies: + glob "^4.3.1" + glob2base "^0.0.12" + minimatch "^2.0.1" + ordered-read-streams "^0.1.0" + through2 "^0.6.1" + unique-stream "^1.0.0" + +glob-stream@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" + integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ= + dependencies: + extend "^3.0.0" + glob "^7.1.1" + glob-parent "^3.1.0" + is-negated-glob "^1.0.0" + ordered-read-streams "^1.0.0" + pumpify "^1.3.5" + readable-stream "^2.1.5" + remove-trailing-separator "^1.0.1" + to-absolute-glob "^2.0.0" + unique-stream "^2.0.2" + +glob-watcher@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-0.0.6.tgz#b95b4a8df74b39c83298b0c05c978b4d9a3b710b" + integrity sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs= + dependencies: + gaze "^0.5.1" + +glob-watcher@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.3.tgz#88a8abf1c4d131eb93928994bc4a593c2e5dd626" + integrity sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg== + dependencies: + anymatch "^2.0.0" + async-done "^1.2.0" + chokidar "^2.0.0" + is-negated-glob "^1.0.0" + just-debounce "^1.0.0" + object.defaults "^1.1.0" + +glob2base@^0.0.12: + version "0.0.12" + resolved "https://registry.yarnpkg.com/glob2base/-/glob2base-0.0.12.tgz#9d419b3e28f12e83a362164a277055922c9c0d56" + integrity sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY= + dependencies: + find-index "^0.1.1" + +glob@^4.3.1: + version "4.5.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" + integrity sha1-xstz0yJsHv7wTePFbQEvAzd+4V8= + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "^2.0.1" + once "^1.3.0" + +glob@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" + integrity sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI= + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" + integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== + 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" + +glob@^7.1.1: + 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" + +glob@~3.1.21: + version "3.1.21" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd" + integrity sha1-0p4KBV3qUTj00H7UDomC6DwgZs0= + dependencies: + graceful-fs "~1.2.0" + inherits "1" + minimatch "~0.2.11" + +glob@~3.2.6: + version "3.2.11" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" + integrity sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0= + dependencies: + inherits "2" + minimatch "0.3" + +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, globals@^11.7.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@^9.2.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +globby@^10.0.0: + version "10.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" + integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + +globule@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d" + integrity sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ== + dependencies: + glob "~7.1.1" + lodash "~4.17.10" + minimatch "~3.0.2" + +globule@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/globule/-/globule-0.1.0.tgz#d9c8edde1da79d125a151b79533b978676346ae5" + integrity sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU= + dependencies: + glob "~3.1.21" + lodash "~1.0.1" + minimatch "~0.2.11" + +glogg@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" + integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA== + dependencies: + sparkles "^1.0.0" + +gonzales-pe-sl@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/gonzales-pe-sl/-/gonzales-pe-sl-4.2.3.tgz#6a868bc380645f141feeb042c6f97fcc71b59fe6" + integrity sha1-aoaLw4BkXxQf7rBCxvl/zHG1n+Y= + dependencies: + minimist "1.1.x" + +gonzales-pe@^4.2.3: + version "4.2.4" + resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.4.tgz#356ae36a312c46fe0f1026dd6cb539039f8500d2" + integrity sha512-v0Ts/8IsSbh9n1OJRnSfa7Nlxi4AkXIsWB6vPept8FDbL4bXn3FNuxjYtO/nmBGu7GDkL9MFeGebeSu6l55EPQ== + dependencies: + minimist "1.1.x" + +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" + +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +graceful-fs@^3.0.0: + version "3.0.12" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.12.tgz#0034947ce9ed695ec8ab0b854bc919e82b1ffaef" + integrity sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg== + dependencies: + natives "^1.1.3" + +graceful-fs@^4.0.0, 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, graceful-fs@^4.2.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" + integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== + +graceful-fs@^4.2.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-fs@~1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364" + integrity sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q= + +"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= + +gulp-audiosprite@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/gulp-audiosprite/-/gulp-audiosprite-1.1.0.tgz#1762d7fb9a669f372b33c1511e3402d79b624892" + integrity sha512-CwSfZjmNPlTyzcAFaE8RiKzh1dQFDLPPZMHshKwvGqNeTB86s30K8hMXGrrjFqHNF9xb0SUnXfbYT32MO4aNog== + dependencies: + audiosprite "*" + through2 "*" + vinyl "*" + +gulp-cache@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/gulp-cache/-/gulp-cache-1.1.3.tgz#7c427670aad4d25364c3cc9c53e492b348190d27" + integrity sha512-NE814LdX1NWQn2sMzn+Rf673o4mqlgg7OyLf92oQ4KEl6DdPfduEGLNH+HexLVcFZXH93DBuxFOvpv4/Js5VaA== + dependencies: + "@babel/runtime" "^7.5.5" + cache-swap "^0.3.0" + core-js "3" + object.pick "^1.3.0" + plugin-error "^1.0.1" + through2 "3.0.1" + vinyl "^2.2.0" + +gulp-cached@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/gulp-cached/-/gulp-cached-1.1.1.tgz#fe7cd4f87f37601e6073cfedee5c2bdaf8b6acce" + integrity sha1-/nzU+H83YB5gc8/t7lwr2vi2rM4= + dependencies: + lodash.defaults "^4.2.0" + through2 "^2.0.1" + +gulp-clean@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/gulp-clean/-/gulp-clean-0.4.0.tgz#3bc25e7084e641bbd7bde057cf90c01c50d95950" + integrity sha512-DARK8rNMo4lHOFLGTiHEJdf19GuoBDHqGUaypz+fOhrvOs3iFO7ntdYtdpNxv+AzSJBx/JfypF0yEj9ks1IStQ== + dependencies: + fancy-log "^1.3.2" + plugin-error "^0.1.2" + rimraf "^2.6.2" + through2 "^2.0.3" + vinyl "^2.1.0" + +gulp-cli@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.3.0.tgz#ec0d380e29e52aa45e47977f0d32e18fd161122f" + integrity sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A== + dependencies: + ansi-colors "^1.0.1" + archy "^1.0.0" + array-sort "^1.0.0" + color-support "^1.1.3" + concat-stream "^1.6.0" + copy-props "^2.0.1" + fancy-log "^1.3.2" + gulplog "^1.0.0" + interpret "^1.4.0" + isobject "^3.0.1" + liftoff "^3.1.0" + matchdep "^2.0.0" + mute-stdout "^1.0.0" + pretty-hrtime "^1.0.0" + replace-homedir "^1.0.0" + semver-greatest-satisfied-range "^1.1.0" + v8flags "^3.2.0" + yargs "^7.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" + integrity sha512-hD2w2t3fsjPicX2mT6MFFb+eP3FyCVtEHdejGMMH4+w9EBFxA2xIZadqlzYdAEdE+39dP1aGatuhdHJteUvn1A== + dependencies: + jsdom "12.2.0" + plugin-error "1.0.1" + through2 "2.0.3" + +gulp-flatten@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/gulp-flatten/-/gulp-flatten-0.4.0.tgz#d9ac819416c30fd5dfb3dea9da79c83a1bcd61d1" + integrity sha512-eg4spVTAiv1xXmugyaCxWne1oPtNG0UHEtABx5W8ScLiqAYceyYm6GYA36x0Qh8KOIXmAZV97L2aYGnKREG3Sg== + dependencies: + plugin-error "^0.1.2" + through2 "^2.0.0" + +gulp-fluent-ffmpeg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/gulp-fluent-ffmpeg/-/gulp-fluent-ffmpeg-2.0.0.tgz#5b5ed180d317fd3d800ddbcd6376ffb46294b836" + integrity sha512-pwG6N+NKwLzO/0ybzgcwiADKZ4OzpFjNR4drqCvbvluYcSh/yvsAW7wm63jFzpJIjfFnanYGPNWiUn8+TuTR/g== + dependencies: + concat-stream "^2.0.0" + fluent-ffmpeg "^2.1.2" + plugin-error "^1.0.1" + through2 "^3.0.1" + +gulp-html-beautify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gulp-html-beautify/-/gulp-html-beautify-1.0.1.tgz#2834c6f77669605726eee55e3205f63074b7a152" + integrity sha1-KDTG93ZpYFcm7uVeMgX2MHS3oVI= + dependencies: + js-beautify "^1.5.10" + rcloader "^0.1.4" + through2 "^2.0.0" + +gulp-htmlmin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/gulp-htmlmin/-/gulp-htmlmin-5.0.1.tgz#90fc5e8ad0425a9e86d5d521427184e7276365e7" + integrity sha512-ASlyDPZOSKjHYUifYV0rf9JPDflN9IRIb8lw2vRqtYMC4ljU3zAmnnaVXwFQ3H+CfXxZSUesZ2x7jrnPJu93jA== + dependencies: + html-minifier "^3.5.20" + plugin-error "^1.0.1" + through2 "^2.0.3" + +gulp-if@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/gulp-if/-/gulp-if-3.0.0.tgz#6c3e7edc8bafadc34f2ebecb314bf43324ba1e40" + integrity sha512-fCUEngzNiEZEK2YuPm+sdMpO6ukb8+/qzbGfJBXyNOXz85bCG7yBI+pPSl+N90d7gnLvMsarthsAImx0qy7BAw== + dependencies: + gulp-match "^1.1.0" + ternary-stream "^3.0.0" + through2 "^3.0.1" + +gulp-imagemin@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/gulp-imagemin/-/gulp-imagemin-7.1.0.tgz#d1810a908fb64b4fbf15a750d303d988443e68cf" + integrity sha512-6xBTNybmPY2YrvrhhlS8Mxi0zn0ypusLon63p9XXxDtIf7U7c6KcViz94K7Skosucr3378A6IY2kJSjJyuwylQ== + dependencies: + chalk "^3.0.0" + fancy-log "^1.3.2" + imagemin "^7.0.0" + plugin-error "^1.0.1" + plur "^3.0.1" + pretty-bytes "^5.3.0" + through2-concurrent "^2.0.0" + optionalDependencies: + imagemin-gifsicle "^7.0.0" + imagemin-mozjpeg "^8.0.0" + imagemin-optipng "^7.0.0" + imagemin-svgo "^7.0.0" + +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" + integrity sha512-U/1Sml7UbyOu2kH6Fbpo+ka2xyp4DRH6+oDtHgC8oKsnlQRuiBQYQ/LS4k6HxBv1HJlucaNV/SdwZXtLBuvSqg== + dependencies: + array-unique "^0.3.2" + fancy-log "^1.2.0" + findup-sync "^4.0.0" + gulplog "^1.0.0" + has-gulplog "^0.1.0" + micromatch "^4.0.2" + resolve "^1.15.1" + +gulp-match@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/gulp-match/-/gulp-match-1.1.0.tgz#552b7080fc006ee752c90563f9fec9d61aafdf4f" + integrity sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ== + dependencies: + minimatch "^3.0.3" + +gulp-phonegap-build@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/gulp-phonegap-build/-/gulp-phonegap-build-0.1.5.tgz#36c145e63cd204702be0f3b99be19e096712bcaf" + integrity sha1-NsFF5jzSBHAr4PO5m+GeCWcSvK8= + dependencies: + archiver "~0.11.0" + gulp "~3.8.7" + gulp-util "~3.0.0" + lodash "~2.4.1" + needle "" + read "~1.0.4" + through2 "~0.6.1" + vinyl-buffer "0.0.0" + vinyl-source-stream "^0.1.1" + +gulp-plumber@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/gulp-plumber/-/gulp-plumber-1.2.1.tgz#d38700755a300b9d372318e4ffb5ff7ced0b2c84" + integrity sha512-mctAi9msEAG7XzW5ytDVZ9PxWMzzi1pS2rBH7lA095DhMa6KEXjm+St0GOCc567pJKJ/oCvosVAZEpAey0q2eQ== + dependencies: + chalk "^1.1.3" + fancy-log "^1.3.2" + plugin-error "^0.1.2" + through2 "^2.0.3" + +gulp-pngquant@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/gulp-pngquant/-/gulp-pngquant-1.0.13.tgz#7160b4b51080898c9bed896ae0432546c46a8130" + integrity sha512-oSo5Rw2Rb10eyGhc8XKbghq6yteMmxvsSAKGOZU0ssbylMHk3WoTWcEpNg0YWMyRjrY913y+B+PA4wHM1AL2wA== + dependencies: + chalk "^3.0.0" + fancy-log "^1.3.3" + plugin-error "^1.0.1" + pngquant-bin "^5.0.2" + through2 "^3.0.1" + +gulp-postcss@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/gulp-postcss/-/gulp-postcss-8.0.0.tgz#8d3772cd4d27bca55ec8cb4c8e576e3bde4dc550" + integrity sha512-Wtl6vH7a+8IS/fU5W9IbOpcaLqKxd5L1DUOzaPmlnCbX1CrG0aWdwVnC3Spn8th0m8D59YbysV5zPUe1n/GJYg== + dependencies: + fancy-log "^1.3.2" + plugin-error "^1.0.1" + postcss "^7.0.2" + postcss-load-config "^2.0.0" + vinyl-sourcemaps-apply "^0.2.1" + +gulp-rename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-2.0.0.tgz#9bbc3962b0c0f52fc67cd5eaff6c223ec5b9cf6c" + integrity sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ== + +gulp-sass-lint@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/gulp-sass-lint/-/gulp-sass-lint-1.4.0.tgz#6f7096c5abcbc0ce99ddf060c9e1a99067a47ebe" + integrity sha512-XerYvHx7rznInkedMw5Ayif+p8EhysOVHUBvlgUa0FSl88H2cjNjaRZ3NGn5Efmp+2HxpXp4NHqMIbOSdwef3A== + dependencies: + plugin-error "^0.1.2" + sass-lint "^1.12.0" + through2 "^2.0.2" + +gulp-sass@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/gulp-sass/-/gulp-sass-4.1.0.tgz#486d7443c32d42bf31a6b1573ebbdaa361de7427" + integrity sha512-xIiwp9nkBLcJDpmYHbEHdoWZv+j+WtYaKD6Zil/67F3nrAaZtWYN5mDwerdo7EvcdBenSAj7Xb2hx2DqURLGdA== + dependencies: + chalk "^2.3.0" + lodash "^4.17.11" + node-sass "^4.8.3" + plugin-error "^1.0.1" + replace-ext "^1.0.0" + strip-ansi "^4.0.0" + through2 "^2.0.0" + vinyl-sourcemaps-apply "^0.2.0" + +"gulp-sftp@git+https://git@github.com/webksde/gulp-sftp": + version "0.1.6" + resolved "git+https://git@github.com/webksde/gulp-sftp#c8dfb20e290477eeed66a867406576d0c3d4fc6b" + dependencies: + async "~0.9.0" + gulp-util "~3.0.0" + object-assign "~0.3.1" + parents "~1.0.0" + ssh2 "~0.6.1" + through2 "~0.4.2" + +gulp-terser@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gulp-terser/-/gulp-terser-1.2.0.tgz#41df2a1d0257d011ba8b05efb2568432ecd0495b" + integrity sha512-lf+jE2DALg2w32p0HRiYMlFYRYelKZPNunHp2pZccCYrrdCLOs0ItbZcN63yr2pbz116IyhUG9mD/QbtRO1FKA== + dependencies: + plugin-error "^1.0.1" + terser "^4.0.0" + through2 "^3.0.1" + vinyl-sourcemaps-apply "^0.2.1" + +gulp-util@^2.2.19: + version "2.2.20" + resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-2.2.20.tgz#d7146e5728910bd8f047a6b0b1e549bc22dbd64c" + integrity sha1-1xRuVyiRC9jwR6awseVJvCLb1kw= + dependencies: + chalk "^0.5.0" + dateformat "^1.0.7-1.2.3" + lodash._reinterpolate "^2.4.1" + lodash.template "^2.4.1" + minimist "^0.2.0" + multipipe "^0.1.0" + through2 "^0.5.0" + vinyl "^0.2.1" + +gulp-util@^3.0.0, gulp-util@~3.0.0: + version "3.0.8" + resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" + integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= + dependencies: + array-differ "^1.0.0" + array-uniq "^1.0.2" + beeper "^1.0.0" + chalk "^1.0.0" + dateformat "^2.0.0" + fancy-log "^1.1.0" + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash._reescape "^3.0.0" + lodash._reevaluate "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.template "^3.0.0" + minimist "^1.1.0" + multipipe "^0.1.2" + object-assign "^3.0.0" + replace-ext "0.0.1" + through2 "^2.0.0" + vinyl "^0.5.0" + +gulp-webserver@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/gulp-webserver/-/gulp-webserver-0.9.1.tgz#e09992165d97c5865616d642a1601529b0367064" + integrity sha1-4JmSFl2XxYZWFtZCoWAVKbA2cGQ= + dependencies: + connect "^3.0.1" + connect-livereload "^0.4.0" + gulp-util "^2.2.19" + isarray "0.0.1" + node.extend "^1.0.10" + open "^0.0.5" + proxy-middleware "^0.5.0" + serve-index "^1.1.4" + serve-static "^1.3.0" + through2 "^0.5.1" + tiny-lr "0.1.4" + watch "^0.11.0" + +gulp-yaml@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/gulp-yaml/-/gulp-yaml-2.0.4.tgz#86569e2becc9f5dfc95dc92db5a71a237f4b6ab4" + integrity sha512-S/9Ib8PO+jGkCvWDwBUkmFkeW7QM0pp4PO8NNrMEfWo5Sk30P+KqpyXc4055L/vOX326T/b9MhM4nw5EenyX9g== + dependencies: + bufferstreams "^2.0.1" + js-yaml "^3.13.1" + object-assign "^4.1.1" + plugin-error "^1.0.1" + replace-ext "^1.0.0" + through2 "^3.0.0" + +gulp@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/gulp/-/gulp-4.0.2.tgz#543651070fd0f6ab0a0650c6a3e6ff5a7cb09caa" + integrity sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA== + dependencies: + glob-watcher "^5.0.3" + gulp-cli "^2.2.0" + undertaker "^1.2.1" + vinyl-fs "^3.0.0" + +gulp@~3.8.7: + version "3.8.11" + resolved "https://registry.yarnpkg.com/gulp/-/gulp-3.8.11.tgz#d557e0a7283eb4136491969b0497767972f1d28a" + integrity sha1-1Vfgpyg+tBNkkZabBJd2eXLx0oo= + dependencies: + archy "^1.0.0" + chalk "^0.5.0" + deprecated "^0.0.1" + gulp-util "^3.0.0" + interpret "^0.3.2" + liftoff "^2.0.1" + minimist "^1.1.0" + orchestrator "^0.3.0" + pretty-hrtime "^0.2.0" + semver "^4.1.0" + tildify "^1.0.0" + v8flags "^2.0.2" + vinyl-fs "^0.3.0" + +gulplog@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" + integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= + dependencies: + glogg "^1.0.0" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + dependencies: + ajv "^6.5.5" + har-schema "^2.0.0" + +has-ansi@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e" + integrity sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4= + dependencies: + ansi-regex "^0.2.0" + +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-gulplog@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" + integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= + dependencies: + sparkles "^1.0.0" + +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: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + +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-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +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.1, 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" + +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" + integrity sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ== + +howler@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/howler/-/howler-2.1.2.tgz#8433a09d8fe84132a3e726e05cb2bd352ef8bd49" + integrity sha512-oKrTFaVXsDRoB/jik7cEpWKTj7VieoiuzMYJ7E/EU5ayvmpRhumCv3YQ3823zi9VTJkSWAhbryHnlZAionGAJg== + +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-encoding-sniffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" + integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== + dependencies: + whatwg-encoding "^1.0.1" + +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.20, 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-cache-semantics@^4.0.0: + version "4.0.3" + 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.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-parser-js@>=0.4.0 <0.4.11": + version "0.4.10" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" + integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= + +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 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.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= + +human-signals@^1.1.1: + version "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.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== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.4.tgz#e95f2e41db0735fc21652f7827a5ee32e63c83a8" + integrity sha1-6V8uQdsHNfwhZS94J6XuMuY8g6g= + +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-walk@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.2.tgz#99d83a246c196ea5c93ef9315ad7b0819c35069b" + integrity sha512-EXyErtpHbn75ZTsOADsfx6J/FPo6/5cjev46PXrcTpd8z3BoRkXgYu9/JVqrI7tusjmwCZutGeRJeU0Wo1e4Cw== + dependencies: + minimatch "^3.0.4" + +ignore@^3.1.2: + version "3.3.10" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== + +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== + +ignore@^5.1.1: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + +imagemin-gifsicle@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/imagemin-gifsicle/-/imagemin-gifsicle-7.0.0.tgz#1a7ab136a144c4678657ba3b6c412f80805d26b0" + integrity sha512-LaP38xhxAwS3W8PFh4y5iQ6feoTSF+dTAXFRUEYQWYst6Xd+9L/iPk34QGgK/VO/objmIlmq9TStGfVY2IcHIA== + dependencies: + execa "^1.0.0" + gifsicle "^5.0.0" + is-gif "^3.0.0" + +imagemin-jpegtran@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/imagemin-jpegtran/-/imagemin-jpegtran-7.0.0.tgz#7728f84876362d489b9a1656e0cc8e2009406e6f" + integrity sha512-MJoyTCW8YjMJf56NorFE41SR/WkaGA3IYk4JgvMlRwguJEEd3PnP9UxA8Y2UWjquz8d+On3Ds/03ZfiiLS8xTQ== + dependencies: + exec-buffer "^3.0.0" + is-jpg "^2.0.0" + jpegtran-bin "^5.0.0" + +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-optipng@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/imagemin-optipng/-/imagemin-optipng-7.1.0.tgz#2225c82c35e5c29b7fa98d4f9ecee1161a68e888" + integrity sha512-JNORTZ6j6untH7e5gF4aWdhDCxe3ODsSLKs/f7Grewy3ebZpl1ZsU+VUTPY4rzeHgaFA8GSWOoA8V2M3OixWZQ== + dependencies: + exec-buffer "^3.0.0" + is-png "^2.0.0" + optipng-bin "^6.0.0" + +imagemin-pngquant@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/imagemin-pngquant/-/imagemin-pngquant-9.0.0.tgz#f22ba4276cde1799fb15dd475e33984f8607e871" + integrity sha512-9cqnTEaJwAHWUi+8EMTB3NUouWToCWxtL+QnoYr8bfVwuKilHvRVWKsa9lt+0c3aWaGxCAkHs++j8qINvSqomA== + dependencies: + execa "^4.0.0" + is-png "^2.0.0" + is-stream "^2.0.0" + ow "^0.17.0" + pngquant-bin "^6.0.0" + +imagemin-svgo@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/imagemin-svgo/-/imagemin-svgo-7.0.0.tgz#a22d0a5917a0d0f37e436932c30f5e000fa91b1c" + integrity sha512-+iGJFaPIMx8TjFW6zN+EkOhlqcemdL7F3N3Y0wODvV2kCUBuUtZK7DRZc1+Zfu4U2W/lTMUyx2G8YMOrZntIWg== + dependencies: + is-svg "^3.0.0" + svgo "^1.0.5" + +imagemin@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/imagemin/-/imagemin-7.0.1.tgz#f6441ca647197632e23db7d971fffbd530c87dbf" + integrity sha512-33AmZ+xjZhg2JMCe+vDf6a9mzWukE7l+wAtesjE7KyteqqKjzxv7aVQeWnul1Ve26mWvEQqyPwl0OctNBfSR9w== + dependencies: + file-type "^12.0.0" + globby "^10.0.0" + graceful-fs "^4.2.2" + junk "^3.1.0" + make-dir "^3.0.0" + p-pipe "^3.0.0" + replace-ext "^1.0.0" + +immutable@^3: + version "3.8.2" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" + integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM= + +import-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" + integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= + dependencies: + import-from "^2.1.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.1.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" + integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-from@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" + integrity sha1-M1238qev/VOqpHHUuAId7ja387E= + dependencies: + resolve-from "^3.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= + +in-publish@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" + integrity sha1-4g/146KvwmkDILbcVSaCqcf631E= + +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@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b" + integrity sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js= + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, 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, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +inquirer@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" + integrity sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34= + dependencies: + ansi-escapes "^1.1.0" + ansi-regex "^2.0.0" + chalk "^1.0.0" + cli-cursor "^1.0.1" + cli-width "^2.0.0" + figures "^1.3.5" + lodash "^4.3.0" + readline2 "^1.0.1" + run-async "^0.1.0" + rx-lite "^3.1.2" + string-width "^1.0.1" + strip-ansi "^3.0.0" + through "^2.3.6" + +inquirer@^6.2.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.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== + +interpret@^0.3.2: + version "0.3.10" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-0.3.10.tgz#088c25de731c6c5b112a90f0071cfaf459e5a7bb" + integrity sha1-CIwl3nMcbFsRKpDwBxz69Fnlp7s= + +interpret@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== + +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: + 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@^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== + +irregular-plurals@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-2.0.0.tgz#39d40f05b00f656d0b7fa471230dd3b714af2872" + integrity sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw== + +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-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + +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-buffer@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" + integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== + +is-callable@^1.1.3, is-callable@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== + +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.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + +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.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= + dependencies: + number-is-nan "^1.0.0" + +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-gif@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-gif/-/is-gif-3.0.0.tgz#c4be60b26a301d695bb833b20d9b5d66c6cf83b1" + integrity sha512-IqJ/jlbw5WJSNfwQ/lHEDXF8rxhRgF6ythk2oiEvhpG29F704eX9NO6TvPfMiq9DrbwgcEDnETYNcZDPewQoVw== + dependencies: + file-type "^10.4.0" + +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-my-ip-valid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" + integrity sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ== + +is-my-json-valid@^2.10.0: + version "2.20.0" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz#1345a6fca3e8daefc10d0fa77067f54cedafd59a" + integrity sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA== + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + is-my-ip-valid "^1.0.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + +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-negated-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" + integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= + +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-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== + +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@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + +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.1, 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-property@^1.0.0, is-property@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== + dependencies: + is-unc-path "^1.0.0" + +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.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + dependencies: + has-symbols "^1.0.0" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== + dependencies: + unc-path-regex "^0.1.2" + +is-utf8@^0.2.0, is-utf8@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-valid-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" + integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= + +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= + +is@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/is/-/is-3.3.0.tgz#61cff6dd3c4193db94a3d62582072b44e5645d79" + integrity sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +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= + +isbinaryfile@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80" + integrity sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw== + dependencies: + buffer-alloc "^1.2.0" + +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= + +isstream@0.1.x, isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +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.6" + resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.3.6.tgz#c40382aac9506e7d1f2d856eb02f6c7b2a98b37c" + integrity sha512-MUj2XlMB8kpe+8DJUGH/3UJm4XpI8XEgZQ+CiHDeyrGoKPdW/8FJv6ku+3UiYm5Fz3CWaL+iXmD8Q4Ap6aC1Jw== + +jpegtran-bin@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/jpegtran-bin/-/jpegtran-bin-5.0.1.tgz#3cecaa471726bbcb66adabeeb544c409b17c73e5" + integrity sha512-xQoXWkIEt4ckmvcHd9xG3RcCIn00sf2TshDyFMOAE+46EspEqwqoPWotVI3e55FGWafMa9cEqaoIyrCeWDnFPw== + dependencies: + bin-build "^3.0.0" + bin-wrapper "^4.0.0" + logalot "^2.0.0" + +js-base64@^2.1.8, js-base64@^2.1.9: + version "2.5.1" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" + integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw== + +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== + dependencies: + config-chain "^1.1.12" + editorconfig "^0.15.3" + glob "^7.1.3" + mkdirp "~0.5.1" + nopt "~4.0.1" + +js-levenshtein@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" + integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== + +"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.0, js-yaml@^3.13.1, js-yaml@^3.4.6, js-yaml@^3.5.1, js-yaml@^3.5.4: + 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" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsdom@12.2.0: + version "12.2.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-12.2.0.tgz#7cf3f5b5eafd47f8f09ca52315d367ff6e95de23" + integrity sha512-QPOggIJ8fquWPLaYYMoh+zqUmdphDtu1ju0QGTitZT1Yd8I5qenPpXM1etzUegu3MjVp8XPzgZxdn8Yj7e40ig== + dependencies: + abab "^2.0.0" + acorn "^6.0.2" + acorn-globals "^4.3.0" + array-equal "^1.0.0" + cssom "^0.3.4" + cssstyle "^1.1.1" + data-urls "^1.0.1" + domexception "^1.0.1" + escodegen "^1.11.0" + html-encoding-sniffer "^1.0.2" + nwsapi "^2.0.9" + parse5 "5.1.0" + pn "^1.1.0" + request "^2.88.0" + request-promise-native "^1.0.5" + saxes "^3.1.3" + symbol-tree "^3.2.2" + tough-cookie "^2.4.3" + w3c-hr-time "^1.0.1" + webidl-conversions "^4.0.2" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.2.0" + whatwg-url "^7.0.0" + ws "^6.1.0" + xml-name-validator "^3.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-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +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= + +json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +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" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + +jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk= + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +junk@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" + integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== + +just-debounce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" + integrity sha1-h/zPrv/AtozRnVX2cilD+SnqNeo= + +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" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +kind-of@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" + integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= + +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, kind-of@^5.0.2: + 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.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +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== + +known-css-properties@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.3.0.tgz#a3d135bbfc60ee8c6eacf2f7e7e6f2d4755e49a4" + integrity sha512-QMQcnKAiQccfQTqtBh/qwquGZ2XK/DXND1jrcN9M8gMMy99Gwla7GQjndVUsEqIaRyP6bsFRuhwRj5poafBGJQ== + +last-run@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b" + integrity sha1-RblpQsF7HHnHchmCWbqUO+v4yls= + dependencies: + default-resolution "^2.0.0" + es6-weak-map "^2.0.1" + +lazystream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" + integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= + dependencies: + readable-stream "^2.0.5" + +lazystream@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-0.1.0.tgz#1b25d63c772a4c20f0a5ed0a9d77f484b6e16920" + integrity sha1-GyXWPHcqTCDwpe0KnXf0hLbhaSA= + dependencies: + readable-stream "~1.0.2" + +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" + +lead@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" + integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI= + dependencies: + flush-write-stream "^1.0.2" + +levn@^0.3.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" + +liftoff@^2.0.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.5.0.tgz#2009291bb31cea861bbf10a7c15a28caf75c31ec" + integrity sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew= + dependencies: + extend "^3.0.0" + findup-sync "^2.0.0" + fined "^1.0.1" + flagged-respawn "^1.0.0" + is-plain-object "^2.0.4" + object.map "^1.0.0" + rechoir "^0.6.2" + resolve "^1.1.7" + +liftoff@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3" + integrity sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog== + dependencies: + extend "^3.0.0" + findup-sync "^3.0.0" + fined "^1.0.1" + flagged-respawn "^1.0.0" + is-plain-object "^2.0.4" + object.map "^1.0.0" + rechoir "^0.6.2" + resolve "^1.1.7" + +limiter@^1.0.5: + version "1.1.4" + resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.4.tgz#87c9c3972d389fdb0ba67a45aadbc5d2f8413bc1" + integrity sha512-XCpr5bElgDI65vVgstP8TWjv6/QKWm9GU5UG0Pr5sLQ3QLo8NVKsioe+Jed5/3vFOe3IQuqE7DKwTvKQkjTHvg== + +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" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.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, 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== + 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.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@^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 "13.3.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._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= + +lodash._basetostring@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" + integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= + +lodash._basevalues@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" + integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= + +lodash._escapehtmlchar@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz#df67c3bb6b7e8e1e831ab48bfa0795b92afe899d" + integrity sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0= + dependencies: + lodash._htmlescapes "~2.4.1" + +lodash._escapestringchar@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz#ecfe22618a2ade50bfeea43937e51df66f0edb72" + integrity sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I= + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= + +lodash._htmlescapes@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz#32d14bf0844b6de6f8b62a051b4f67c228b624cb" + integrity sha1-MtFL8IRLbeb4tioFG09nwii2JMs= + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= + +lodash._isnative@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._isnative/-/lodash._isnative-2.4.1.tgz#3ea6404b784a7be836c7b57580e1cdf79b14832c" + integrity sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw= + +lodash._objecttypes@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz#7c0b7f69d98a1f76529f890b0cdb1b4dfec11c11" + integrity sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE= + +lodash._reescape@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" + integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= + +lodash._reevaluate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" + integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= + +lodash._reinterpolate@^2.4.1, lodash._reinterpolate@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz#4f1227aa5a8711fc632f5b07a1f4607aab8b3222" + integrity sha1-TxInqlqHEfxjL1sHofRgequLMiI= + +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._reunescapedhtml@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz#747c4fc40103eb3bb8a0976e571f7a2659e93ba7" + integrity sha1-dHxPxAED6zu4oJduVx96JlnpO6c= + dependencies: + lodash._htmlescapes "~2.4.1" + lodash.keys "~2.4.1" + +lodash._root@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= + +lodash._shimkeys@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz#6e9cc9666ff081f0b5a6c978b83e242e6949d203" + integrity sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM= + dependencies: + lodash._objecttypes "~2.4.1" + +lodash.capitalize@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz#f826c9b4e2a8511d84e3aca29db05e1a4f3b72a9" + integrity sha1-+CbJtOKoUR2E46yinbBeGk87cqk= + +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.clonedeep@^4.3.2: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + +lodash.defaults@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= + +lodash.defaults@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-2.4.1.tgz#a7e8885f05e68851144b6e12a8f3678026bc4c54" + integrity sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ= + dependencies: + lodash._objecttypes "~2.4.1" + lodash.keys "~2.4.1" + +lodash.escape@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" + integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= + dependencies: + lodash._root "^3.0.0" + +lodash.escape@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-2.4.1.tgz#2ce12c5e084db0a57dda5e5d1eeeb9f5d175a3b4" + integrity sha1-LOEsXghNsKV92l5dHu659dF1o7Q= + dependencies: + lodash._escapehtmlchar "~2.4.1" + lodash._reunescapedhtml "~2.4.1" + lodash.keys "~2.4.1" + +lodash.get@^4.0.0: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= + +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.isobject@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz#5a2e47fe69953f1ee631a7eba1fe64d2d06558f5" + integrity sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU= + dependencies: + lodash._objecttypes "~2.4.1" + +lodash.kebabcase@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" + integrity sha1-hImxyw0p/4gZXM7KRI/21swpXDY= + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash.keys@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-2.4.1.tgz#48dea46df8ff7632b10d706b8acb26591e2b3727" + integrity sha1-SN6kbfj/djKxDXBrissmWR4rNyc= + dependencies: + lodash._isnative "~2.4.1" + lodash._shimkeys "~2.4.1" + lodash.isobject "~2.4.1" + +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.restparam@^3.0.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= + +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.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= + +lodash.template@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-2.4.1.tgz#9e611007edf629129a974ab3c48b817b3e1cf20d" + integrity sha1-nmEQB+32KRKal0qzxIuBez4c8g0= + dependencies: + lodash._escapestringchar "~2.4.1" + lodash._reinterpolate "~2.4.1" + lodash.defaults "~2.4.1" + lodash.escape "~2.4.1" + lodash.keys "~2.4.1" + lodash.templatesettings "~2.4.1" + lodash.values "~2.4.1" + +lodash.template@^3.0.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" + integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= + dependencies: + lodash._basecopy "^3.0.0" + lodash._basetostring "^3.0.0" + lodash._basevalues "^3.0.0" + lodash._isiterateecall "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + lodash.keys "^3.0.0" + lodash.restparam "^3.0.0" + lodash.templatesettings "^3.0.0" + +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@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" + integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.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.templatesettings@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz#ea76c75d11eb86d4dbe89a83893bb861929ac699" + integrity sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk= + dependencies: + lodash._reinterpolate "~2.4.1" + lodash.escape "~2.4.1" + +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.values@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-2.4.1.tgz#abf514436b3cb705001627978cbcf30b1280eea4" + integrity sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ= + dependencies: + lodash.keys "~2.4.1" + +lodash@^3.0.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" + integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y= + +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== + +lodash@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" + integrity sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE= + +lodash@~2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e" + integrity sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4= + +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" + +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, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +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@2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" + integrity sha1-bUUk6LlV+V1PW1iFHOId1y+06VI= + +lru-cache@^4.0.1, lru-cache@^4.1.5: + 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" + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-iterator@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" + integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw== + dependencies: + kind-of "^6.0.2" + +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.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@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/markdown-loader/-/markdown-loader-5.1.0.tgz#4efd5006b1514ca966141c661a47e542a9836e6e" + integrity sha512-xtQNozLEL+55ZSPTNwro8epZqf1h7HjAZd/69zNe8lbckDiGVHeLQm849bXzocln2pwRK2A/GrW/7MAmwjcFog== + dependencies: + loader-utils "^1.2.3" + marked "^0.7.0" + +marked@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e" + integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg== + +matchdep@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e" + integrity sha1-xvNINKDY28OzfCfui7yyfHd1WC4= + dependencies: + findup-sync "^2.0.0" + micromatch "^3.0.4" + resolve "^1.4.0" + stack-trace "0.0.10" + +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@~1.1.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" + integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== + +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" + +meow@^3.3.0, meow@^3.7.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-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.2.3: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +merge@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" + integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== + +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" + +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + +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.40.0: + version "1.40.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" + integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== + +mime-db@^1.28.0: + version "1.41.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.41.0.tgz#9110408e1f6aa1b34aef51f2c9df3caddf46b6a0" + integrity sha512-B5gxBI+2K431XW8C2rcc/lhppbuji67nf9v39eH8pkWoZDxnAL0PxdpH32KYRScniF8qDHBDlI+ipgg5WrCUYw== + +mime-db@~1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.12.0.tgz#3d0c63180f458eb10d325aaa37d7c58ae312e9d7" + integrity sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc= + +mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: + version "2.1.24" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" + integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== + dependencies: + mime-db "1.40.0" + +mime-types@~2.0.9: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.0.14.tgz#310e159db23e077f8bb22b748dabfa4957140aa6" + integrity sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY= + dependencies: + mime-db "~1.12.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, mimic-response@^1.0.1: + 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" + +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + +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@0.3: + version "0.3.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" + integrity sha1-J12O2qxPG7MyZHIInnlJyDlGmd0= + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +"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== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^2.0.1: + version "2.0.10" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" + integrity sha1-jQh8OcazjAAbl/ynzm0OHoCvusc= + dependencies: + brace-expansion "^1.0.0" + +minimatch@~0.2.11: + version "0.2.14" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" + integrity sha1-x054BXT2PG+aCQ6Q775u9TpqdWo= + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +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.x: + version "1.1.3" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" + integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag= + +minimist@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de" + integrity sha1-md9lelJXTCHJBXSX33QnkLK0wN4= + +minimist@^0.2.0: + version "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" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= + +minipass@^2.2.1, minipass@^2.6.0, minipass@^2.6.4: + version "2.7.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.7.0.tgz#c01093a82287c8331f08f1075499fef124888796" + integrity sha512-+CbZuJ4uEiuTL9s5Z/ULkuRg1O9AvVqVvceaBrhbYHIy1R3dPO7FMmG0nZLD0//ZzZq0MUOjwdBQvk+w1JHUqQ== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.2.tgz#6f0ccc82fa53e1bf2ff145f220d2da9fa6e3a166" + integrity sha512-hR3At21uSrsjjDTWrbu0IMLTpnkpv8IIMFDFaoz43Tmu4LkmAXfH44vNNzpTnf+OAQQCHrb91y/wc2J4x5XgSQ== + dependencies: + minipass "^2.2.1" + +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.1.3" + resolved "https://registry.yarnpkg.com/mitt/-/mitt-1.1.3.tgz#528c506238a05dce11cd914a741ea2cc332da9b8" + integrity sha512-mUDCnVNsAi+eD6qA0HkRkwYczbLHJ49z17BGe2PYRhZL4wpZUFZGJHU7/5tmvohoma+Hdn0Vh/oJTiPEmgSruA== + +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, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.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.3: + 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== + +multipipe@^0.1.0, multipipe@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" + integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= + dependencies: + duplexer2 "0.0.2" + +mute-stdout@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331" + integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg== + +mute-stream@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" + integrity sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA= + +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.4: + 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, nan@^2.13.2: + 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" + +natives@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.6.tgz#a603b4a498ab77173612b9ea1acdec4d980f00bb" + integrity sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA== + +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= + +needle@, needle@^2.2.1: + version "2.4.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" + integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + +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== + +next-tick@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + +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-gyp@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" + integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA== + dependencies: + fstream "^1.0.0" + glob "^7.0.3" + graceful-fs "^4.1.2" + mkdirp "^0.5.0" + nopt "2 || 3" + npmlog "0 || 1 || 2 || 3 || 4" + osenv "0" + request "^2.87.0" + rimraf "2" + semver "~5.3.0" + tar "^2.0.0" + which "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-pre-gyp@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" + integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +node-releases@^1.1.29: + version "1.1.32" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.32.tgz#485b35c1bf9b4d8baa105d782f8ca731e518276e" + integrity sha512-VhVknkitq8dqtWoluagsGPn3dxTvN9fwgR59fV3D7sLBHe0JfDramsMI8n8mY//ccq/Kkrf8ZRHRpsyVZ3qw1A== + dependencies: + semver "^5.3.0" + +node-sass@^4.8.3: + version "4.12.0" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.12.0.tgz#0914f531932380114a30cc5fa4fa63233a25f017" + integrity sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ== + dependencies: + async-foreach "^0.1.3" + chalk "^1.1.1" + cross-spawn "^3.0.0" + gaze "^1.0.0" + get-stdin "^4.0.1" + glob "^7.0.3" + in-publish "^2.0.0" + lodash "^4.17.11" + meow "^3.7.0" + mkdirp "^0.5.1" + nan "^2.13.2" + node-gyp "^3.8.0" + npmlog "^4.0.0" + request "^2.88.0" + sass-graph "^2.2.4" + stdout-stream "^1.4.0" + "true-case-path" "^1.0.2" + +node-sri@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/node-sri/-/node-sri-1.1.1.tgz#041096d2b11f232b65dedc4c3ae1cb62babb54b0" + integrity sha1-BBCW0rEfIytl3txMOuHLYrq7VLA= + +node.extend@^1.0.10: + version "1.1.8" + resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.8.tgz#0aab3e63789f4e6d68b42bc00073ad1881243cf0" + integrity sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA== + dependencies: + has "^1.0.3" + is "^3.2.1" + +"nopt@2 || 3": + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= + dependencies: + abbrev "1" + +nopt@^4.0.1, nopt@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= + dependencies: + abbrev "1" + osenv "^0.1.4" + +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== + +normalize-url@^4.1.0: + version "4.4.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.4.1.tgz#81e9c153b0ad5743755696f2aa20488d48e962b6" + integrity sha512-rjH3yRt0Ssx19mUwS0hrDUOdG9VI+oRLpLHJ7tXRdjcuQ7v7wo6qPvOZppHRrqfslTKr0L2yBhjj4UXd7c3cQg== + +now-and-later@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.1.tgz#8e579c8685764a7cc02cb680380e94f43ccb1f7c" + integrity sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ== + dependencies: + once "^1.3.2" + +npm-bundled@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" + integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== + +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-packlist@^1.1.6: + version "1.4.4" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" + integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +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" + +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~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= + +nwsapi@^2.0.9: + version "2.1.4" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.1.4.tgz#e006a878db23636f8e8a67d33ca0e4edf61a842f" + integrity sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw== + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" + integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= + +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-assign@~0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-0.3.1.tgz#060e2a2a27d7c0d77ec77b78f11aa47fd88008d2" + integrity sha1-Bg4qKifXwNd+x3t48Rqkf9iACNI= + +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.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== + +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-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= + +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.0.4, 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.defaults@^1.0.0, object.defaults@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" + integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8= + dependencies: + array-each "^1.0.1" + array-slice "^1.0.0" + for-own "^1.0.0" + isobject "^3.0.0" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + +object.map@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" + integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc= + dependencies: + for-own "^1.0.0" + make-iterator "^1.0.0" + +object.pick@^1.2.0, 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.reduce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.reduce/-/object.reduce-1.0.1.tgz#6fe348f2ac7fa0f95ca621226599096825bb03ad" + integrity sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60= + dependencies: + for-own "^1.0.0" + make-iterator "^1.0.0" + +object.values@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" + integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.12.0" + 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.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.1.0.tgz#0c539f09291e8ffadde0c8a25850fb2cedc7022d" + integrity sha1-DFOfCSkej/rd4MiiWFD7LO3HAi0= + dependencies: + ee-first "1.0.5" + +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.3.2, 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" + +once@~1.3.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" + integrity sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA= + dependencies: + wrappy "1" + +onetime@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= + +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" + +open@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc" + integrity sha1-QsPhjslUZra/DcQvOilFw/DK2Pw= + +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@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" + +optimist@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +optionator@^0.8.1, optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +optipng-bin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/optipng-bin/-/optipng-bin-6.0.0.tgz#376120fa79d5e71eee2f524176efdd3a5eabd316" + integrity sha512-95bB4y8IaTsa/8x6QH4bLUuyvyOoGBCLDA7wOgDL8UFqJpSUh1Hob8JRJhit+wC1ZLN3tQ7mFt7KuBj0x8F2Wg== + dependencies: + bin-build "^3.0.0" + bin-wrapper "^4.0.0" + logalot "^2.0.0" + +orchestrator@^0.3.0: + version "0.3.8" + resolved "https://registry.yarnpkg.com/orchestrator/-/orchestrator-0.3.8.tgz#14e7e9e2764f7315fbac184e506c7aa6df94ad7e" + integrity sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4= + dependencies: + end-of-stream "~0.1.5" + sequencify "~0.0.7" + stream-consume "~0.1.0" + +ordered-read-streams@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz#fd565a9af8eb4473ba69b6ed8a34352cb552f126" + integrity sha1-/VZamvjrRHO6abbtijQ1LLVS8SY= + +ordered-read-streams@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" + integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4= + dependencies: + readable-stream "^2.0.1" + +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-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +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.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= + +osenv@0, osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +ow@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/ow/-/ow-0.17.0.tgz#4f938999fed6264c9048cd6254356e0f1e7f688c" + integrity sha512-i3keDzDQP5lWIe4oODyDFey1qVrq2hXKTuTH2VpqwpYtzPiKZt2ziRI4NBQmgW40AnV5Euz17OyWweCb+bNEQA== + dependencies: + type-fest "^0.11.0" + +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-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +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: + version "2.2.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + 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" + 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-pipe@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.1.0.tgz#48b57c922aa2e1af6a6404cb7c6bf0eb9cc8e60e" + integrity sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw== + +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.10" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" + integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== + +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" + +parents@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" + integrity sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E= + dependencies: + path-platform "~0.11.15" + +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-author@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-author/-/parse-author-2.0.0.tgz#d3460bf1ddd0dfaeed42da754242e65fb684a81f" + integrity sha1-00YL8d3Q367tQtp1QkLmX7aEqB8= + dependencies: + author-regex "^1.0.0" + +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-filepath@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" + integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE= + dependencies: + is-absolute "^1.0.0" + map-cache "^0.2.0" + path-root "^0.1.1" + +parse-headers@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.2.tgz#9545e8a4c1ae5eaea7d24992bca890281ed26e34" + integrity sha512-/LypJhzFmyBIDYP9aDVgeyEb5sQfbfY5mnDq4hVhlQ69js87wXfmEI5V3xI6vvXasqebp0oCytYFLxsBVfCzSg== + dependencies: + for-each "^0.3.3" + string.prototype.trim "^1.1.2" + +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= + +parse5@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" + integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== + +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.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-is-inside@^1.0.1, path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + +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.0.0, 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-platform@~0.11.15: + version "0.11.15" + resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" + integrity sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I= + +path-root-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0= + +path-root@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc= + dependencies: + path-root-regex "^0.1.0" + +path-starts-with@^2.0.0: + version "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-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" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= + dependencies: + pify "^2.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +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= + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +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.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== + +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" + +pkginfo@0.3.x: + version "0.3.1" + resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21" + integrity sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE= + +plist@^3.0.0, plist@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c" + integrity sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ== + dependencies: + base64-js "^1.2.3" + xmlbuilder "^9.0.7" + xmldom "0.1.x" + +plugin-error@1.0.1, 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" + +plugin-error@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" + integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4= + dependencies: + ansi-cyan "^0.1.1" + ansi-red "^0.1.1" + arr-diff "^1.0.1" + arr-union "^2.0.1" + extend-shallow "^1.1.2" + +plur@^3.0.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/plur/-/plur-3.1.1.tgz#60267967866a8d811504fe58f2faaba237546a5b" + integrity sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w== + dependencies: + irregular-plurals "^2.0.0" + +pluralize@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" + integrity sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU= + +pn@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" + integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== + +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.2: + 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" + +pngquant-bin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/pngquant-bin/-/pngquant-bin-6.0.0.tgz#aff0d7e61095feb96ced379ad8c7294ad3dd1712" + integrity sha512-oXWAS9MQ9iiDAJRdAZ9KO1mC5UwhzKkJsmetiu0iqIjJuW7JsuLhmc4JdRm7uJkIWRzIAou/Vq2VcjfJwz30Ow== + dependencies: + bin-build "^3.0.0" + bin-wrapper "^4.0.1" + execa "^4.0.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.1" + resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.1.tgz#b2a721a0d279c2f9103a36331c88981526428cc7" + integrity sha512-L2YKB3vF4PetdTIthQVeT+7YiSzMoNMLLYxPXXppOOP7NoazEAy45sh2LvJ8leCQjfBcfkYQs8TtCcQjeZTp8A== + dependencies: + postcss "^7.0.2" + postcss-selector-parser "^5.0.0" + +postcss-calc@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" + integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== + dependencies: + css-unit-converter "^1.1.1" + postcss "^7.0.5" + postcss-selector-parser "^5.0.0-rc.4" + postcss-value-parser "^3.3.1" + +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-critical-split@^2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/postcss-critical-split/-/postcss-critical-split-2.5.3.tgz#9339d3699f6363d0a3ad0952420dc9faa181363b" + integrity sha512-FDG+evU4RBGM9/LQ5nCktzFKjYH2O/SLollJwtrdGagXXbMvk620Bc9o8WpqHJnu573uxVkx9lhob1HZvSWhZg== + dependencies: + merge "^1.2.0" + postcss "^6.0.1" + +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.1" + resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.1.tgz#99d319669a13d6c06ef8e70d852f68cb1b399b61" + integrity sha512-I2Sz83ZSHybMNh02xQDK609lZ1/QOyYeuizCjzEhlMgeV/HcDJapQiH4yTqLjZss0X6/6VvKFXUeObaHpJoINw== + 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-load-config@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003" + integrity sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q== + dependencies: + cosmiconfig "^5.0.0" + import-cwd "^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.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" + integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= + dependencies: + dot-prop "^4.1.1" + 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-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.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" + integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== + +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.1, 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.5, postcss@^7.0.6: + version "7.0.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.18.tgz#4b9cda95ae6c069c67a4d933029eddd4838ac233" + integrity sha512-/7g1QXXgegpF+9GJj4iN7ChGF40sYuGYJ8WZu8DZWnmhQ/G36hfdk3q9LBJmoK+lZ+yzZ5KYpOoxq7LF1BxE8g== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +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= + +pretty-bytes@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" + integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== + +pretty-hrtime@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-0.2.2.tgz#d4fd88351e3a4741f8173af7d6a4b846f9895c00" + integrity sha1-1P2INR46R0H4Fzr31qS4RvmJXAA= + +pretty-hrtime@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= + +private@^0.1.6, 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@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= + +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-middleware@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/proxy-middleware/-/proxy-middleware-0.5.1.tgz#da24d5d58c1ddf13dad237c7eca503849eaea903" + integrity sha1-2iTV1Ywd3xPa0jfH7KUDhJ6uqQM= + +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= + +psl@^1.1.24, psl@^1.1.28: + version "1.4.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" + integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== + +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, pumpify@^1.3.5: + 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, punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0, punycode@^2.1.1: + 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@2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/qs/-/qs-2.2.4.tgz#2e9fbcd34b540e3421c924ecd01e90aa975319c8" + integrity sha1-Lp+800tUDjQhySTs0B6QqpdTGcg= + +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@~2.2.3: + version "2.2.5" + resolved "https://registry.yarnpkg.com/qs/-/qs-2.2.5.tgz#1088abaf9dcc0ae5ae45b709e6c6b5888b23923c" + integrity sha1-EIirr53MCuWuRbcJ5sa1iIsjkjw= + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +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.8.3" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.8.3.tgz#fd9fb7ffb068b79062b43383685611ee47777d4b" + integrity sha512-llcxWccnyaWlODe7A9hRjkvdCKamEKTh+wH8ITdTc3OhchaqUZteiSCX/2ablWHVrkVIe04dntnaZJ7BdyW0lQ== + 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.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@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-1.3.0.tgz#978230a156a5548f42eef14de22d0f4f610083d1" + integrity sha1-l4IwoValVI9C7vFN4i0PT2EAg9E= + dependencies: + bytes "1" + iconv-lite "0.4.4" + +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" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +rcedit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/rcedit/-/rcedit-2.0.0.tgz#dcc85d93aa91a41c1ebc5c6aa1dfc43ea28b7dad" + integrity sha512-XcFGyEBjhWSsud+R8elwQtGBbVkCf7tAiad+nXo5jc6l2rMf46NfGNwjnmBNneBIZDfq+Npf8lwP371JTONfrw== + +rcfinder@^0.1.6: + version "0.1.9" + resolved "https://registry.yarnpkg.com/rcfinder/-/rcfinder-0.1.9.tgz#f3e80f387ddf9ae80ae30a4100329642eae81115" + integrity sha1-8+gPOH3fmugK4wpBADKWQuroERU= + dependencies: + lodash.clonedeep "^4.3.2" + +rcloader@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/rcloader/-/rcloader-0.1.4.tgz#d0c902f0444983a2ee5a6907937c6a79ca704509" + integrity sha1-0MkC8ERJg6LuWmkHk3xqecpwRQk= + dependencies: + lodash "^3.0.1" + 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" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + dependencies: + find-up "^2.0.0" + read-pkg "^2.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" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +read@~1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= + dependencies: + mute-stream "~0.0.4" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, 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.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + 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@2 || 3": + version "3.4.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" + integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +"readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@~1.0.17, readable-stream@~1.0.2, readable-stream@~1.0.24, readable-stream@~1.0.26: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^1.0.27-1, readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^3.0.2, readable-stream@^3.1.1: + 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" + +readline2@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" + integrity sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + mute-stream "0.0.5" + +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" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + dependencies: + resolve "^1.1.6" + +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.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" + integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== + 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: + version "0.13.3" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" + integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== + +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.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" + integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ== + dependencies: + private "^0.1.6" + +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" + +regexp-tree@^0.1.13: + version "0.1.13" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.13.tgz#5b19ab9377edc68bc3679256840bb29afc158d7f" + integrity sha512-hwdV/GQY5F8ReLZWO+W1SRoN5YfpOKY6852+tBFcma72DKBIcHjPRIlIvQN35bCOljuAfP2G2iB0FC/w236mUw== + +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + +regexpu-core@^4.5.4: + version "4.6.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" + integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.1.0" + regjsgen "^0.5.0" + regjsparser "^0.6.0" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.1.0" + +regjsgen@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd" + integrity sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA== + +regjsparser@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" + integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== + 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-bom-buffer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" + integrity sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ== + dependencies: + is-buffer "^1.1.5" + is-utf8 "^0.2.1" + +remove-bom-stream@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" + integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM= + dependencies: + remove-bom-buffer "^3.0.0" + safe-buffer "^5.1.0" + through2 "^2.0.3" + +remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0: + 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@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" + integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= + +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= + +replace-homedir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-homedir/-/replace-homedir-1.0.0.tgz#e87f6d513b928dde808260c12be7fec6ff6e798c" + integrity sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw= + dependencies: + homedir-polyfill "^1.0.1" + is-absolute "^1.0.0" + remove-trailing-separator "^1.1.0" + +request-promise-core@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346" + integrity sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag== + dependencies: + lodash "^4.17.11" + +request-promise-native@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.7.tgz#a49868a624bdea5069f1251d0a836e0d89aa2c59" + integrity sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w== + dependencies: + request-promise-core "1.1.2" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +request@^2.87.0, request@^2.88.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.0" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +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== + +require-uncached@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +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= + +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@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= + +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-options@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" + integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE= + dependencies: + value-or-function "^3.0.0" + +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.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.3.2: + version "1.12.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" + integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== + dependencies: + path-parse "^1.0.6" + +resolve@^1.15.1, resolve@^1.4.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + 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, 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@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE= + dependencies: + exit-hook "^1.0.0" + onetime "^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" + +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== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +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, rimraf@^2.4.0, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, 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" + +rimraf@2.6.3, rimraf@~2.6.2: + 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@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.0.tgz#614176d4b3010b75e5c390eb0ee96f6dc0cebb9b" + integrity sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg== + 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@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" + integrity sha1-yK1KXhEGYeQCp9IbUw4AnyX444k= + dependencies: + once "^1.3.0" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= + dependencies: + is-promise "^2.1.0" + +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + +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-lite@^3.1.2: + version "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: + 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.4.0: + version "6.5.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" + integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== + 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.1.0, 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", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sanitize-filename@^1.6.0, sanitize-filename@^1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378" + integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== + dependencies: + truncate-utf8-bytes "^1.0.0" + +sass-graph@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" + integrity sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k= + dependencies: + glob "^7.0.0" + lodash "^4.0.0" + scss-tokenizer "^0.2.3" + yargs "^7.0.0" + +sass-lint@^1.12.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/sass-lint/-/sass-lint-1.13.1.tgz#5fd2b2792e9215272335eb0f0dc607f61e8acc8f" + integrity sha512-DSyah8/MyjzW2BWYmQWekYEKir44BpLqrCFsgs9iaWiVTcwZfwXHF586hh3D1n+/9ihUNMfd8iHAyb9KkGgs7Q== + dependencies: + commander "^2.8.1" + eslint "^2.7.0" + front-matter "2.1.2" + fs-extra "^3.0.1" + glob "^7.0.0" + globule "^1.0.0" + gonzales-pe-sl "^4.2.3" + js-yaml "^3.5.4" + known-css-properties "^0.3.0" + lodash.capitalize "^4.1.0" + lodash.kebabcase "^4.0.0" + merge "^1.2.0" + path-is-absolute "^1.0.0" + util "^0.10.3" + +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, 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== + +saxes@^3.1.3: + version "3.1.11" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.11.tgz#d59d1fd332ec92ad98a2e0b2ee644702384b1c5b" + integrity sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g== + dependencies: + xmlchars "^2.1.1" + +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" + +scss-tokenizer@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" + integrity sha1-jrBtualyMzOCTT9VMGQRSYR85dE= + dependencies: + js-base64 "^2.1.8" + source-map "^0.4.2" + +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-greatest-satisfied-range@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz#13e8c2658ab9691cb0cd71093240280d36f77a5b" + integrity sha1-E+jCZYq5aRywzXEJMkAoDTb3els= + dependencies: + sver-compat "^1.5.0" + +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.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, 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@^4.1.0: + version "4.3.6" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" + integrity sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto= + +semver@^6.0.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= + +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" + +sequencify@~0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c" + integrity sha1-kM/xnQLgcCf9dn9erT57ldHnOAw= + +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@^1.7.0: + version "1.9.1" + 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" + 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.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== + 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, 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== + +shelljs@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8" + integrity sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg= + +sigmund@^1.0.1, sigmund@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +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" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= + +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" + +socket.io-adapter@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz#2a805e8a14d6372124dd9159ad4502f8cb07f06b" + integrity sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs= + +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.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + 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.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + 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.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + integrity sha1-66T12pwNyZneaAMti092FzZSA2s= + dependencies: + amdefine ">=0.0.4" + +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, 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" + +sparkles@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" + integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== + +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" + +ssh2-streams@~0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ssh2-streams/-/ssh2-streams-0.2.1.tgz#9c9c9964be60e9644575af328677f64b1e5cbd79" + integrity sha512-3zCOsmunh1JWgPshfhKmBCL3lUtHPoh+a/cyQ49Ft0Q0aF7xgN06b76L+oKtFi0fgO57FLjFztb1GlJcEZ4a3Q== + dependencies: + asn1 "~0.2.0" + semver "^5.1.0" + streamsearch "~0.1.2" + +ssh2@~0.6.1: + version "0.6.2" + resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-0.6.2.tgz#b065d6e2133a2d4b557447d613b3511cb15e3a2e" + integrity sha512-DJ+dOhXEEsmNpcQTI0x69FS++JH6qqL/ltEHf01pI1SSLMAcmD+hL4jRwvHjPwynPsmSUbHJ/WIZYzROfqZWjA== + dependencies: + ssh2-streams "~0.2.0" + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +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== + +stack-trace@0.0.10, stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= + +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== + +stdout-stream@^1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" + integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA== + dependencies: + readable-stream "^2.0.1" + +stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + +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-consume@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.1.tgz#d3bdb598c2bd0ae82b8cac7ac50b1107a7996c48" + integrity sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg== + +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-exhaust@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d" + integrity sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw== + +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.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + +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" + +streamsearch@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" + integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= + +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@^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@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.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.trim@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.0.tgz#75a729b10cfc1be439543dae442129459ce61e3d" + integrity sha512-9EIjYD/WdlvLpn987+ctkLf0FfvBefOCuiEr2henD8X+7jfwPnyvTdmW8OJhj5p+M0/96mBdynLWkxUr+rHlpg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.13.0" + function-bind "^1.1.1" + +string.prototype.trimleft@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +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@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +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@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.3.0.tgz#25f48ea22ca79187f3174a4db8759347bb126220" + integrity sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA= + dependencies: + ansi-regex "^0.2.1" + +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@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-1.0.0.tgz#85b8862f3844b5a6d5ec8467a93598173a36f794" + integrity sha1-hbiGLzhEtabV7IRnqTWYFzo295Q= + dependencies: + first-chunk-stream "^1.0.0" + is-utf8 "^0.2.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-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +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-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +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-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + +strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +strip-json-comments@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== + +strip-json-comments@~1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" + integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E= + +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" + +sumchecker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.0.tgz#da5457b4605184575c76540e5e99cc777cb8ce4c" + integrity sha512-yreseuC/z4iaodVoq07XULEOO9p4jnQazO7mbrnDSvWAU/y2cbyIKs+gWJptfcGu9R+1l27K8Rkj0bfvqnBpgQ== + dependencies: + debug "^4.1.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@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" + integrity sha1-2S3iaU6z9nMjlz1649i1W0wiGQo= + +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" + +sver-compat@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8" + integrity sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg= + dependencies: + es6-iterator "^2.0.1" + es6-symbol "^3.1.1" + +svgo@^1.0.0, svgo@^1.0.5: + version "1.3.0" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.0.tgz#bae51ba95ded9a33a36b7c46ce9c359ae9154313" + integrity sha512-MLfUA6O+qauLDbym+mMZgtXCGRfIxyQoeH6IKVcFslyODEe/ElJNwr0FohQ3xG4C6HK6bk3KYPPXwHVJk3V5NQ== + 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.33" + csso "^3.5.1" + 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= + +symbol-tree@^3.2.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + +table@^3.7.8: + version "3.8.3" + resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" + integrity sha1-K7xULw/amGGnVdOUf+/Ys/UThV8= + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.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" + +tar-stream@~0.4.0: + version "0.4.7" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-0.4.7.tgz#1f1d2ce9ebc7b42765243ca0e8f1b7bfda0aadcd" + integrity sha1-Hx0s6evHtCdlJDyg6PG3v9oKrc0= + dependencies: + bl "^0.9.0" + end-of-stream "^1.0.0" + readable-stream "^1.0.27-1" + xtend "^4.0.0" + +tar@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" + integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== + dependencies: + block-stream "*" + fstream "^1.0.12" + inherits "2" + +tar@^4: + version "4.4.11" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.11.tgz#7ac09801445a3cf74445ed27499136b5240ffb73" + integrity sha512-iI4zh3ktLJKaDNZKZc+fUONiQrSn9HkCFzamtb7k8FFmVilHVob7QsLX/VySAW8lAviMzMbFw4QtFb4errwgYA== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.6.4" + minizlib "^1.2.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.3" + +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" + +ternary-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ternary-stream/-/ternary-stream-3.0.0.tgz#7951930ea9e823924d956f03d516151a2d516253" + integrity sha512-oIzdi+UL/JdktkT+7KU5tSIQjj8pbShj3OASuvDEhm0NT5lppsm7aXWAmAq4/QMaBIyfuEcNLbAQA+HpaISobQ== + dependencies: + duplexify "^4.1.1" + fork-stream "^0.0.4" + merge-stream "^2.0.0" + through2 "^3.0.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== + dependencies: + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" + schema-utils "^1.0.0" + serialize-javascript "^1.7.0" + 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.0.0, terser@^4.1.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.1.tgz#09820bcb3398299c4b48d9a86aefc65127d0ed65" + integrity sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +text-table@^0.2.0, 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-concurrent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/through2-concurrent/-/through2-concurrent-2.0.0.tgz#c9dd2c146504ec9962dbc86a5168b63d662669fa" + integrity sha512-R5/jLkfMvdmDD+seLwN7vB+mhbqzWop5fAjx5IX8/yQq7VhBhzDmhXgaHAOnhnWkCpRMM7gToYHycB0CS/pd+A== + dependencies: + through2 "^2.0.0" + +through2-filter@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" + integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== + dependencies: + through2 "~2.0.0" + xtend "~4.0.0" + +through2@*, through2@3.0.1, through2@^3.0.0, through2@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" + integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== + dependencies: + readable-stream "2 || 3" + +through2@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + integrity sha1-AARWmzfHx0ujnEPzzteNGtlBQL4= + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +through2@^0.4.1, through2@~0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b" + integrity sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s= + dependencies: + readable-stream "~1.0.17" + xtend "~2.1.1" + +through2@^0.5.0, through2@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.5.1.tgz#dfdd012eb9c700e2323fd334f38ac622ab372da7" + integrity sha1-390BLrnHAOIyP9M084rGIqs3Lac= + dependencies: + readable-stream "~1.0.17" + xtend "~3.0.0" + +through2@^0.6.1, through2@~0.6.1: + version "0.6.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" + integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg= + dependencies: + readable-stream ">=1.0.33-1 <1.1.0-0" + xtend ">=4.0.0 <4.1.0-0" + +through2@^2.0.0, through2@^2.0.1, through2@^2.0.2, through2@^2.0.3, 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" + +through2@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.3.0.tgz#2d1d28c8d1daf8d9c5cb78f0a69343c6b8642d97" + integrity sha1-LR0oyNHa+NnFy3jwppNDxrhkLZc= + dependencies: + readable-stream "~1.0.17" + xtend "~2.1.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= + +tildify@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" + integrity sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo= + dependencies: + os-homedir "^1.0.0" + +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= + +tiny-lr@0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/tiny-lr/-/tiny-lr-0.1.4.tgz#6e41d7e67dfd0878e5e0b37e37a06d67e309ff4d" + integrity sha1-bkHX5n39CHjl4LN+N6BtZ+MJ/00= + dependencies: + body-parser "~1.8.0" + debug "~0.8.1" + faye-websocket "~0.7.2" + parseurl "~1.3.0" + qs "~2.2.3" + +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-promise@^1.0.5: + version "1.1.0" + resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-1.1.0.tgz#bb924d239029157b9bc1d506a6aa341f8b13e64c" + integrity sha512-8+Ah9aB1IRXCnIOxXZ0uFozV1nMU5xiu7hhFVUSxZ3bYu+psD4TzagCzVbexUCgNNGJnsmNDQlS4nG3mTyoNkw== + dependencies: + bluebird "^3.5.0" + tmp "0.1.0" + +tmp@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" + integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== + dependencies: + rimraf "^2.6.3" + +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-absolute-glob@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" + integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs= + dependencies: + is-absolute "^1.0.0" + is-negated-glob "^1.0.0" + +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-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +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" + +to-through@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" + integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY= + dependencies: + through2 "^2.0.3" + +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== + +tough-cookie@^2.3.3, tough-cookie@^2.4.3: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + +tr46@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= + dependencies: + punycode "^2.1.0" + +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-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= + +trim@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= + +"true-case-path@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" + integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew== + dependencies: + glob "^7.1.2" + +truncate-utf8-bytes@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" + integrity sha1-QFkjkJWS1W94pYGENLC3hInKXys= + dependencies: + utf8-byte-length "^1.0.1" + +tslib@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + +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" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +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-is@~1.5.1: + version "1.5.7" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.5.7.tgz#b9368a593cc6ef7d0645e78b2f4c64cbecd05e90" + integrity sha1-uTaKWTzG730GReeLL0xky+zQXpA= + dependencies: + media-typer "0.3.0" + mime-types "~2.0.9" + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +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" + 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.3.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a" + integrity sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= + +underscore@~1.8.3: + version "1.8.3" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" + integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= + +undertaker-registry@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/undertaker-registry/-/undertaker-registry-1.0.1.tgz#5e4bda308e4a8a2ae584f9b9a4359a499825cc50" + integrity sha1-XkvaMI5KiirlhPm5pDWaSZglzFA= + +undertaker@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.2.1.tgz#701662ff8ce358715324dfd492a4f036055dfe4b" + integrity sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA== + dependencies: + arr-flatten "^1.0.1" + arr-map "^2.0.0" + bach "^1.0.0" + collection-map "^1.0.0" + es6-weak-map "^2.0.1" + last-run "^1.1.0" + object.defaults "^1.0.0" + object.reduce "^1.0.0" + undertaker-registry "^1.0.0" + +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.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" + integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" + integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== + +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" + +unique-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b" + integrity sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs= + +unique-stream@^2.0.2: + version "2.3.1" + resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" + integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A== + dependencies: + json-stable-stringify-without-jsonify "^1.0.1" + through2-filter "^3.0.0" + +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== + +user-home@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" + integrity sha1-K1viOjK2Onyd640PKNSFcko98ZA= + +user-home@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" + integrity sha1-nHC/2Babwdy/SGBODwS4tJzenp8= + dependencies: + os-homedir "^1.0.0" + +utf8-byte-length@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" + integrity sha1-9F8VDExm7uloGGUFq5P8u4rWv2E= + +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.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" + +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.10.3: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== + dependencies: + inherits "2.0.3" + +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, uuid@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" + integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== + +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== + +v8flags@^2.0.2: + version "2.1.1" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" + integrity sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ= + dependencies: + user-home "^1.1.1" + +v8flags@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.2.0.tgz#b243e3b4dfd731fa774e7492128109a0fe66d656" + integrity sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg== + dependencies: + homedir-polyfill "^1.0.1" + +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" + +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= + +vendors@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.3.tgz#a6467781abd366217c050f8202e7e50cc9eef8c0" + integrity sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vinyl-buffer@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/vinyl-buffer/-/vinyl-buffer-0.0.0.tgz#d197a824badcb11cccf9643ac91be24d43eda8db" + integrity sha1-0ZeoJLrcsRzM+WQ6yRviTUPtqNs= + dependencies: + bl "^0.7.0" + through2 "^0.4.1" + +vinyl-fs@^0.3.0: + version "0.3.14" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz#9a6851ce1cac1c1cea5fe86c0931d620c2cfa9e6" + integrity sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY= + dependencies: + defaults "^1.0.0" + glob-stream "^3.1.5" + glob-watcher "^0.0.6" + graceful-fs "^3.0.0" + mkdirp "^0.5.0" + strip-bom "^1.0.0" + through2 "^0.6.1" + vinyl "^0.4.0" + +vinyl-fs@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7" + integrity sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng== + dependencies: + fs-mkdirp-stream "^1.0.0" + glob-stream "^6.1.0" + graceful-fs "^4.0.0" + is-valid-glob "^1.0.0" + lazystream "^1.0.0" + lead "^1.0.0" + object.assign "^4.0.4" + pumpify "^1.3.5" + readable-stream "^2.3.3" + remove-bom-buffer "^3.0.0" + remove-bom-stream "^1.2.0" + resolve-options "^1.1.0" + through2 "^2.0.0" + to-through "^2.0.0" + value-or-function "^3.0.0" + vinyl "^2.0.0" + vinyl-sourcemap "^1.1.0" + +vinyl-source-stream@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-0.1.1.tgz#a53a4f21a07a234695e04c2703f9f1b5b9084595" + integrity sha1-pTpPIaB6I0aV4EwnA/nxtbkIRZU= + dependencies: + through2 "~0.3.0" + vinyl "~0.2.2" + +vinyl-sourcemap@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" + integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY= + dependencies: + append-buffer "^1.0.2" + convert-source-map "^1.5.0" + graceful-fs "^4.1.6" + normalize-path "^2.1.1" + now-and-later "^2.0.0" + remove-bom-buffer "^3.0.0" + vinyl "^2.0.0" + +vinyl-sourcemaps-apply@^0.2.0, vinyl-sourcemaps-apply@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" + integrity sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU= + dependencies: + source-map "^0.5.1" + +vinyl@*, vinyl@^2.0.0, vinyl@^2.1.0, vinyl@^2.2.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" + +vinyl@^0.2.1, vinyl@~0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.2.3.tgz#bca938209582ec5a49ad538a00fa1f125e513252" + integrity sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI= + dependencies: + clone-stats "~0.0.1" + +vinyl@^0.4.0: + version "0.4.6" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" + integrity sha1-LzVsh6VQolVGHza76ypbqL94SEc= + dependencies: + clone "^0.2.0" + clone-stats "^0.0.1" + +vinyl@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" + integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= + dependencies: + clone "^1.0.0" + clone-stats "^0.0.1" + replace-ext "0.0.1" + +vm-browserify@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019" + integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw== + +w3c-hr-time@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" + integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU= + dependencies: + browser-process-hrtime "^0.1.2" + +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" + +watch@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/watch/-/watch-0.11.0.tgz#e8dba091b7456799a3af57978b986e77e1320406" + integrity sha1-6NugkbdFZ5mjr1eXi5hud+EyBAY= + +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" + +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-cli@^3.1.0: + version "3.3.9" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.9.tgz#79c27e71f94b7fe324d594ab64a8e396b9daa91a" + integrity sha512-xwnSxWl8nZtBl/AFJCOn9pG7s5CYUYdZxmmukv+fAHLcBIHM36dImfpQg3WfShZXeArkWlf6QRw24Klcsv8a5A== + 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.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== + 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.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" + +websocket-driver@>=0.3.6: + version "0.7.3" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" + integrity sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg== + dependencies: + http-parser-js ">=0.4.0 <0.4.11" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" + integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== + +whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +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== + +whatwg-mimetype@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-url@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.0.0.tgz#fde926fa54a599f3adf82dff25a9f7be02dc6edd" + integrity sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + +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, which@^1.1.1, 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" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +winston@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/winston/-/winston-1.0.2.tgz#351c58e2323f8a4ca29a45195aa9aa3b4c35d76f" + integrity sha1-NRxY4jI/ikyimkUZWqmqO0w1128= + dependencies: + async "~1.0.0" + colors "1.0.x" + cycle "1.0.x" + eyes "0.1.x" + isstream "0.1.x" + pkginfo "0.3.x" + stack-trace "0.0.x" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + +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" + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= + dependencies: + mkdirp "^0.5.1" + +ws@^6.1.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-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +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.22" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.22.tgz#4fa2d846ec803237de86f30aa9b5f70b6600de02" + integrity sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw== + dependencies: + sax ">=0.6.0" + util.promisify "~1.0.0" + xmlbuilder "~11.0.0" + +xmlbuilder@^9.0.7: + version "9.0.7" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" + integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= + +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== + +xmlchars@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + +xmldom@0.1.x: + version "0.1.27" + resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" + integrity sha1-1QH5ezvbQDr4757MIFcxh6rawOk= + +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 <4.1.0-0", xtend@^4.0.0, 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== + +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= + dependencies: + object-keys "~0.4.0" + +xtend@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a" + integrity sha1-XM50B7r2Qsunvs2laBEcST9ZZlo= + +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.0, yallist@^3.0.2, yallist@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" + integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== + +yaml-loader@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/yaml-loader/-/yaml-loader-0.6.0.tgz#fe1c48b9f4803dace55a59a1474e790ba6ab1b48" + integrity sha512-1bNiLelumURyj+zvVHOv8Y3dpCri0F2S+DCcmps0pA1zWRLjS+FhZQg4o3aUUDYESh73+pKZNI18bj7stpReow== + dependencies: + loader-utils "^1.4.0" + yaml "^1.8.3" + +yaml@^1.8.3: + version "1.10.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" + integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== + +yargs-parser@5.0.0-security.0: + version "5.0.0-security.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz#4ff7271d25f90ac15643b86076a2ab499ec9ee24" + integrity sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ== + dependencies: + camelcase "^3.0.0" + object.assign "^4.1.0" + +yargs-parser@^13.0.0, yargs-parser@^13.1.0: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +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 "^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" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= + 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@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: + cliui "^5.0.0" + find-up "^3.0.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 "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" + +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: + 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.2" + +yargs@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" + integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= + 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 "^5.0.0" + +yargs@^7.1.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.1.tgz#67f0ef52e228d4ee0d6311acede8850f53464df6" + integrity sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g== + 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 "5.0.0-security.0" + +yargs@~1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.2.6.tgz#9c7b4a82fd5d595b2bf17ab6dcc43135432fe34b" + integrity sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s= + dependencies: + minimist "^0.1.0" + +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" + +yeast@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" + integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= + +zip-stream@~0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-0.4.1.tgz#4ea795a8ce19e9fab49a31d1d0877214159f03a3" + integrity sha1-TqeVqM4Z6fq0mjHR0IdyFBWfA6M= + dependencies: + compress-commons "~0.1.0" + lodash "~2.4.1" + readable-stream "~1.0.26" diff --git a/package.json b/package.json index af94e173..acd23c07 100644 --- a/package.json +++ b/package.json @@ -1,103 +1,101 @@ -{ - "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": { + "@octokit/rest": "^18.0.6", + "@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/bg_render.webm b/res/bg_render.webm index bda0db6b..86ed678e 100644 Binary files a/res/bg_render.webm and b/res/bg_render.webm differ 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/analyzer.png b/res/ui/building_icons/analyzer.png new file mode 100644 index 00000000..61f9e1ba Binary files /dev/null and b/res/ui/building_icons/analyzer.png differ diff --git a/res/ui/building_icons/balancer.png b/res/ui/building_icons/balancer.png new file mode 100644 index 00000000..4347d2ba Binary files /dev/null and b/res/ui/building_icons/balancer.png differ diff --git a/res/ui/building_icons/belt.png b/res/ui/building_icons/belt.png index f9ed2542..566e971d 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/comparator.png b/res/ui/building_icons/comparator.png new file mode 100644 index 00000000..25955e22 Binary files /dev/null and b/res/ui/building_icons/comparator.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..311df8a8 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..84eafc30 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..56548fde 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..16215918 Binary files /dev/null and b/res/ui/building_icons/filter.png differ diff --git a/res/ui/building_icons/item_producer.png b/res/ui/building_icons/item_producer.png new file mode 100644 index 00000000..ca267ea6 Binary files /dev/null and b/res/ui/building_icons/item_producer.png differ diff --git a/res/ui/building_icons/lever.png b/res/ui/building_icons/lever.png new file mode 100644 index 00000000..e4514b98 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..1de56dfa 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..9103750b 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..6ce15dbb 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..e0b63af5 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..8381c9b8 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..00a4c75d 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 deleted file mode 100644 index 29ea7123..00000000 Binary files a/res/ui/building_icons/splitter.png and /dev/null differ diff --git a/res/ui/building_icons/stacker.png b/res/ui/building_icons/stacker.png index 3098ae3e..ccafd591 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/storage.png b/res/ui/building_icons/storage.png new file mode 100644 index 00000000..5423513d Binary files /dev/null and b/res/ui/building_icons/storage.png differ diff --git a/res/ui/building_icons/transistor.png b/res/ui/building_icons/transistor.png new file mode 100644 index 00000000..5296edbb Binary files /dev/null and b/res/ui/building_icons/transistor.png differ diff --git a/res/ui/building_icons/trash.png b/res/ui/building_icons/trash.png index 8f094f2e..0f4238f4 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..a8f121c1 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..f67f4c84 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..1f07a846 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..97bfc3db Binary files /dev/null and b/res/ui/building_icons/wire_tunnel.png differ diff --git a/res/ui/building_tutorials/analyzer.png b/res/ui/building_tutorials/analyzer.png new file mode 100644 index 00000000..d0e820c1 Binary files /dev/null and b/res/ui/building_tutorials/analyzer.png differ diff --git a/res/ui/building_tutorials/splitter-compact.png b/res/ui/building_tutorials/balancer-merger.png similarity index 100% rename from res/ui/building_tutorials/splitter-compact.png rename to res/ui/building_tutorials/balancer-merger.png diff --git a/res/ui/building_tutorials/balancer-splitter.png b/res/ui/building_tutorials/balancer-splitter.png new file mode 100644 index 00000000..d03103b2 Binary files /dev/null and b/res/ui/building_tutorials/balancer-splitter.png differ diff --git a/res/ui/building_tutorials/splitter.png b/res/ui/building_tutorials/balancer.png similarity index 100% rename from res/ui/building_tutorials/splitter.png rename to res/ui/building_tutorials/balancer.png diff --git a/res/ui/building_tutorials/comparator.png b/res/ui/building_tutorials/comparator.png new file mode 100644 index 00000000..8dfed981 Binary files /dev/null and b/res/ui/building_tutorials/comparator.png differ diff --git a/res/ui/building_tutorials/constant_signal.png b/res/ui/building_tutorials/constant_signal.png new file mode 100644 index 00000000..70de0a21 Binary files /dev/null and b/res/ui/building_tutorials/constant_signal.png differ diff --git a/res/ui/building_tutorials/cutter-quad.png b/res/ui/building_tutorials/cutter-quad.png index 22137353..696a05be 100644 Binary files a/res/ui/building_tutorials/cutter-quad.png and b/res/ui/building_tutorials/cutter-quad.png differ diff --git a/res/ui/building_tutorials/display.png b/res/ui/building_tutorials/display.png new file mode 100644 index 00000000..de5c7ed7 Binary files /dev/null and b/res/ui/building_tutorials/display.png differ diff --git a/res/ui/building_tutorials/item_producer.png b/res/ui/building_tutorials/item_producer.png new file mode 100644 index 00000000..b0d15387 Binary files /dev/null and b/res/ui/building_tutorials/item_producer.png differ diff --git a/res/ui/building_tutorials/lever.png b/res/ui/building_tutorials/lever.png new file mode 100644 index 00000000..da7551f2 Binary files /dev/null and b/res/ui/building_tutorials/lever.png differ diff --git a/res/ui/building_tutorials/logic_gate-and.png b/res/ui/building_tutorials/logic_gate-and.png new file mode 100644 index 00000000..e8c31683 Binary files /dev/null and b/res/ui/building_tutorials/logic_gate-and.png differ diff --git a/res/ui/building_tutorials/logic_gate-not.png b/res/ui/building_tutorials/logic_gate-not.png new file mode 100644 index 00000000..47fbeb1b Binary files /dev/null and b/res/ui/building_tutorials/logic_gate-not.png differ diff --git a/res/ui/building_tutorials/logic_gate-or.png b/res/ui/building_tutorials/logic_gate-or.png new file mode 100644 index 00000000..d1c82770 Binary files /dev/null and b/res/ui/building_tutorials/logic_gate-or.png differ diff --git a/res/ui/building_tutorials/logic_gate-xor.png b/res/ui/building_tutorials/logic_gate-xor.png new file mode 100644 index 00000000..d9d282f7 Binary files /dev/null and b/res/ui/building_tutorials/logic_gate-xor.png differ diff --git a/res/ui/building_tutorials/painter-mirrored.png b/res/ui/building_tutorials/painter-mirrored.png new file mode 100644 index 00000000..63cc6683 Binary files /dev/null and b/res/ui/building_tutorials/painter-mirrored.png differ diff --git a/res/ui/building_tutorials/painter-quad.png b/res/ui/building_tutorials/painter-quad.png index 57536440..2d52a01b 100644 Binary files a/res/ui/building_tutorials/painter-quad.png and b/res/ui/building_tutorials/painter-quad.png differ diff --git a/res/ui/building_tutorials/painter.png b/res/ui/building_tutorials/painter.png index 8791082f..bb1147d5 100644 Binary files a/res/ui/building_tutorials/painter.png and b/res/ui/building_tutorials/painter.png differ diff --git a/res/ui/building_tutorials/reader.png b/res/ui/building_tutorials/reader.png new file mode 100644 index 00000000..c008e28e Binary files /dev/null and b/res/ui/building_tutorials/reader.png differ diff --git a/res/ui/building_tutorials/rotater-ccw.png b/res/ui/building_tutorials/rotater-ccw.png index a76b7179..cf13f63b 100644 Binary files a/res/ui/building_tutorials/rotater-ccw.png and b/res/ui/building_tutorials/rotater-ccw.png differ diff --git a/res/ui/building_tutorials/rotater-rotate180.png b/res/ui/building_tutorials/rotater-rotate180.png new file mode 100644 index 00000000..b2681662 Binary files /dev/null and b/res/ui/building_tutorials/rotater-rotate180.png differ diff --git a/res/ui/building_tutorials/rotater.png b/res/ui/building_tutorials/rotater.png index c8ecb8b0..0726f2b1 100644 Binary files a/res/ui/building_tutorials/rotater.png and b/res/ui/building_tutorials/rotater.png differ diff --git a/res/ui/building_tutorials/splitter-compact-inverse.png b/res/ui/building_tutorials/splitter-compact-inverse.png deleted file mode 100644 index 38965f4d..00000000 Binary files a/res/ui/building_tutorials/splitter-compact-inverse.png and /dev/null differ diff --git a/res/ui/building_tutorials/stacker.png b/res/ui/building_tutorials/stacker.png index 55232a2c..ef11af8d 100644 Binary files a/res/ui/building_tutorials/stacker.png and b/res/ui/building_tutorials/stacker.png differ diff --git a/res/ui/building_tutorials/storage.png b/res/ui/building_tutorials/storage.png new file mode 100644 index 00000000..b5d21433 Binary files /dev/null and b/res/ui/building_tutorials/storage.png differ diff --git a/res/ui/building_tutorials/transistor.png b/res/ui/building_tutorials/transistor.png new file mode 100644 index 00000000..e3ca0ba6 Binary files /dev/null and b/res/ui/building_tutorials/transistor.png differ diff --git a/res/ui/building_tutorials/trash-storage.png b/res/ui/building_tutorials/trash-storage.png deleted file mode 100644 index 50c77719..00000000 Binary files a/res/ui/building_tutorials/trash-storage.png and /dev/null differ diff --git a/res/ui/building_tutorials/virtual_processor-cutter.png b/res/ui/building_tutorials/virtual_processor-cutter.png new file mode 100644 index 00000000..45ad6d3a Binary files /dev/null and b/res/ui/building_tutorials/virtual_processor-cutter.png differ diff --git a/res/ui/building_tutorials/virtual_processor-painter.png b/res/ui/building_tutorials/virtual_processor-painter.png new file mode 100644 index 00000000..2b9387eb Binary files /dev/null and b/res/ui/building_tutorials/virtual_processor-painter.png differ diff --git a/res/ui/building_tutorials/virtual_processor-rotater.png b/res/ui/building_tutorials/virtual_processor-rotater.png new file mode 100644 index 00000000..752d21f8 Binary files /dev/null and b/res/ui/building_tutorials/virtual_processor-rotater.png differ diff --git a/res/ui/building_tutorials/virtual_processor-stacker.png b/res/ui/building_tutorials/virtual_processor-stacker.png new file mode 100644 index 00000000..fdaccb02 Binary files /dev/null and b/res/ui/building_tutorials/virtual_processor-stacker.png differ diff --git a/res/ui/building_tutorials/virtual_processor-unstacker.png b/res/ui/building_tutorials/virtual_processor-unstacker.png new file mode 100644 index 00000000..697c21cd Binary files /dev/null and b/res/ui/building_tutorials/virtual_processor-unstacker.png differ diff --git a/res/ui/building_tutorials/wire-second.png b/res/ui/building_tutorials/wire-second.png new file mode 100644 index 00000000..9f2b462c Binary files /dev/null and b/res/ui/building_tutorials/wire-second.png differ diff --git a/res/ui/building_tutorials/wire.png b/res/ui/building_tutorials/wire.png new file mode 100644 index 00000000..d5cf0bed Binary files /dev/null and b/res/ui/building_tutorials/wire.png differ diff --git a/res/ui/building_tutorials/wire_tunnel.png b/res/ui/building_tutorials/wire_tunnel.png new file mode 100644 index 00000000..e8b25063 Binary files /dev/null and b/res/ui/building_tutorials/wire_tunnel.png differ diff --git a/res/ui/get_on_steam_with_price.png b/res/ui/get_on_steam_with_price.png new file mode 100644 index 00000000..e935acdc Binary files /dev/null and b/res/ui/get_on_steam_with_price.png differ diff --git a/res/ui/icons/advantage_buildings.png b/res/ui/icons/advantage_buildings.png new file mode 100644 index 00000000..91e7a565 Binary files /dev/null and b/res/ui/icons/advantage_buildings.png differ diff --git a/res/ui/icons/advantage_dark_mode.png b/res/ui/icons/advantage_dark_mode.png new file mode 100644 index 00000000..c176b8ad Binary files /dev/null and b/res/ui/icons/advantage_dark_mode.png differ diff --git a/res/ui/icons/advantage_markers.png b/res/ui/icons/advantage_markers.png new file mode 100644 index 00000000..af3835c7 Binary files /dev/null and b/res/ui/icons/advantage_markers.png differ diff --git a/res/ui/icons/advantage_new_levels.png b/res/ui/icons/advantage_new_levels.png new file mode 100644 index 00000000..730732fe Binary files /dev/null and b/res/ui/icons/advantage_new_levels.png differ diff --git a/res/ui/icons/advantage_savegames.png b/res/ui/icons/advantage_savegames.png new file mode 100644 index 00000000..79e7c327 Binary files /dev/null and b/res/ui/icons/advantage_savegames.png differ diff --git a/res/ui/icons/advantage_support.png b/res/ui/icons/advantage_support.png new file mode 100644 index 00000000..b86703a5 Binary files /dev/null and b/res/ui/icons/advantage_support.png differ diff --git a/res/ui/icons/advantage_upgrades.png b/res/ui/icons/advantage_upgrades.png new file mode 100644 index 00000000..e06b6d82 Binary files /dev/null and b/res/ui/icons/advantage_upgrades.png differ diff --git a/res/ui/icons/advantage_wires.png b/res/ui/icons/advantage_wires.png new file mode 100644 index 00000000..bb26fa87 Binary files /dev/null and b/res/ui/icons/advantage_wires.png differ diff --git a/res/ui/icons/delete.png b/res/ui/icons/delete.png index db1c86f1..114693a6 100644 Binary files a/res/ui/icons/delete.png and b/res/ui/icons/delete.png differ diff --git a/res/ui/icons/demo_steam_link_indicator.png b/res/ui/icons/demo_steam_link_indicator.png new file mode 100644 index 00000000..98add9df Binary files /dev/null and b/res/ui/icons/demo_steam_link_indicator.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..9bea1b85 100644 Binary files a/res/ui/icons/download.png and b/res/ui/icons/download.png differ diff --git a/res/ui/icons/enum_selector_white.png b/res/ui/icons/enum_selector_white.png new file mode 100644 index 00000000..c95a44cc Binary files /dev/null and b/res/ui/icons/enum_selector_white.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/ui/icons/main_menu_exit.png b/res/ui/icons/main_menu_exit.png index 07a54c6c..b1918778 100644 Binary files a/res/ui/icons/main_menu_exit.png and b/res/ui/icons/main_menu_exit.png differ diff --git a/res/ui/icons/main_menu_settings.png b/res/ui/icons/main_menu_settings.png index eb99a2ef..88bd4987 100644 Binary files a/res/ui/icons/main_menu_settings.png and b/res/ui/icons/main_menu_settings.png differ diff --git a/res/ui/icons/save.png b/res/ui/icons/save.png index d48274bc..e75c08f4 100644 Binary files a/res/ui/icons/save.png and b/res/ui/icons/save.png differ diff --git a/res/ui/icons/settings_menu_exit.png b/res/ui/icons/settings_menu_exit.png new file mode 100644 index 00000000..3fa17330 Binary files /dev/null and b/res/ui/icons/settings_menu_exit.png differ diff --git a/res/ui/icons/settings_menu_play.png b/res/ui/icons/settings_menu_play.png new file mode 100644 index 00000000..358b5362 Binary files /dev/null and b/res/ui/icons/settings_menu_play.png differ diff --git a/res/ui/icons/settings_menu_settings.png b/res/ui/icons/settings_menu_settings.png new file mode 100644 index 00000000..8eb6efee Binary files /dev/null and b/res/ui/icons/settings_menu_settings.png differ diff --git a/res/ui/icons/shop.png b/res/ui/icons/shop.png index 29519103..94dbc6de 100644 Binary files a/res/ui/icons/shop.png and b/res/ui/icons/shop.png differ diff --git a/res/ui/icons/shop_active.png b/res/ui/icons/shop_active.png new file mode 100644 index 00000000..773d4c88 Binary files /dev/null and b/res/ui/icons/shop_active.png differ diff --git a/res/ui/icons/statistics.png b/res/ui/icons/statistics.png index c6b8e68a..e6349d88 100644 Binary files a/res/ui/icons/statistics.png and b/res/ui/icons/statistics.png differ diff --git a/res/ui/icons/toggle_unit.png b/res/ui/icons/toggle_unit.png new file mode 100644 index 00000000..e2126a97 Binary files /dev/null and b/res/ui/icons/toggle_unit.png differ diff --git a/res/ui/interactive_tutorial.noinline/21_1_place_quad_painter.gif b/res/ui/interactive_tutorial.noinline/21_1_place_quad_painter.gif new file mode 100644 index 00000000..ea854cf2 Binary files /dev/null and b/res/ui/interactive_tutorial.noinline/21_1_place_quad_painter.gif differ diff --git a/res/ui/interactive_tutorial.noinline/21_2_switch_to_wires.gif b/res/ui/interactive_tutorial.noinline/21_2_switch_to_wires.gif new file mode 100644 index 00000000..78ab6fd2 Binary files /dev/null and b/res/ui/interactive_tutorial.noinline/21_2_switch_to_wires.gif differ diff --git a/res/ui/interactive_tutorial.noinline/21_3_place_button.gif b/res/ui/interactive_tutorial.noinline/21_3_place_button.gif new file mode 100644 index 00000000..52ffb076 Binary files /dev/null and b/res/ui/interactive_tutorial.noinline/21_3_place_button.gif differ diff --git a/res/ui/interactive_tutorial.noinline/21_4_press_button.gif b/res/ui/interactive_tutorial.noinline/21_4_press_button.gif new file mode 100644 index 00000000..5d79f1e3 Binary files /dev/null and b/res/ui/interactive_tutorial.noinline/21_4_press_button.gif differ diff --git a/res/ui/interactive_tutorial.noinline/2_1_place_cutter.gif b/res/ui/interactive_tutorial.noinline/2_1_place_cutter.gif new file mode 100644 index 00000000..1678c0b2 Binary files /dev/null and b/res/ui/interactive_tutorial.noinline/2_1_place_cutter.gif differ diff --git a/res/ui/interactive_tutorial.noinline/2_2_place_trash.gif b/res/ui/interactive_tutorial.noinline/2_2_place_trash.gif new file mode 100644 index 00000000..0d60fa9f Binary files /dev/null and b/res/ui/interactive_tutorial.noinline/2_2_place_trash.gif differ diff --git a/res/ui/interactive_tutorial.noinline/2_3_more_cutters.gif b/res/ui/interactive_tutorial.noinline/2_3_more_cutters.gif new file mode 100644 index 00000000..50ce88f9 Binary files /dev/null and b/res/ui/interactive_tutorial.noinline/2_3_more_cutters.gif differ diff --git a/res/ui/interactive_tutorial.noinline/3_1_rectangles.gif b/res/ui/interactive_tutorial.noinline/3_1_rectangles.gif new file mode 100644 index 00000000..418d3123 Binary files /dev/null and b/res/ui/interactive_tutorial.noinline/3_1_rectangles.gif differ diff --git a/res/ui/languages/da.svg b/res/ui/languages/da.svg index ea9d950a..b6ace9ab 100644 --- a/res/ui/languages/da.svg +++ b/res/ui/languages/da.svg @@ -1,36 +1,38 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/ui/memes/cat1.png b/res/ui/memes/cat1.png new file mode 100644 index 00000000..114c3fa0 Binary files /dev/null and b/res/ui/memes/cat1.png differ diff --git a/res_built/.gitignore b/res_built/.gitignore deleted file mode 100644 index 060e04d9..00000000 --- a/res_built/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# Ignore built sounds -sounds 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_raw/atlas.json b/res_raw/atlas.json new file mode 100644 index 00000000..9e548568 --- /dev/null +++ b/res_raw/atlas.json @@ -0,0 +1,22 @@ +{ + "pot": true, + "paddingX": 2, + "paddingY": 2, + "edgePadding": true, + "rotation": false, + "maxWidth": 2048, + "useIndexes": false, + "alphaThreshold": 1, + "maxHeight": 2048, + "stripWhitespaceX": true, + "stripWhitespaceY": true, + "duplicatePadding": true, + "alias": true, + "fast": false, + "limitMemory": false, + "combineSubdirectories": true, + "flattenPaths": false, + "bleedIterations": 4, + "scale": [0.25, 0.5, 0.75], + "scaleSuffix": ["_lq", "_mq", "_hq"] +} diff --git a/res_raw/atlas.tps b/res_raw/atlas.tps deleted file mode 100644 index 87eacd70..00000000 --- a/res_raw/atlas.tps +++ /dev/null @@ -1,648 +0,0 @@ - - - - fileFormatVersion - 4 - texturePackerVersion - 5.4.0 - autoSDSettings - - - scale - 1 - extension - _100 - spriteFilter - - acceptFractionalValues - - maxTextureSize - - width - 4096 - height - 4096 - - - - scale - 0.75 - extension - _75 - spriteFilter - - acceptFractionalValues - - maxTextureSize - - width - 2048 - height - 2048 - - - - scale - 0.5 - extension - _50 - spriteFilter - - acceptFractionalValues - - maxTextureSize - - width - 2048 - height - 2048 - - - - scale - 0.25 - extension - _25 - spriteFilter - - acceptFractionalValues - - maxTextureSize - - width - 1024 - height - 1024 - - - - scale - 0.1 - extension - _10 - spriteFilter - - acceptFractionalValues - - maxTextureSize - - width - -1 - height - -1 - - - - allowRotation - - shapeDebug - - dpi - 72 - dataFormat - json - textureFileName - - flipPVR - - pvrCompressionQuality - PVR_QUALITY_NORMAL - atfCompressData - - mipMapMinSize - 32768 - etc1CompressionQuality - ETC1_QUALITY_LOW_PERCEPTUAL - etc2CompressionQuality - ETC2_QUALITY_LOW_PERCEPTUAL - dxtCompressionMode - DXT_PERCEPTUAL - jxrColorFormat - JXR_YUV444 - jxrTrimFlexBits - 0 - jxrCompressionLevel - 0 - ditherType - NearestNeighbour - backgroundColor - 0 - libGdx - - filtering - - x - Linear - y - Linear - - - shapePadding - 0 - jpgQuality - 80 - pngOptimizationLevel - 0 - webpQualityLevel - 101 - textureSubPath - - atfFormats - - textureFormat - png - borderPadding - 1 - maxTextureSize - - width - 2048 - height - 2048 - - fixedTextureSize - - width - -1 - height - -1 - - algorithmSettings - - algorithm - MaxRects - freeSizeMode - Best - sizeConstraints - AnySize - forceSquared - - maxRects - - heuristic - Best - - basic - - sortBy - Best - order - Ascending - - polygon - - alignToGrid - 1 - - - dataFileNames - - data - - name - ../res_built/atlas/atlas{n}{v}.json - - - multiPack - - forceIdenticalLayout - - outputFormat - RGBA8888 - alphaHandling - ClearTransparentPixels - contentProtection - - key - - - autoAliasEnabled - - trimSpriteNames - - prependSmartFolderName - - autodetectAnimations - - globalSpriteSettings - - scale - 1 - scaleMode - Smooth - extrude - 2 - trimThreshold - 2 - trimMargin - 1 - trimMode - Trim - tracerTolerance - 200 - heuristicMask - - defaultPivotPoint - 0.5,0.5 - writePivotPoints - - - 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 - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 32,32,64,64 - scale9Paddings - 32,32,64,64 - 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/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 - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 32,32,63,63 - scale9Paddings - 32,32,63,63 - 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 - sprites/buildings/painter-quad.png - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 192,48,384,96 - scale9Paddings - 192,48,384,96 - scale9FromFile - - - sprites/blueprints/cutter.png - sprites/blueprints/mixer.png - sprites/blueprints/painter-mirrored.png - sprites/blueprints/painter.png - sprites/blueprints/splitter.png - sprites/blueprints/stacker.png - sprites/buildings/painter-mirrored.png - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 96,48,192,96 - scale9Paddings - 96,48,192,96 - 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 - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 48,48,96,96 - scale9Paddings - 48,48,96,96 - scale9FromFile - - - sprites/buildings/cutter.png - sprites/buildings/mixer.png - sprites/buildings/painter.png - sprites/buildings/splitter.png - sprites/buildings/stacker.png - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 64,32,128,64 - scale9Paddings - 64,32,128,64 - scale9FromFile - - - sprites/buildings/hub.png - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 192,192,384,384 - scale9Paddings - 192,192,384,384 - scale9FromFile - - - sprites/buildings/trash-storage.png - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 144,144,288,288 - scale9Paddings - 144,144,288,288 - scale9FromFile - - - 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 - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 8,8,16,16 - scale9Paddings - 8,8,16,16 - scale9FromFile - - - sprites/misc/deletion_marker.png - sprites/misc/slot_bad_arrow.png - sprites/misc/slot_good_arrow.png - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 24,24,48,48 - scale9Paddings - 24,24,48,48 - 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 - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 44,22,89,43 - scale9Paddings - 44,22,89,43 - 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 - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 16,16,32,32 - scale9Paddings - 16,16,32,32 - scale9FromFile - - - - fileList - - sprites - - ignoreFileList - - replaceList - - ignoredWarnings - - commonDivisorX - 1 - commonDivisorY - 1 - packNormalMaps - - autodetectNormalMaps - - normalMapFilter - - normalMapSuffix - - normalMapSheetFileName - - exporterProperties - - - diff --git a/res_raw/sounds/music/menu.wav b/res_raw/sounds/music/menu.wav index 4024b94a..54a5d9d3 100644 Binary files a/res_raw/sounds/music/menu.wav and b/res_raw/sounds/music/menu.wav differ diff --git a/res_raw/sounds/music/theme-full.mp3 b/res_raw/sounds/music/theme-full.mp3 new file mode 100644 index 00000000..db26aeb8 Binary files /dev/null and b/res_raw/sounds/music/theme-full.mp3 differ diff --git a/res_raw/sounds/music/theme-short.mp3 b/res_raw/sounds/music/theme-short.mp3 new file mode 100644 index 00000000..1cc3b7da Binary files /dev/null and b/res_raw/sounds/music/theme-short.mp3 differ diff --git a/res_raw/sounds/music/theme.wav b/res_raw/sounds/music/theme.wav deleted file mode 100644 index 555caaee..00000000 --- a/res_raw/sounds/music/theme.wav +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:df7487fb5e8cb34cecee2519b9c3162a5107d2d7b1301c4a550904cfb108a015 -size 223361394 diff --git a/res_raw/sounds/sfx/badge_notification.wav b/res_raw/sounds/sfx/badge_notification.wav index 0af30494..4a1a4f3f 100644 Binary files a/res_raw/sounds/sfx/badge_notification.wav and b/res_raw/sounds/sfx/badge_notification.wav differ diff --git a/res_raw/sounds/sfx/copy.wav b/res_raw/sounds/sfx/copy.wav new file mode 100644 index 00000000..c595b90a Binary files /dev/null and b/res_raw/sounds/sfx/copy.wav differ diff --git a/res_raw/sounds/sfx/destroy_building.wav b/res_raw/sounds/sfx/destroy_building.wav index ffb38158..111469f3 100644 Binary files a/res_raw/sounds/sfx/destroy_building.wav and b/res_raw/sounds/sfx/destroy_building.wav differ diff --git a/res_raw/sounds/sfx/dialog_error.wav b/res_raw/sounds/sfx/dialog_error.wav index ef7eddfd..66a7a653 100644 Binary files a/res_raw/sounds/sfx/dialog_error.wav and b/res_raw/sounds/sfx/dialog_error.wav differ diff --git a/res_raw/sounds/sfx/dialog_ok.wav b/res_raw/sounds/sfx/dialog_ok.wav index 889d3426..20181cc9 100644 Binary files a/res_raw/sounds/sfx/dialog_ok.wav and b/res_raw/sounds/sfx/dialog_ok.wav differ diff --git a/res_raw/sounds/sfx/level_complete.wav b/res_raw/sounds/sfx/level_complete.wav index 71444cd8..96c6f9fb 100644 Binary files a/res_raw/sounds/sfx/level_complete.wav and b/res_raw/sounds/sfx/level_complete.wav differ diff --git a/res_raw/sounds/sfx/place_belt.wav b/res_raw/sounds/sfx/place_belt.wav index 087104bc..f2ac6c21 100644 Binary files a/res_raw/sounds/sfx/place_belt.wav and b/res_raw/sounds/sfx/place_belt.wav differ diff --git a/res_raw/sounds/sfx/place_building.wav b/res_raw/sounds/sfx/place_building.wav index 3bb89df5..329d1d65 100644 Binary files a/res_raw/sounds/sfx/place_building.wav and b/res_raw/sounds/sfx/place_building.wav differ diff --git a/res_raw/sounds/sfx/ui_click.wav b/res_raw/sounds/sfx/ui_click.wav index 673b8904..3535f23e 100644 Binary files a/res_raw/sounds/sfx/ui_click.wav and b/res_raw/sounds/sfx/ui_click.wav differ diff --git a/res_raw/sounds/sfx/ui_error.wav b/res_raw/sounds/sfx/ui_error.wav index 283ea26c..07a988d2 100644 Binary files a/res_raw/sounds/sfx/ui_error.wav and b/res_raw/sounds/sfx/ui_error.wav differ diff --git a/res_raw/sounds/sfx/ui_swish_hide.wav b/res_raw/sounds/sfx/ui_swish_hide.wav index ad7bed1d..e24b0939 100644 Binary files a/res_raw/sounds/sfx/ui_swish_hide.wav and b/res_raw/sounds/sfx/ui_swish_hide.wav differ diff --git a/res_raw/sounds/sfx/ui_swish_show.wav b/res_raw/sounds/sfx/ui_swish_show.wav index 63436899..e46cf9eb 100644 Binary files a/res_raw/sounds/sfx/ui_swish_show.wav and b/res_raw/sounds/sfx/ui_swish_show.wav differ 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..7db9782c --- /dev/null +++ b/res_raw/sprites/belt/generate_wire_sprites.js @@ -0,0 +1,212 @@ +/** + * + * 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 = 14; +const lowerLineSize = 32; + +const variants = { + first: "#61ef6f", + second: "#5fb2f1", + conflict: "#f74c4c", +}; + +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 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); + + const lineCanvas = createCanvas(dimensions, dimensions); + const lineContext = lineCanvas.getContext("2d"); + lineContext.quality = "best"; + lineContext.clearRect(0, 0, dimensions, dimensions); + lineContext.strokeStyle = hexDarkenedColor; + lineContext.lineWidth = lowerLineSize; + lineContext.lineCap = "square"; + lineContext.imageSmoothingEnabled = false; + + // Draw lower lines + partLines.forEach(([x1, y1, x2, y2]) => { + lineContext.beginPath(); + lineContext.moveTo(x1 * dimensions, y1 * dimensions); + lineContext.lineTo(x2 * dimensions, y2 * dimensions); + lineContext.stroke(); + }); + + context.globalAlpha = 0.4; + context.drawImage(lineCanvas, 0, 0, dimensions, dimensions); + + context.globalAlpha = 1; + context.imageSmoothingEnabled = false; + context.lineCap = "square"; + 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); + + 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/analyzer.png b/res_raw/sprites/blueprints/analyzer.png new file mode 100644 index 00000000..9aa5d298 Binary files /dev/null and b/res_raw/sprites/blueprints/analyzer.png differ diff --git a/res_raw/sprites/blueprints/balancer-merger-inverse.png b/res_raw/sprites/blueprints/balancer-merger-inverse.png new file mode 100644 index 00000000..3940e0a6 Binary files /dev/null and b/res_raw/sprites/blueprints/balancer-merger-inverse.png differ diff --git a/res_raw/sprites/blueprints/balancer-merger.png b/res_raw/sprites/blueprints/balancer-merger.png new file mode 100644 index 00000000..a9554f33 Binary files /dev/null and b/res_raw/sprites/blueprints/balancer-merger.png differ diff --git a/res_raw/sprites/blueprints/balancer-splitter-inverse.png b/res_raw/sprites/blueprints/balancer-splitter-inverse.png new file mode 100644 index 00000000..c9c4c4c9 Binary files /dev/null and b/res_raw/sprites/blueprints/balancer-splitter-inverse.png differ diff --git a/res_raw/sprites/blueprints/balancer-splitter.png b/res_raw/sprites/blueprints/balancer-splitter.png new file mode 100644 index 00000000..3d59d05f Binary files /dev/null and b/res_raw/sprites/blueprints/balancer-splitter.png differ diff --git a/res_raw/sprites/blueprints/balancer.png b/res_raw/sprites/blueprints/balancer.png new file mode 100644 index 00000000..52473772 Binary files /dev/null and b/res_raw/sprites/blueprints/balancer.png 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/comparator.png b/res_raw/sprites/blueprints/comparator.png new file mode 100644 index 00000000..6fe8abfb Binary files /dev/null and b/res_raw/sprites/blueprints/comparator.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..34adf95b Binary files /dev/null and b/res_raw/sprites/blueprints/constant_signal.png differ diff --git a/res_raw/sprites/blueprints/cutter-quad.png b/res_raw/sprites/blueprints/cutter-quad.png index 5ae8989e..bf47b09b 100644 Binary files a/res_raw/sprites/blueprints/cutter-quad.png and b/res_raw/sprites/blueprints/cutter-quad.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/item_producer.png b/res_raw/sprites/blueprints/item_producer.png new file mode 100644 index 00000000..2288c07d Binary files /dev/null and b/res_raw/sprites/blueprints/item_producer.png differ diff --git a/res_raw/sprites/blueprints/lever.png b/res_raw/sprites/blueprints/lever.png new file mode 100644 index 00000000..cca2ccea 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..e8b4573a Binary files /dev/null and b/res_raw/sprites/blueprints/logic_gate-or.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..9a711fe4 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..5b492203 Binary files /dev/null and b/res_raw/sprites/blueprints/logic_gate.png differ diff --git a/res_raw/sprites/blueprints/painter-double.png b/res_raw/sprites/blueprints/painter-double.png index 0fe1d913..f0bf0160 100644 Binary files a/res_raw/sprites/blueprints/painter-double.png and b/res_raw/sprites/blueprints/painter-double.png differ diff --git a/res_raw/sprites/blueprints/painter-mirrored.png b/res_raw/sprites/blueprints/painter-mirrored.png index f72f80e2..7641a7cd 100644 Binary files a/res_raw/sprites/blueprints/painter-mirrored.png and b/res_raw/sprites/blueprints/painter-mirrored.png differ diff --git a/res_raw/sprites/blueprints/painter-quad.png b/res_raw/sprites/blueprints/painter-quad.png index c3c755f2..75d5100a 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/painter.png b/res_raw/sprites/blueprints/painter.png index c2326268..0fe02224 100644 Binary files a/res_raw/sprites/blueprints/painter.png and b/res_raw/sprites/blueprints/painter.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-rotate180.png b/res_raw/sprites/blueprints/rotater-rotate180.png new file mode 100644 index 00000000..e27c78e5 Binary files /dev/null and b/res_raw/sprites/blueprints/rotater-rotate180.png differ diff --git a/res_raw/sprites/blueprints/splitter-compact-inverse.png b/res_raw/sprites/blueprints/splitter-compact-inverse.png deleted file mode 100644 index db528f32..00000000 Binary files a/res_raw/sprites/blueprints/splitter-compact-inverse.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/splitter-compact.png b/res_raw/sprites/blueprints/splitter-compact.png deleted file mode 100644 index 3e3c81f7..00000000 Binary files a/res_raw/sprites/blueprints/splitter-compact.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/splitter.png b/res_raw/sprites/blueprints/splitter.png deleted file mode 100644 index 984a99a8..00000000 Binary files a/res_raw/sprites/blueprints/splitter.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/storage.png b/res_raw/sprites/blueprints/storage.png new file mode 100644 index 00000000..0d9f62db Binary files /dev/null and b/res_raw/sprites/blueprints/storage.png differ diff --git a/res_raw/sprites/blueprints/transistor-mirrored.png b/res_raw/sprites/blueprints/transistor-mirrored.png new file mode 100644 index 00000000..88eaad0d Binary files /dev/null and b/res_raw/sprites/blueprints/transistor-mirrored.png differ diff --git a/res_raw/sprites/blueprints/transistor.png b/res_raw/sprites/blueprints/transistor.png new file mode 100644 index 00000000..b13aedea Binary files /dev/null and b/res_raw/sprites/blueprints/transistor.png differ diff --git a/res_raw/sprites/blueprints/trash-storage.png b/res_raw/sprites/blueprints/trash-storage.png deleted file mode 100644 index a4e6122f..00000000 Binary files a/res_raw/sprites/blueprints/trash-storage.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/underground_belt_entry-tier2.png b/res_raw/sprites/blueprints/underground_belt_entry-tier2.png index 9a4beb66..796dff59 100644 Binary files a/res_raw/sprites/blueprints/underground_belt_entry-tier2.png and b/res_raw/sprites/blueprints/underground_belt_entry-tier2.png differ diff --git a/res_raw/sprites/blueprints/underground_belt_entry.png b/res_raw/sprites/blueprints/underground_belt_entry.png index aa237b6d..f9ad0ba5 100644 Binary files a/res_raw/sprites/blueprints/underground_belt_entry.png and b/res_raw/sprites/blueprints/underground_belt_entry.png differ diff --git a/res_raw/sprites/blueprints/underground_belt_exit-tier2.png b/res_raw/sprites/blueprints/underground_belt_exit-tier2.png index b9c97b75..be78107b 100644 Binary files a/res_raw/sprites/blueprints/underground_belt_exit-tier2.png and b/res_raw/sprites/blueprints/underground_belt_exit-tier2.png differ diff --git a/res_raw/sprites/blueprints/underground_belt_exit.png b/res_raw/sprites/blueprints/underground_belt_exit.png index 760f63a9..9f02504d 100644 Binary files a/res_raw/sprites/blueprints/underground_belt_exit.png and b/res_raw/sprites/blueprints/underground_belt_exit.png differ diff --git a/res_raw/sprites/blueprints/virtual_processor-painter.png b/res_raw/sprites/blueprints/virtual_processor-painter.png new file mode 100644 index 00000000..243517db Binary files /dev/null and b/res_raw/sprites/blueprints/virtual_processor-painter.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..1cf0e901 Binary files /dev/null and b/res_raw/sprites/blueprints/virtual_processor-rotater.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..09363c3e 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_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.png b/res_raw/sprites/blueprints/wire_tunnel.png new file mode 100644 index 00000000..5a2f9c69 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/analyzer.png b/res_raw/sprites/buildings/analyzer.png new file mode 100644 index 00000000..f30c8d3b Binary files /dev/null and b/res_raw/sprites/buildings/analyzer.png differ diff --git a/res_raw/sprites/buildings/balancer-merger-inverse.png b/res_raw/sprites/buildings/balancer-merger-inverse.png new file mode 100644 index 00000000..ff9c3833 Binary files /dev/null and b/res_raw/sprites/buildings/balancer-merger-inverse.png differ diff --git a/res_raw/sprites/buildings/balancer-merger.png b/res_raw/sprites/buildings/balancer-merger.png new file mode 100644 index 00000000..7101c824 Binary files /dev/null and b/res_raw/sprites/buildings/balancer-merger.png differ diff --git a/res_raw/sprites/buildings/balancer-splitter-inverse.png b/res_raw/sprites/buildings/balancer-splitter-inverse.png new file mode 100644 index 00000000..4a765fa4 Binary files /dev/null and b/res_raw/sprites/buildings/balancer-splitter-inverse.png differ diff --git a/res_raw/sprites/buildings/balancer-splitter.png b/res_raw/sprites/buildings/balancer-splitter.png new file mode 100644 index 00000000..e8fb62be Binary files /dev/null and b/res_raw/sprites/buildings/balancer-splitter.png differ diff --git a/res_raw/sprites/buildings/balancer.png b/res_raw/sprites/buildings/balancer.png new file mode 100644 index 00000000..d1d12ad9 Binary files /dev/null and b/res_raw/sprites/buildings/balancer.png 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/comparator.png b/res_raw/sprites/buildings/comparator.png new file mode 100644 index 00000000..dad1e4bf Binary files /dev/null and b/res_raw/sprites/buildings/comparator.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..cba902bf Binary files /dev/null and b/res_raw/sprites/buildings/constant_signal.png differ diff --git a/res_raw/sprites/buildings/cutter-quad.png b/res_raw/sprites/buildings/cutter-quad.png index e67628f2..00d70cdc 100644 Binary files a/res_raw/sprites/buildings/cutter-quad.png and b/res_raw/sprites/buildings/cutter-quad.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/item_producer.png b/res_raw/sprites/buildings/item_producer.png new file mode 100644 index 00000000..573ef372 Binary files /dev/null and b/res_raw/sprites/buildings/item_producer.png differ diff --git a/res_raw/sprites/buildings/lever.png b/res_raw/sprites/buildings/lever.png new file mode 100644 index 00000000..fea5a18a 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..f2995a86 Binary files /dev/null and b/res_raw/sprites/buildings/logic_gate-or.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..3828e4a0 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..aa0ad6fd Binary files /dev/null and b/res_raw/sprites/buildings/logic_gate.png differ diff --git a/res_raw/sprites/buildings/painter-double.png b/res_raw/sprites/buildings/painter-double.png index 0d909786..9d2c472e 100644 Binary files a/res_raw/sprites/buildings/painter-double.png and b/res_raw/sprites/buildings/painter-double.png differ diff --git a/res_raw/sprites/buildings/painter-mirrored.png b/res_raw/sprites/buildings/painter-mirrored.png index da0e199d..2a3310d7 100644 Binary files a/res_raw/sprites/buildings/painter-mirrored.png and b/res_raw/sprites/buildings/painter-mirrored.png differ diff --git a/res_raw/sprites/buildings/painter-quad.png b/res_raw/sprites/buildings/painter-quad.png index 18790a78..698b753a 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/painter.png b/res_raw/sprites/buildings/painter.png index 1ebca21f..3382d420 100644 Binary files a/res_raw/sprites/buildings/painter.png and b/res_raw/sprites/buildings/painter.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-rotate180.png b/res_raw/sprites/buildings/rotater-rotate180.png new file mode 100644 index 00000000..c5969351 Binary files /dev/null and b/res_raw/sprites/buildings/rotater-rotate180.png differ diff --git a/res_raw/sprites/buildings/splitter-compact-inverse.png b/res_raw/sprites/buildings/splitter-compact-inverse.png deleted file mode 100644 index 1d9bd4c9..00000000 Binary files a/res_raw/sprites/buildings/splitter-compact-inverse.png and /dev/null differ diff --git a/res_raw/sprites/buildings/splitter-compact.png b/res_raw/sprites/buildings/splitter-compact.png deleted file mode 100644 index f0f80a0b..00000000 Binary files a/res_raw/sprites/buildings/splitter-compact.png and /dev/null differ diff --git a/res_raw/sprites/buildings/splitter.png b/res_raw/sprites/buildings/splitter.png deleted file mode 100644 index 7cd9a2ef..00000000 Binary files a/res_raw/sprites/buildings/splitter.png and /dev/null differ diff --git a/res_raw/sprites/buildings/storage.png b/res_raw/sprites/buildings/storage.png new file mode 100644 index 00000000..1e30b766 Binary files /dev/null and b/res_raw/sprites/buildings/storage.png differ diff --git a/res_raw/sprites/buildings/transistor-mirrored.png b/res_raw/sprites/buildings/transistor-mirrored.png new file mode 100644 index 00000000..606bfce3 Binary files /dev/null and b/res_raw/sprites/buildings/transistor-mirrored.png differ diff --git a/res_raw/sprites/buildings/transistor.png b/res_raw/sprites/buildings/transistor.png new file mode 100644 index 00000000..e543d985 Binary files /dev/null and b/res_raw/sprites/buildings/transistor.png differ diff --git a/res_raw/sprites/buildings/trash-storage.png b/res_raw/sprites/buildings/trash-storage.png deleted file mode 100644 index 57b1519e..00000000 Binary files a/res_raw/sprites/buildings/trash-storage.png and /dev/null differ diff --git a/res_raw/sprites/buildings/underground_belt_entry-tier2.png b/res_raw/sprites/buildings/underground_belt_entry-tier2.png index 3a30f4b5..96dd4f66 100644 Binary files a/res_raw/sprites/buildings/underground_belt_entry-tier2.png and b/res_raw/sprites/buildings/underground_belt_entry-tier2.png differ diff --git a/res_raw/sprites/buildings/underground_belt_entry.png b/res_raw/sprites/buildings/underground_belt_entry.png index 3b771f60..c1e4c4e8 100644 Binary files a/res_raw/sprites/buildings/underground_belt_entry.png and b/res_raw/sprites/buildings/underground_belt_entry.png differ diff --git a/res_raw/sprites/buildings/underground_belt_exit-tier2.png b/res_raw/sprites/buildings/underground_belt_exit-tier2.png index 87c59bf3..2ee15c61 100644 Binary files a/res_raw/sprites/buildings/underground_belt_exit-tier2.png and b/res_raw/sprites/buildings/underground_belt_exit-tier2.png differ diff --git a/res_raw/sprites/buildings/underground_belt_exit.png b/res_raw/sprites/buildings/underground_belt_exit.png index c281ed0e..9614ae11 100644 Binary files a/res_raw/sprites/buildings/underground_belt_exit.png and b/res_raw/sprites/buildings/underground_belt_exit.png differ diff --git a/res_raw/sprites/buildings/virtual_processor-painter.png b/res_raw/sprites/buildings/virtual_processor-painter.png new file mode 100644 index 00000000..b952e9d7 Binary files /dev/null and b/res_raw/sprites/buildings/virtual_processor-painter.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..6cad3244 Binary files /dev/null and b/res_raw/sprites/buildings/virtual_processor-rotater.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..59c5bada 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_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.png b/res_raw/sprites/buildings/wire_tunnel.png new file mode 100644 index 00000000..a798036e Binary files /dev/null and b/res_raw/sprites/buildings/wire_tunnel.png differ diff --git a/res_raw/sprites/colors/blue.png b/res_raw/sprites/colors/blue.png new file mode 100644 index 00000000..5dceb132 Binary files /dev/null and b/res_raw/sprites/colors/blue.png differ diff --git a/res_raw/sprites/colors/cyan.png b/res_raw/sprites/colors/cyan.png new file mode 100644 index 00000000..efd0ff1a Binary files /dev/null and b/res_raw/sprites/colors/cyan.png differ diff --git a/res_raw/sprites/colors/green.png b/res_raw/sprites/colors/green.png new file mode 100644 index 00000000..f719e0ce Binary files /dev/null and b/res_raw/sprites/colors/green.png differ diff --git a/res_raw/sprites/colors/purple.png b/res_raw/sprites/colors/purple.png new file mode 100644 index 00000000..ee3ebaf1 Binary files /dev/null and b/res_raw/sprites/colors/purple.png differ diff --git a/res_raw/sprites/colors/red.png b/res_raw/sprites/colors/red.png new file mode 100644 index 00000000..8e918371 Binary files /dev/null and b/res_raw/sprites/colors/red.png differ diff --git a/res_raw/sprites/colors/uncolored.png b/res_raw/sprites/colors/uncolored.png new file mode 100644 index 00000000..9ca5159e Binary files /dev/null and b/res_raw/sprites/colors/uncolored.png differ diff --git a/res_raw/sprites/colors/white.png b/res_raw/sprites/colors/white.png new file mode 100644 index 00000000..3f1c29f4 Binary files /dev/null and b/res_raw/sprites/colors/white.png differ diff --git a/res_raw/sprites/colors/yellow.png b/res_raw/sprites/colors/yellow.png new file mode 100644 index 00000000..6dc9c0ea Binary files /dev/null and b/res_raw/sprites/colors/yellow.png differ diff --git a/res_raw/sprites/create_blueprint_previews.py b/res_raw/sprites/create_blueprint_previews.py index cceefae0..96688fe4 100644 --- a/res_raw/sprites/create_blueprint_previews.py +++ b/res_raw/sprites/create_blueprint_previews.py @@ -1,110 +1,92 @@ -# Requirements: numpy, scipy, Pillow, -from __future__ import print_function -import sys -import numpy as np -from scipy import ndimage -from PIL import Image, ImageFilter, ImageChops -import math -from os import listdir -from os.path import isdir, isfile - -roberts_cross_v = np.array([[0, 0, 0], - [0, 1, 0], - [0, 0, -1]]) - -roberts_cross_h = np.array([[0, 0, 0], - [0, 0, 1], - [0, -1, 0]]) - - -def rgb2gray(rgb): - return np.dot(rgb[..., :3], [0.2989, 0.5870, 0.1140]) - - - - -def save_image(data, outfilename, src_image): - img = Image.fromarray(np.asarray( - np.clip(data, 0, 255), dtype="uint8"), "L") - dest = Image.new("RGBA", (img.width, img.height)) - src = img.load() - dst = dest.load() - - realSrc = src_image.load() - mask = src_image.filter(ImageFilter.GaussianBlur(10)).load() - orig = src_image.load() - - - isWire = "wire" in outfilename - - targetR = 104 - targetG = 200 - targetB = 255 - - if isWire: - targetR = 255 - targetG = 104 - targetB = 232 - - for x in range(img.width): - for y in range(img.height): - realpixl = realSrc[x, y] - greyval = float(src[x, y]) - greyval = min(255.0, greyval) - greyval = math.pow( - min(1, float(greyval / 255.0 * 1)), 1.5) * 255.0 * 1 - greyval = max(0, greyval) - alpha = mask[x, y][3] / 255.0 * 1 - - edgeFactor = src[x, y] / 255.0 - noEdge = 1 - edgeFactor - - shadow = min(1, 1 - realpixl[3] / 255.0 - edgeFactor) - noShadow = 1 - shadow - - dst[x, y] = ( - min(255, int((realpixl[0] / 255.0 * 0.4 + 0.6) * targetR * 1.1)), - min(255, int((realpixl[1] / 255.0 * 0.4 + 0.6) * targetG * 1.1)), - min(255, int((realpixl[2] / 255.0 * 0.4 + 0.6) * targetB * 1.1)), - min(255, int(float(realpixl[3]) * (0.6 + 5 * edgeFactor)))) - - - dest.save(outfilename) - - -def roberts_cross(infilename, outfilename): - print("Processing", infilename) - img = Image.open(infilename) - img.load() - img = img.filter(ImageFilter.GaussianBlur(0.5)) - - image = rgb2gray(np.asarray(img, dtype="int32")) - vertical = ndimage.convolve(image, roberts_cross_v) - horizontal = ndimage.convolve(image, roberts_cross_h) - output_image = np.sqrt(np.square(horizontal) + np.square(vertical)) - save_image(output_image, outfilename, img) - - -def generateUiPreview(srcPath, buildingId): - print(srcPath, buildingId) - img = Image.open(srcPath) - img.load() - img.thumbnail((110, 110), Image.ANTIALIAS) - img.save("../res/ui/hud/building_previews/" + buildingId + ".png") - - img = img.convert("LA") - - data = img.load() - for x in range(img.width): - for y in range(img.height): - data[x, y] = (data[x, y][0], int(data[x, y][1] * 0.5)) - - img.save("../res/ui/hud/building_previews/" + buildingId + "_disabled.png") - - -buildings = listdir("buildings") - -for buildingId in buildings: - if "hub" in buildingId: - continue - roberts_cross("buildings/" + buildingId + "", "blueprints/" + buildingId + "") +# Requirements: numpy, scipy, Pillow, +from __future__ import print_function +import sys +import numpy as np +from scipy import ndimage +from PIL import Image, ImageFilter, ImageChops +import math +from os import listdir +from os.path import isdir, isfile + +generate_blueprint_sprite_v = np.array([[0, 0, 0], + [0, 1, 0], + [0, 0, -1]]) + +generate_blueprint_sprite_h = np.array([[0, 0, 0], + [0, 0, 1], + [0, -1, 0]]) + + +def rgb2gray(rgb): + return np.dot(rgb[..., :3], [0.2989, 0.5870, 0.1140]) + +def process_image(data, outfilename, src_image): + img = Image.fromarray(np.asarray( + np.clip(data, 0, 255), dtype="uint8"), "L") + dest = Image.new("RGBA", (img.width, img.height)) + src = img.load() + dst = dest.load() + + realSrc = src_image.load() + mask = src_image.filter(ImageFilter.GaussianBlur(10)).load() + orig = src_image.load() + + # isWire = "wire" in outfilename + isWire = False + + targetR = 104 + targetG = 200 + targetB = 255 + + if isWire: + targetR = 255 + targetG = 104 + targetB = 232 + + for x in range(img.width): + for y in range(img.height): + realpixl = realSrc[x, y] + greyval = float(src[x, y]) + greyval = min(255.0, greyval) + greyval = math.pow( + min(1, float(greyval / 255.0 * 1)), 1.5) * 255.0 * 1 + greyval = max(0, greyval) + alpha = mask[x, y][3] / 255.0 * 1 + + edgeFactor = src[x, y] / 255.0 + noEdge = 1 - edgeFactor + + shadow = min(1, 1 - realpixl[3] / 255.0 - edgeFactor) + noShadow = 1 - shadow + + dst[x, y] = ( + min(255, int((realpixl[0] / 255.0 * 0.4 + 0.6) * targetR * 1.1)), + min(255, int((realpixl[1] / 255.0 * 0.4 + 0.6) * targetG * 1.1)), + min(255, int((realpixl[2] / 255.0 * 0.4 + 0.6) * targetB * 1.1)), + min(255, int(float(realpixl[3]) * (0.6 + 5 * edgeFactor)))) + + + dest.save(outfilename) + + +def generate_blueprint_sprite(infilename, outfilename): + print("Processing", infilename) + img = Image.open(infilename) + img.load() + img = img.filter(ImageFilter.GaussianBlur(0.5)) + + image = rgb2gray(np.asarray(img, dtype="int32")) + vertical = ndimage.convolve(image, generate_blueprint_sprite_v) + horizontal = ndimage.convolve(image, generate_blueprint_sprite_h) + output_image = np.sqrt(np.square(horizontal) + np.square(vertical)) + process_image(output_image, outfilename, img) + + +buildings = listdir("buildings") + +for buildingId in buildings: + if "hub" in buildingId: + continue + if "wire-" in buildingId: + continue + generate_blueprint_sprite("buildings/" + buildingId + "", "blueprints/" + buildingId + "") 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..55aad16c 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/conflict_cross.png b/res_raw/sprites/wires/sets/conflict_cross.png new file mode 100644 index 00000000..3be1e9b9 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..abb02d18 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..c74a0e41 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..d359969b Binary files /dev/null and b/res_raw/sprites/wires/sets/conflict_turn.png differ diff --git a/res_raw/sprites/wires/sets/first_cross.png b/res_raw/sprites/wires/sets/first_cross.png new file mode 100644 index 00000000..5ec6e11b Binary files /dev/null and b/res_raw/sprites/wires/sets/first_cross.png differ diff --git a/res_raw/sprites/wires/sets/first_forward.png b/res_raw/sprites/wires/sets/first_forward.png new file mode 100644 index 00000000..a6e0df71 Binary files /dev/null and b/res_raw/sprites/wires/sets/first_forward.png differ diff --git a/res_raw/sprites/wires/sets/first_split.png b/res_raw/sprites/wires/sets/first_split.png new file mode 100644 index 00000000..f77ff0b8 Binary files /dev/null and b/res_raw/sprites/wires/sets/first_split.png differ diff --git a/res_raw/sprites/wires/sets/first_turn.png b/res_raw/sprites/wires/sets/first_turn.png new file mode 100644 index 00000000..6d005aae Binary files /dev/null and b/res_raw/sprites/wires/sets/first_turn.png differ diff --git a/res_raw/sprites/wires/sets/second_cross.png b/res_raw/sprites/wires/sets/second_cross.png new file mode 100644 index 00000000..7c5008b6 Binary files /dev/null and b/res_raw/sprites/wires/sets/second_cross.png differ diff --git a/res_raw/sprites/wires/sets/second_forward.png b/res_raw/sprites/wires/sets/second_forward.png new file mode 100644 index 00000000..3656acd7 Binary files /dev/null and b/res_raw/sprites/wires/sets/second_forward.png differ diff --git a/res_raw/sprites/wires/sets/second_split.png b/res_raw/sprites/wires/sets/second_split.png new file mode 100644 index 00000000..dd1a51a8 Binary files /dev/null and b/res_raw/sprites/wires/sets/second_split.png differ diff --git a/res_raw/sprites/wires/sets/second_turn.png b/res_raw/sprites/wires/sets/second_turn.png new file mode 100644 index 00000000..b2be4bb6 Binary files /dev/null and b/res_raw/sprites/wires/sets/second_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/adinplay.scss b/src/css/adinplay.scss index c0deca58..79b7542e 100644 --- a/src/css/adinplay.scss +++ b/src/css/adinplay.scss @@ -50,7 +50,6 @@ left: 0; right: 0; bottom: 0; - background: rgba($mainBgColor, 0.9) uiResource("loading.svg") center center / #{D(60px)} no-repeat; @include InlineAnimation(0.2s ease-in-out) { 0% { opacity: 0; @@ -59,6 +58,11 @@ opacity: 1; } } + + & { + /* @load-async */ + background: rgba($mainBgColor, 0.9) uiResource("loading.svg") center center / #{D(60px)} no-repeat; + } } } } diff --git a/src/css/common.scss b/src/css/common.scss index 6a87012e..5b28cd03 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,22 +384,28 @@ 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; - @include S(width, 15px); - @include S(height, 15px); - @include S(margin-top, 1px); - @include S(margin-left, 5px); + @include S(width, 35px); + @include S(height, 35px); display: inline-block; vertical-align: middle; + + & { + /* @load-async */ + background: uiResource("loading.svg") center center / contain no-repeat; + } + } + + @include InlineAnimation(1.5s ease-in-out infinite) { + 50% { + transform: scale(1.2) rotate(160deg); + } } @include DarkThemeOverride { @@ -439,7 +429,6 @@ canvas { .prefab_FeatureComingSoon { position: relative; - &::after { @include S(top, -5px); @include S(left, -5px); @@ -457,9 +446,7 @@ canvas { @include PlainText; text-transform: uppercase; } - opacity: 0.6; - > * { opacity: 0.5 !important; } @@ -468,7 +455,6 @@ canvas { .prefab_InfoIcon { @include S(width, 25px); @include S(height, 25px); - // background: uiResource("icons_small/info.png") center center / contain no-repeat; z-index: 100; opacity: 0.8; cursor: pointer; @@ -484,12 +470,34 @@ 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; + + @include InlineAnimation(1.5s ease-in-out infinite) { + 50% { + transform: scale(1.2) rotate(160deg); + } + } + + & { + /* @load-async */ + background: uiResource("loading.svg") center center / #{D(40px)} no-repeat; + } + } + + .prefab_GameHint { + position: absolute; + @include S(left, 20px); + @include S(right, 20px); + @include S(bottom, 60px); + @include Text; + color: #666; + + @include DarkThemeOverride() { + color: lighten($darkModeGameBackground, 50); + } } .loadingStatus { @@ -498,13 +506,17 @@ canvas { @include S(right, 20px); @include S(bottom, 30px); @include Text; - @include TextShadow3D(#aaa); + @include PlainText; + color: #aaa; + + @include DarkThemeOverride { + color: lighten($darkModeGameBackground, 20); + } display: flex; flex-direction: column; justify-content: center; align-items: center; - > .bar { display: none; @include S(margin-top, 15px); @@ -513,7 +525,6 @@ canvas { position: relative; @include TextShadow3D(#fff); height: 2px; - .inner { position: absolute !important; top: 0; @@ -522,9 +533,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 +549,6 @@ canvas { } } } - .status { display: none; position: relative; @@ -575,11 +583,9 @@ canvas { &.loading { opacity: 0.2; } - &:hover { background-color: darken($bgColor, 5); } - .knob { @include S(width, 20px); @include S(height, 17px); @@ -590,18 +596,76 @@ 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); } } + + @include DarkThemeOverride { + background-color: $darkModeGameBackground !important; + &.checked { + background-color: $colorBlueBright !important; + } + } +} + +.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); + } + + @include DarkThemeOverride { + &::-webkit-slider-runnable-track { + background-color: $darkModeControlsBackground; + } + + &::-webkit-slider-thumb { + box-shadow: inset 0 0 0 D(10px) #eee; + } + } + + &::-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 { @@ -618,7 +682,6 @@ canvas { text-shadow: none !important; // font-family: Arial, sans-serif !important; } - font-weight: bold; color: $accentColorDark; text-align: center; @@ -634,7 +697,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 +709,6 @@ canvas { .xpaystation-widget-lightbox-overlay { background: rgba($mainBgColor, 0.94); } - &, iframe { pointer-events: all; @@ -660,7 +721,7 @@ iframe { user-select: all; } -// Steam overlay fiy +// Steam overlay fix #steamOverlayCanvasFix { position: fixed; top: 0px; @@ -688,9 +749,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 deleted file mode 100644 index a0967656..00000000 --- a/src/css/icons.scss +++ /dev/null @@ -1,38 +0,0 @@ -$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; - } -} diff --git a/src/css/ingame_hud/beta_overlay.scss b/src/css/ingame_hud/beta_overlay.scss index 816cddb2..caadd127 100644 --- a/src/css/ingame_hud/beta_overlay.scss +++ b/src/css/ingame_hud/beta_overlay.scss @@ -1,8 +1,24 @@ #ingame_HUD_BetaOverlay { position: fixed; @include S(top, 10px); - @include S(right, 15px); + left: 50%; + transform: translateX(-50%); color: $colorRedBright; @include Heading; text-transform: uppercase; + + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + + h2 { + @include PlainText; + } + + span { + color: #555; + @include SuperSmallText; + } } diff --git a/src/css/ingame_hud/blueprint_placer.scss b/src/css/ingame_hud/blueprint_placer.scss index e1cf06ef..36d1cdad 100644 --- a/src/css/ingame_hud/blueprint_placer.scss +++ b/src/css/ingame_hud/blueprint_placer.scss @@ -1,39 +1,40 @@ -#ingame_HUD_BlueprintPlacer { - position: absolute; - @include S(top, 50px); - left: 50%; - transform: translateX(-50%); - color: #333; - z-index: 9999; - background: $ingameHudBg; - @include S(padding, 5px); - display: flex; - flex-direction: column; - color: #fff; - @include S(width, 120px); - align-items: center; - justify-content: center; - - .label { - @include PlainText; - text-transform: uppercase; - } - .costContainer { - display: flex; - align-items: center; - @include Heading; - - > canvas { - @include S(margin-left, 5px); - @include S(width, 30px); - @include S(height, 30px); - } - } - - &:not(.canAfford) { - background: rgba(98, 27, 41, 0.8); - // .costContainer { - color: rgb(255, 97, 128); - // } - } -} +#ingame_HUD_BlueprintPlacer { + position: absolute; + @include S(top, 70px); + left: 50%; + transform: translateX(-50%); + color: #333; + z-index: 9999; + background: $ingameHudBg; + @include S(padding, 5px); + display: flex; + flex-direction: column; + color: #fff; + @include S(width, 120px); + align-items: center; + justify-content: center; + @include S(border-radius, $globalBorderRadius); + + .label { + @include PlainText; + text-transform: uppercase; + } + .costContainer { + display: flex; + align-items: center; + @include Heading; + + > canvas { + @include S(margin-left, 5px); + @include S(width, 30px); + @include S(height, 30px); + } + } + + &:not(.canAfford) { + background: rgba(98, 27, 41, 0.8); + // .costContainer { + color: rgb(255, 97, 128); + // } + } +} 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..54205d64 100644 --- a/src/css/ingame_hud/buildings_toolbar.scss +++ b/src/css/ingame_hud/buildings_toolbar.scss @@ -1,81 +1,114 @@ -.ingame_buildingsToolbar { - position: fixed; - @include S(bottom, 0px); - left: 50%; - transform: translateX(-50%); - - display: flex; - flex-direction: column; - background-color: rgb(255, 255, 255); - background: transparent; - border-bottom-width: 0; - transition: transform 0.12s ease-in-out; - - background: rgba(mix(#ddd, $colorBlueBright, 90%), 0.75); - - @include DarkThemeOverride { - background: #222428; - } - - &:not(.visible) { - transform: translateX(-50%) translateY(#{D(100px)}); - } - - .buildings { - display: grid; - grid-auto-flow: column; - @include S(margin-bottom, 2px); - - .building { - color: $accentColorDark; - display: flex; - flex-direction: column; - position: relative; - align-items: center; - justify-content: center; - @include S(padding, 5px); - @include S(padding-bottom, 1px); - @include S(width, 35px); - @include S(height, 40px); - - background: center center / 70% no-repeat; - - &:not(.unlocked) { - @include S(width, 20px); - opacity: 0.15; - background-image: none !important; - - &::before { - content: " "; - background: uiResource("locked_building.png") center center / #{D(20px)} #{D(20px)} - no-repeat; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 4; - } - } - - @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); - cursor: pointer; - } - } - } -} +.ingame_buildingsToolbar { + position: absolute; + @include S(bottom, 5px); + left: 50%; + transform: translateX(-50%); + + display: grid; + grid-template-rows: auto auto; + justify-items: center; + + background: transparent; + transition: transform 120ms ease-in-out; + will-change: transform; + + &:not(.visible) { + transform: translateX(-50%) translateY(#{D(100px)}); + } + + .buildings { + display: grid; + grid-auto-flow: column; + justify-items: center; + align-self: center; + grid-row: 2 / 3; + + background-color: rgba(240, 241, 243, 0.5); + @include S(border-radius, $globalBorderRadius); + + @include DarkThemeOverride { + background-color: rgba(darken($darkModeGameBackground, 15), 0.95); + } + + &.secondary { + grid-row: 1 / 2; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + + .building { + @include S(width, 30px); + @include S(height, 22px); + background-size: 45%; + + &:not(.unlocked) { + &::before { + background-size: #{D(13px)}; + } + } + } + } + + .building { + color: $accentColorDark; + display: flex; + flex-direction: column; + position: relative; + align-items: center; + justify-content: center; + @include S(padding, 5px); + @include S(padding-bottom, 1px); + @include S(width, 35px); + @include S(height, 40px); + + background: center center / 70% no-repeat; + + &:not(.unlocked) { + @include S(width, 20px); + opacity: 0.15; + background-image: none !important; + + &::before { + content: " "; + + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 4; + & { + /* @load-async */ + background: uiResource("locked_building.png") center center / #{D(20px)} #{D(20px)} + no-repeat; + } + } + } + + @include S(border-radius, $globalBorderRadius); + + &.unlocked { + pointer-events: all; + transition: all 50ms ease-in-out; + transition-property: background-color, transform; + + cursor: pointer; + &:hover { + background-color: rgba(30, 40, 90, 0.1); + } + + &.pressed { + transform: scale(0.9) !important; + } + + &.selected { + // transform: scale(1.05); + background-color: rgba(lighten($colorBlueBright, 9), 0.4); + + .keybinding { + color: #111; + } + } + } + } + } +} diff --git a/src/css/ingame_hud/cat_memes.scss b/src/css/ingame_hud/cat_memes.scss new file mode 100644 index 00000000..ddb0ae3f --- /dev/null +++ b/src/css/ingame_hud/cat_memes.scss @@ -0,0 +1,23 @@ +#ingame_HUD_CatMemes { + position: absolute; + @include S(width, 150px); + @include S(height, 150px); + background: transparent center center / contain no-repeat; + + right: 0; + @include S(bottom, 150px); + + & { + /* @load-async */ + background-image: uiResource("res/ui/memes/cat1.png") !important; + } + + @include InlineAnimation(0.5s ease-in-out) { + 0% { + transform: translateX(100%); + } + 100% { + transform: none; + } + } +} diff --git a/src/css/ingame_hud/dialogs.scss b/src/css/ingame_hud/dialogs.scss index d72265e7..ad3f76d0 100644 --- a/src/css/ingame_hud/dialogs.scss +++ b/src/css/ingame_hud/dialogs.scss @@ -1,230 +1,259 @@ -.ingameDialog { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - pointer-events: all; - background: $modalDialogBg; - - display: flex; - align-items: center; - justify-content: center; - - @include InlineAnimation(0.12s ease-in-out) { - 0% { - background-color: transparent; - opacity: 0.5; - } - 100% { - background-color: $modalDialogBg; - } - } - - $darkModeDialogBg: darken($darkModeGameBackground, 10); - - @include DarkThemeOverride { - background: rgba($darkModeDialogBg, 0.9); - @include InlineAnimation(0.12s ease-in-out) { - 0% { - background-color: transparent; - opacity: 0.5; - } - 100% { - background-color: rgba($darkModeDialogBg, 0.9); - } - } - - > .dialogInner.optionChooserDialog .optionParent { - .option { - background: #3d3f42; - - &:hover { - background-color: #424348; - } - - &.active { - background: $colorBlueBright; - color: #fff; - } - } - } - } - - &.visible { - .dialogInner { - opacity: 1; - } - } - - .dialogInner { - transition: opacity 0.2s ease-in-out; - opacity: 0; - } - - &.loadingDialog { - * { - color: #fff; - } - } - - > .dialogInner { - background: #fff; - max-height: calc(100vh - #{D(40px)}); - @include S(border-radius, $globalBorderRadius); - display: flex; - flex-direction: column; - @include S(padding, 12px); - pointer-events: all; - - @include DarkThemeOverride { - background: #333438; - } - - &.optionChooserDialog { - .optionParent { - display: grid; - @include S(grid-gap, 5px); - grid-template-columns: 1fr 1fr; - .option { - pointer-events: all; - cursor: pointer; - @include S(padding, 10px); - background: #eee; - transition: background-color 0.12s ease-in-out; - - &:hover { - background-color: #e7e7e7; - } - - &.active { - background-color: $colorBlueBright; - color: #fff; - } - } - } - } - - > .title { - @include Heading; - margin: 0; - text-transform: uppercase; - display: grid; - align-items: center; - grid-template-columns: 1fr auto; - @include S(margin-bottom, 10px); - - @include DarkThemeInvert(); - > .closeButton { - opacity: 0.7; - @include S(width, 20px); - @include S(height, 20px); - background: uiResource("icons/close.png") center center / 80% no-repeat; - cursor: pointer; - pointer-events: all; - transition: opacity 0.2s ease-in-out; - &:hover { - opacity: 0.4; - } - } - } - - > .content { - @include PlainText; - overflow-y: auto; - pointer-events: all; - @include S(width, 350px); - - @include DarkThemeOverride { - color: #aaa; - } - - a { - color: $colorBlueBright; - } - - strong { - font-weight: bold; - } - - .keybinding { - position: relative; - background: #eee; - @include PlainText; - height: unset; - margin: 1px 0; - } - - input { - background: #eee; - color: #333438; - width: 100%; - - &.errored { - background-color: rgb(250, 206, 206); - } - } - - ul.bucketList { - padding-left: 30px; - - li { - display: list-item; - } - } - } - - > .buttons { - @include S(margin-top, 15px); - display: flex; - justify-content: flex-end; - > button { - @include S(margin-left, 8px); - @include Text; - @include S(min-width, 60px); - @include S(padding, 5px, 15px); - - transition: opacity 0.12s ease-in-out; - &:hover { - opacity: 0.9; - } - - &.good { - background-color: $colorGreenBright; - color: #fff; - } - - &.bad { - background-color: $colorRedBright; - color: #fff; - } - - &.timedButton { - pointer-events: none; - cursor: default; - position: relative; - overflow: hidden; - &::after { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: unset; - z-index: 5; - content: " "; - display: inline-block; - background: rgba(#fff, 0.6); - @include InlineAnimation(5s linear) { - 0% { - width: 100%; - } - 100% { - width: 0%; - } - } - } - } - } - } - } -} +.ingameDialog { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + pointer-events: all; + background: $modalDialogBg; + + display: flex; + align-items: center; + justify-content: center; + + @include InlineAnimation(0.12s ease-in-out) { + 0% { + background-color: transparent; + opacity: 0.5; + } + 100% { + background-color: $modalDialogBg; + } + } + + $darkModeDialogBg: darken($darkModeGameBackground, 5); + + @include DarkThemeOverride { + background: rgba($darkModeDialogBg, 0.9); + @include InlineAnimation(0.12s ease-in-out) { + 0% { + background-color: transparent; + opacity: 0.5; + } + 100% { + background-color: rgba($darkModeDialogBg, 0.9); + } + } + + > .dialogInner.optionChooserDialog .optionParent { + .option { + background: $darkModeControlsBackground; + + &:hover { + background-color: lighten($darkModeControlsBackground, 5); + } + + &.active { + background: $colorBlueBright; + color: #fff; + } + } + } + } + + &.visible { + .dialogInner { + opacity: 1; + } + backdrop-filter: blur(D(3px)); + } + + .dialogInner { + transition: opacity 0.2s ease-in-out; + opacity: 0; + } + + &.loadingDialog { + * { + color: #fff; + } + } + + > .dialogInner { + background: #fff; + max-height: calc(100vh - #{D(40px)}); + @include S(border-radius, $globalBorderRadius); + display: flex; + flex-direction: column; + @include S(padding, 12px); + pointer-events: all; + + @include DarkThemeOverride { + background: darken($darkModeControlsBackground, 5); + } + + &.optionChooserDialog { + .optionParent { + display: grid; + @include S(grid-gap, 5px); + grid-template-columns: 1fr 1fr; + .option { + pointer-events: all; + cursor: pointer; + @include S(padding, 10px); + + background: #eee; + + transition: background-color 0.12s ease-in-out; + + &:hover { + background-color: #e7e7e7; + } + + &.active { + background-color: $colorBlueBright; + color: #fff; + } + } + } + } + + > .title { + @include Heading; + margin: 0; + text-transform: uppercase; + display: grid; + align-items: center; + grid-template-columns: 1fr auto; + @include S(margin-bottom, 10px); + + @include DarkThemeInvert(); + > .closeButton { + opacity: 0.7; + @include S(width, 20px); + @include S(height, 20px); + cursor: pointer; + pointer-events: all; + transition: opacity 0.2s ease-in-out; + &:hover { + opacity: 0.4; + } + & { + /* @load-async */ + background: uiResource("icons/close.png") center center / 80% no-repeat; + } + } + } + + > .content { + @include PlainText; + overflow-y: auto; + pointer-events: all; + @include S(width, 350px); + + @include DarkThemeOverride { + color: #aaa; + } + + a { + color: $colorBlueBright; + } + + strong { + font-weight: bold; + } + + .keybinding { + position: relative; + background: #eee; + @include PlainText; + height: unset; + margin: 1px 0; + } + + input { + background: #eee; + color: #333438; + width: 100%; + + &.errored { + background-color: rgb(250, 206, 206); + } + } + + ul.bucketList { + padding-left: 30px; + + li { + display: list-item; + } + } + + .ingameItemChooser { + @include S(margin, 10px, 0); + display: grid; + @include S(grid-column-gap, 3px); + @include S(grid-row-gap, 5px); + grid-template-columns: repeat(10, 1fr); + align-items: center; + justify-items: center; + + canvas { + pointer-events: all; + @include S(width, 25px); + @include S(height, 25px); + position: relative; + cursor: pointer; + @include IncreasedClickArea(3px); + + &:hover { + opacity: 0.9; + } + } + } + } + + > .buttons { + @include S(margin-top, 15px); + display: flex; + justify-content: flex-end; + > button { + @include S(margin-left, 8px); + @include Text; + @include S(min-width, 60px); + @include S(padding, 5px, 15px); + + transition: opacity 0.12s ease-in-out; + &:hover { + opacity: 0.9; + } + + &.good { + background-color: $colorGreenBright; + color: #fff; + } + + &.bad { + background-color: $colorRedBright; + color: #fff; + } + + &.timedButton { + pointer-events: none; + cursor: default; + position: relative; + overflow: hidden; + &::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: unset; + z-index: 5; + content: " "; + display: inline-block; + background: rgba(#fff, 0.6); + @include InlineAnimation(3s linear) { + 0% { + width: 100%; + } + 100% { + width: 0%; + } + } + } + } + } + } + } +} diff --git a/src/css/ingame_hud/entity_debugger.scss b/src/css/ingame_hud/entity_debugger.scss index 15f03848..4cf7e5e9 100644 --- a/src/css/ingame_hud/entity_debugger.scss +++ b/src/css/ingame_hud/entity_debugger.scss @@ -1,43 +1,79 @@ #ingame_HUD_EntityDebugger { position: absolute; + background: $ingameHudBg; + @include S(padding, 5px); @include S(right, 30px); - @include S(top, 200px); - font-size: 14px; - line-height: 16px; - color: #fff; - background: rgba(0, 10, 20, 0.7); - padding: 10px; + top: 50%; + transform: translateY(-50%); + + @include SuperSmallText; + color: #eee; + display: flex; + flex-direction: column; + + > label { + text-transform: uppercase; + } + + .hint { + color: #aaa; + } + &, * { pointer-events: all; } - .flag { - display: inline-block; - background: #333438; - @include S(padding, 2px); - @include S(margin-right, 2px); - - u { - opacity: 0.5; - } + .propertyTable { + @include S(margin-top, 8px); } - .components { - @include S(margin-top, 4px); + .propertyTable, + .entityComponents, + .entityComponents .object > div { display: grid; - grid-template-columns: 1fr 1fr; - @include S(grid-gap, 3px); - .component { - @include S(padding, 2px); - background: #333; - display: flex; - flex-direction: column; + grid-template-columns: 1fr auto; + @include S(column-gap, 10px); + } - .data { - @include S(width, 150px); - @include S(height, 130px); + .entityComponents { + grid-column: 1 / 3; + @include S(margin-top, 5px); + + font-family: "Roboto Mono", "Fira Code", monospace; + font-size: 90%; + @include S(letter-spacing, -0.5px); + + label, + span { + line-height: 1.5em; + + &:not(span) { + opacity: 0.5; + } + } + &, + * { + @include SuperSmallText; + @include S(font-size, 7px, $important: true); + @include S(line-height, 12px, $important: true); + } + + .object { + grid-column: 1 / 3; + line-height: 1.5em; + + > summary { + transition: opacity 0.1s ease-in-out; + cursor: pointer; + &:hover { + opacity: 0.8; + } + } + > div { + @include S(margin-left, 4px); + cursor: pointer; } } } diff --git a/src/css/ingame_hud/game_menu.scss b/src/css/ingame_hud/game_menu.scss index 41ea600f..c95626f1 100644 --- a/src/css/ingame_hud/game_menu.scss +++ b/src/css/ingame_hud/game_menu.scss @@ -1,159 +1,141 @@ -#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; + @include S(top, 10px); + @include S(right, 10px); + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + @include S(grid-gap, 6px); + + backdrop-filter: blur(D(1px)); + + > button, + > .button { + @include PlainText; + @include IncreasedClickArea(0px); + background: green; + @include S(width, 30px); + @include S(height, 30px); + + pointer-events: all; + cursor: pointer; + position: relative; + transition: all 0.12s ease-in-out; + transition-property: opacity, transform; + + display: inline-flex; + background: center center / 70% no-repeat; + grid-row: 1; + + &.pressed { + transform: scale(0.9) !important; + } + + opacity: 0.7; + &:hover { + opacity: 0.9 !important; + } + + @include DarkThemeInvert; + + &.shop { + grid-column: 1; + & { + /* @load-async */ + background-image: uiResource("icons/shop.png"); + } + } + + &.stats { + grid-column: 2; + & { + /* @load-async */ + background-image: uiResource("icons/statistics.png"); + } + } + + &.save { + & { + /* @load-async */ + background-image: uiResource("icons/save.png"); + } + grid-column: 3; + @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); + } + } + + &.saving { + @include InlineAnimation(0.4s ease-in-out infinite) { + 50% { + opacity: 0.5; + transform: scale(0.8); + } + } + pointer-events: none; + cursor: default; + } + } + + &.settings { + grid-column: 4; + & { + /* @load-async */ + background-image: uiResource("icons/settings_menu_settings.png"); + } + } + + &:hover { + opacity: 0.9; + transform: translateY(0); + } + + &:not(.hasBadge) .badge { + display: none; + } + + &.hasBadge { + &.shop { + filter: none; + opacity: 0.9; + + & { + /* @load-async */ + background-image: uiResource("icons/shop_active.png"); + } + } + + transform-origin: 50% 50%; + @include InlineAnimation(0.8s ease-in-out infinite) { + 50% { + transform: scale(1.3) rotate(6deg); + } + } + + .badge { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + @include PlainText; + display: flex; + justify-content: center; + align-items: center; + } + } + } +} diff --git a/src/css/ingame_hud/interactive_tutorial.scss b/src/css/ingame_hud/interactive_tutorial.scss index d4fb58e1..45750b04 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; @@ -44,7 +56,9 @@ .helperGif { @include S(margin-top, 5px); + @include S(width, 150px); @include S(height, 150px); - background: center center / contain no-repeat; + background: center center / cover 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..b44dde4b 100644 --- a/src/css/ingame_hud/keybindings_overlay.scss +++ b/src/css/ingame_hud/keybindings_overlay.scss @@ -1,68 +1,76 @@ -#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(1px)); + 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 { + /* @load-async */ + background: #fff uiResource("icons/mouse_right.png") center center / 85% no-repeat; + } + + &.leftMouse { + /* @load-async */ + 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..671f5aa5 100644 --- a/src/css/ingame_hud/pinned_shapes.scss +++ b/src/css/ingame_hud/pinned_shapes.scss @@ -1,135 +1,135 @@ -#ingame_HUD_PinnedShapes { - position: absolute; - @include S(left, 9px); - @include S(top, 150px); - @include PlainText; - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: flex-start; - - > .shape { - position: relative; - display: grid; - align-items: center; - justify-content: center; - grid-template-columns: auto 1fr; - grid-template-rows: 1fr 1fr; - @include S(margin-bottom, 4px); - color: #333438; - // text-shadow: #{D(1px)} #{D(1px)} 0 rgba(0, 10, 20, 0.2); - - &.unpinable { - > canvas { - cursor: pointer; - pointer-events: all; - } - } - - > canvas { - @include S(width, 25px); - @include S(height, 25px); - grid-column: 1 / 2; - grid-row: 1 / 3; - pointer-events: all; - transition: transform 0.1s ease-in-out; - position: relative; - z-index: 20; - &:hover { - transform: scale(2) translateX(#{D(5px)}); - z-index: 21; - } - } - - > .amountLabel, - > .goalLabel { - @include S(margin-left, 5px); - @include SuperSmallText; - font-weight: bold; - display: inline-flex; - align-items: center; - flex-direction: row; - grid-column: 2 / 3; - @include S(height, 9px); - - @include DarkThemeOverride { - color: #eee; - } - } - - > .goalLabel { - @include S(font-size, 7px); - opacity: 0.9; - align-self: start; - justify-self: start; - font-weight: normal; - grid-row: 2 / 3; - } - - > .amountLabel { - align-self: end; - justify-self: start; - grid-row: 1 / 2; - } - - > .infoButton { - @include S(width, 8px); - @include S(height, 8px); - background: uiResource("icons/info_button.png") center center / 95% no-repeat; - position: absolute; - opacity: 0.7; - @include S(top, 13px); - @include S(left, -7px); - @include DarkThemeInvert; - @include IncreasedClickArea(2px); - transition: opacity 0.12s ease-in-out; - z-index: 100; - - &:hover { - opacity: 0.8; - } - } - - &.goal, - &.blueprint { - .amountLabel::after { - content: " "; - position: absolute; - display: inline-block; - @include S(width, 8px); - @include S(height, 8px); - @include S(top, 4px); - @include S(left, -7px); - background: center center / contain no-repeat; - } - - &.goal .amountLabel { - &::after { - background-image: uiResource("icons/current_goal_marker.png"); - background-size: 90%; - } - @include DarkThemeOverride { - &::after { - background-image: uiResource("icons/current_goal_marker_inverted.png") !important; - } - } - } - - &.blueprint .amountLabel { - &::after { - background-image: uiResource("icons/blueprint_marker.png"); - background-size: 90%; - } - @include DarkThemeOverride { - &::after { - background-image: uiResource("icons/blueprint_marker_inverted.png") !important; - } - } - } - } - - &.completed { - opacity: 0.5; - } - } -} +#ingame_HUD_PinnedShapes { + position: absolute; + @include S(left, 9px); + @include S(top, 150px); + @include PlainText; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + + > .shape { + position: relative; + display: grid; + align-items: center; + justify-content: center; + grid-template-columns: auto 1fr; + grid-template-rows: 1fr 1fr; + @include S(margin-bottom, 4px); + color: #333438; + + &.removable { + cursor: pointer; + pointer-events: all; + } + + > canvas { + @include S(width, 25px); + @include S(height, 25px); + grid-column: 1 / 2; + grid-row: 1 / 3; + pointer-events: none; + z-index: 20; + position: relative; + } + + > .amountLabel, + > .goalLabel { + @include S(margin-left, 5px); + @include SuperSmallText; + font-weight: bold; + display: inline-flex; + align-items: center; + flex-direction: row; + grid-column: 2 / 3; + @include S(height, 9px); + + @include DarkThemeOverride { + color: #eee; + } + } + + > .goalLabel { + @include S(font-size, 7px); + opacity: 0.9; + align-self: start; + justify-self: start; + font-weight: normal; + grid-row: 2 / 3; + } + + > .amountLabel { + align-self: end; + justify-self: start; + grid-row: 1 / 2; + } + + > .infoButton { + @include S(width, 8px); + @include S(height, 8px); + position: absolute; + opacity: 0.7; + @include S(top, 13px); + @include S(left, -7px); + @include DarkThemeInvert; + @include IncreasedClickArea(2px); + transition: opacity 0.12s ease-in-out; + z-index: 100; + + &:hover { + opacity: 0.8; + } + + & { + /* @load-async */ + background: uiResource("icons/info_button.png") center center / 95% no-repeat; + } + } + + &.goal, + &.blueprint { + .amountLabel::after { + content: " "; + position: absolute; + display: inline-block; + @include S(width, 8px); + @include S(height, 8px); + @include S(top, 4px); + @include S(left, -7px); + background: center center / contain no-repeat; + } + + &.goal .amountLabel { + &::after { + /* @load-async */ + background-image: uiResource("icons/current_goal_marker.png"); + background-size: 90%; + } + @include DarkThemeOverride { + &::after { + /* @load-async */ + background-image: uiResource("icons/current_goal_marker_inverted.png") !important; + } + } + } + + &.blueprint .amountLabel { + &::after { + /* @load-async */ + background-image: uiResource("icons/blueprint_marker.png"); + background-size: 90%; + } + @include DarkThemeOverride { + &::after { + /* @load-async */ + background-image: uiResource("icons/blueprint_marker_inverted.png") !important; + } + } + } + } + + &.completed { + opacity: 0.5; + } + } +} diff --git a/src/css/ingame_hud/sandbox_controller.scss b/src/css/ingame_hud/sandbox_controller.scss index 0202f5ef..e4680fe4 100644 --- a/src/css/ingame_hud/sandbox_controller.scss +++ b/src/css/ingame_hud/sandbox_controller.scss @@ -1,50 +1,50 @@ -#ingame_HUD_SandboxController { - position: absolute; - background: $ingameHudBg; - @include S(padding, 5px); - @include S(bottom, 10px); - @include S(left, 10px); - - @include SuperSmallText; - color: #eee; - display: flex; - flex-direction: column; - - > label { - text-transform: uppercase; - } - - .hint { - color: #aaa; - } - - .plusMinus { - @include S(margin-top, 4px); - display: grid; - grid-template-columns: 1fr auto auto; - align-items: center; - @include S(grid-gap, 4px); - - button { - @include PlainText; - @include S(padding, 0); - display: flex; - align-items: center; - justify-content: center; - @include S(width, 15px); - @include S(height, 15px); - @include IncreasedClickArea(0px); - } - } - - .additionalOptions { - display: flex; - flex-direction: column; - @include S(margin-top, 10px); - button { - @include S(margin-bottom, 2px); - @include IncreasedClickArea(0px); - @include SuperSmallText; - } - } -} +#ingame_HUD_SandboxController { + position: absolute; + background: $ingameHudBg; + @include S(padding, 5px); + @include S(bottom, 10px); + @include S(left, 10px); + + @include SuperSmallText; + color: #eee; + display: flex; + flex-direction: column; + + > label { + text-transform: uppercase; + } + + .sandboxHint { + color: #aaa; + } + + .plusMinus { + @include S(margin-top, 4px); + display: grid; + grid-template-columns: 1fr auto auto; + align-items: center; + @include S(grid-gap, 4px); + + button { + @include PlainText; + @include S(padding, 0); + display: flex; + align-items: center; + justify-content: center; + @include S(width, 15px); + @include S(height, 15px); + @include IncreasedClickArea(0px); + } + } + + .additionalOptions { + display: flex; + flex-direction: column; + @include S(margin-top, 10px); + button { + @include S(margin-bottom, 2px); + @include IncreasedClickArea(0px); + @include SuperSmallText; + } + } +} diff --git a/src/css/ingame_hud/settings_menu.scss b/src/css/ingame_hud/settings_menu.scss index e0cec1f6..55d5a9e4 100644 --- a/src/css/ingame_hud/settings_menu.scss +++ b/src/css/ingame_hud/settings_menu.scss @@ -1,41 +1,67 @@ -#ingame_HUD_SettingsMenu { - .statsElement { - position: absolute; - @include S(left, 30px); - @include S(top, 30px); - color: #fff; - display: flex; - grid-template-rows: 1fr auto; - flex-direction: column; - - strong { - text-transform: uppercase; - @include PlainText; - opacity: 0.5; - } - - span { - @include S(margin-bottom, 25px); - @include Heading; - } - } - - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - - .buttons { - display: grid; - grid-auto-flow: row; - @include S(grid-gap, 10px); - background: rgba(0, 10, 20, 0.1); - @include S(padding, 10px); - @include S(border-radius, $globalBorderRadius); - - button { - background-color: #eee; - color: #55585a; - } - } -} +#ingame_HUD_SettingsMenu { + .statsElement { + position: absolute; + @include S(left, 30px); + @include S(right, 30px); + @include S(bottom, 30px); + color: #fff; + display: grid; + grid-template-rows: auto auto; + grid-auto-columns: 1fr; + align-items: center; + justify-items: center; + + strong { + text-transform: uppercase; + @include PlainText; + opacity: 0.5; + grid-row: 1; + } + + span { + @include Heading; + grid-row: 2; + } + } + + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + + .buttons { + display: grid; + grid-auto-flow: column; + @include S(grid-gap, 50px); + @include S(margin-top, -10px); + + button { + background: transparent; + filter: invert(1); + + content: ""; + opacity: 0.8; + @include S(width, 35px); + @include S(height, 35px); + + &.settings { + /* @load-async */ + background-image: uiResource("icons/settings_menu_settings.png"); + } + + &.menu { + /* @load-async */ + background-image: uiResource("icons/settings_menu_exit.png"); + } + + &:hover { + opacity: 0.6; + } + + & { + /* @load-async */ + background: uiResource("icons/settings_menu_play.png") center top / contain no-repeat; + } + } + } +} diff --git a/src/css/ingame_hud/shape_viewer.scss b/src/css/ingame_hud/shape_viewer.scss index 65491a5a..9ece9f35 100644 --- a/src/css/ingame_hud/shape_viewer.scss +++ b/src/css/ingame_hud/shape_viewer.scss @@ -1,161 +1,154 @@ -#ingame_HUD_ShapeViewer { - $dims: 170px; - - .content { - display: flex; - @include S(width, $dims); - width: 100%; - flex-direction: column; - overflow-x: hidden; - - &[data-layers="3"], - &[data-layers="4"] { - @include S(width, 2 * $dims); - .renderArea { - display: grid; - grid-template-columns: 1fr 1fr; - @include S(grid-row-gap, 15px); - } - } - - .renderArea { - display: grid; - width: 100%; - @include S(grid-row-gap, 10px); - align-items: center; - justify-items: center; - } - - .infoArea { - align-self: flex-end; - @include S(margin-top, 10px); - display: flex; - flex-direction: column; - overflow: hidden; - - button { - @include S(margin, 0); - @include PlainText; - } - } - - .seperator { - display: flex; - align-items: center; - justify-content: center; - width: 100%; - } - - .layer { - position: relative; - background: #eee; - - @include DarkThemeOverride { - background: rgba(0, 10, 20, 0.2); - } - @include S(width, 150px); - @include S(height, 100px); - display: flex; - align-items: center; - justify-content: center; - - > canvas { - @include S(width, 50px); - @include S(height, 50px); - } - - .quad { - position: absolute; - width: 50%; - height: 50%; - display: flex; - justify-content: center; - align-items: center; - box-sizing: border-box; - - $arrowDims: 23px; - $spacing: 9px; - @include S(padding, 6px); - - .colorLabel { - text-transform: uppercase; - @include SuperSmallText; - @include S(font-size, 9px); - } - - .emptyLabel { - text-transform: uppercase; - @include SuperSmallText; - @include S(font-size, 9px); - } - - &::after { - content: " "; - background: rgba(0, 10, 20, 0.5); - @include S(width, $arrowDims); - @include S(height, 1px); - position: absolute; - transform: rotate(45deg); - transform-origin: 50% 50%; - } - @include DarkThemeOverride { - &::after { - background: rgba(255, 255, 255, 0.5); - } - } - - &.quad-0 { - right: 0; - top: 0; - align-items: flex-start; - justify-content: flex-end; - - &::after { - @include S(left, $spacing); - @include S(bottom, $arrowDims / 2 + $spacing); - transform: rotate(-45deg); - } - } - &.quad-1 { - bottom: 0; - right: 0; - - align-items: flex-end; - justify-content: flex-end; - - &::after { - @include S(left, $spacing); - @include S(top, $arrowDims / 2 + $spacing); - transform: rotate(45deg); - } - } - &.quad-2 { - bottom: 0; - left: 0; - - align-items: flex-end; - justify-content: flex-start; - - &::after { - @include S(right, $spacing); - @include S(top, $arrowDims / 2 + $spacing); - transform: rotate(135deg); - } - } - &.quad-3 { - top: 0; - left: 0; - - align-items: flex-start; - justify-content: flex-start; - - &::after { - @include S(right, $spacing); - @include S(bottom, $arrowDims / 2 + $spacing); - transform: rotate(225deg); - } - } - } - } - } -} +#ingame_HUD_ShapeViewer { + $dims: 170px; + + .content { + display: flex; + @include S(width, $dims); + width: 100%; + flex-direction: column; + overflow-x: hidden; + + &[data-layers="3"], + &[data-layers="4"] { + @include S(width, 2 * $dims); + .renderArea { + display: grid; + grid-template-columns: 1fr 1fr; + @include S(grid-row-gap, 15px); + } + } + + .renderArea { + display: grid; + width: 100%; + @include S(grid-row-gap, 10px); + align-items: center; + justify-items: center; + } + + .infoArea { + align-self: flex-end; + @include S(margin-top, 10px); + display: flex; + flex-direction: column; + overflow: hidden; + + button { + @include S(margin, 0); + @include PlainText; + } + } + + .layer { + position: relative; + background: #eee; + + @include DarkThemeOverride { + background: rgba(0, 10, 20, 0.2); + } + @include S(width, 150px); + @include S(height, 100px); + display: flex; + align-items: center; + justify-content: center; + + > canvas { + @include S(width, 50px); + @include S(height, 50px); + } + + .quad { + position: absolute; + width: 50%; + height: 50%; + display: flex; + justify-content: center; + align-items: center; + box-sizing: border-box; + + $arrowDims: 23px; + $spacing: 9px; + @include S(padding, 6px); + + .colorLabel { + text-transform: uppercase; + @include SuperSmallText; + @include S(font-size, 9px); + } + + .emptyLabel { + text-transform: uppercase; + @include SuperSmallText; + @include S(font-size, 9px); + } + + &::after { + content: " "; + background: rgba(0, 10, 20, 0.5); + @include S(width, $arrowDims); + @include S(height, 1px); + position: absolute; + transform: rotate(45deg); + transform-origin: 50% 50%; + } + @include DarkThemeOverride { + &::after { + background: rgba(255, 255, 255, 0.5); + } + } + + &.quad-0 { + right: 0; + top: 0; + align-items: flex-start; + justify-content: flex-end; + + &::after { + @include S(left, $spacing); + @include S(bottom, $arrowDims / 2 + $spacing); + transform: rotate(-45deg); + } + } + &.quad-1 { + bottom: 0; + right: 0; + + align-items: flex-end; + justify-content: flex-end; + + &::after { + @include S(left, $spacing); + @include S(top, $arrowDims / 2 + $spacing); + transform: rotate(45deg); + } + } + &.quad-2 { + bottom: 0; + left: 0; + + align-items: flex-end; + justify-content: flex-start; + + &::after { + @include S(right, $spacing); + @include S(top, $arrowDims / 2 + $spacing); + transform: rotate(135deg); + } + } + &.quad-3 { + top: 0; + left: 0; + + align-items: flex-start; + justify-content: flex-start; + + &::after { + @include S(right, $spacing); + @include S(bottom, $arrowDims / 2 + $spacing); + transform: rotate(225deg); + } + } + } + } + } +} diff --git a/src/css/ingame_hud/shop.scss b/src/css/ingame_hud/shop.scss index d8cc8a86..301021e7 100644 --- a/src/css/ingame_hud/shop.scss +++ b/src/css/ingame_hud/shop.scss @@ -1,320 +1,328 @@ -#ingame_HUD_Shop { - .content { - @include S(padding-right, 10px); - display: flex; - flex-direction: column; - @include S(width, 500px); - - .upgrade { - display: grid; - grid-template-columns: auto 1fr auto; - background: #eee; - @include S(border-radius, $globalBorderRadius); - @include S(margin-bottom, 4px); - @include S(padding, 5px, 10px); - @include S(grid-row-gap, 1px); - @include S(height, 85px); - grid-template-rows: #{D(20px)} auto; - - &:last-child { - margin-bottom: 0; - } - - @include DarkThemeOverride { - background: #55585a; - } - - .title { - grid-column: 1 / 3; - grid-row: 1 / 2; - @include PlainText; - display: flex; - align-items: center; - flex-direction: row-reverse; - justify-content: flex-end; - - @include DarkThemeOverride { - color: #fff; - } - - .tier { - @include S(margin-right, 9px); - background: $colorGreenBright; - @include S(border-radius, $globalBorderRadius); - text-transform: uppercase; - @include PlainText; - color: #fff; - text-align: center; - font-weight: bold; - @include S(min-width, 50px); - @include S(padding, 0px, 5px); - - &[data-tier="0"] { - background-color: rgb(73, 186, 190); - } - &[data-tier="1"] { - background-color: rgb(88, 110, 207); - } - &[data-tier="2"] { - background-color: rgb(189, 100, 192); - } - &[data-tier="3"] { - background-color: rgb(117, 192, 98); - } - &[data-tier="4"] { - background-color: rgb(243, 77, 48); - } - &[data-tier="5"] { - background-color: rgb(255, 209, 6); - } - &[data-tier="6"] { - background-color: rgb(44, 41, 46); - } - } - } - - .icon { - @include S(width, 40px); - @include S(height, 40px); - background: center center / 80% no-repeat; - align-self: center; - justify-self: center; - grid-column: 1 / 2; - grid-row: 2 / 4; - @include S(margin-right, 30px); - @include S(margin-left, 10px); - opacity: 0.32; - display: none; - } - - .description { - grid-column: 2 / 4; - grid-row: 1 / 2; - @include PlainText; - color: #aaa; - align-self: start; - justify-self: end; - } - - .requirements { - grid-column: 2 / 3; - grid-row: 3 / 4; - display: grid; - grid-auto-flow: column; - @include S(grid-gap, 9px); - justify-content: start; - - .requirement { - position: relative; - display: flex; - flex-direction: column; - align-items: center; - @include S(width, 70px); - overflow: hidden; - - button.pin { - @include S(width, 12px); - @include S(height, 12px); - background: uiResource("icons/pin.png") center center / 95% no-repeat; - position: absolute; - @include S(top, 2px); - @include S(right, 2px); - opacity: 0.6; - cursor: pointer; - pointer-events: all; - @include IncreasedClickArea(5px); - transition: opacity 0.12s ease-in-out; - - @include DarkThemeInvert; - - $disabledOpacity: 0.2; - $enabledOpacity: 0.6; - - &:hover { - opacity: $enabledOpacity + 0.1; - } - - &.alreadyPinned { - opacity: $disabledOpacity !important; - - &:hover { - opacity: $disabledOpacity + 0.1 !important; - } - } - - &.isGoal { - background: uiResource("icons/current_goal_marker.png") center center / 95% - no-repeat; - opacity: $disabledOpacity !important; - cursor: default; - pointer-events: none; - } - - &.pinned { - opacity: $disabledOpacity; - @include InlineAnimation(0.3s ease-in-out) { - 0% { - opacity: 1; - transform: scale(0.8); - } - - 30% { - opacity: 1; - transform: scale(1.2); - } - - 100% { - transform: scale(1); - } - } - &:hover { - opacity: $disabledOpacity + 0.1; - } - } - - &.unpinned { - opacity: $enabledOpacity; - @include InlineAnimation(0.3s ease-in-out) { - 0% { - opacity: 1; - transform: scale(0.8); - } - - 30% { - opacity: 1; - transform: scale(1.2); - } - - 100% { - transform: scale(1); - } - } - &:hover { - opacity: $enabledOpacity + 0.1; - } - } - } - - button.showInfo { - @include S(width, 11px); - @include S(height, 11px); - background: uiResource("icons/info_button.png") center center / 95% no-repeat; - position: absolute; - @include S(top, 17px); - @include S(right, 2.5px); - opacity: 0.5; - cursor: pointer; - pointer-events: all; - @include IncreasedClickArea(5px); - transition: opacity 0.12s ease-in-out; - @include DarkThemeInvert; - - &:hover { - opacity: 0.6; - } - } - - canvas { - @include S(width, 40px); - @include S(height, 40px); - } - - .amount { - @include S(margin-top, 4px); - z-index: 10; - @include SuperSmallText; - letter-spacing: 0; - background: #e2e4e6; - - @include S(line-height, 13px); - @include S(border-radius, $globalBorderRadius); - @include S(padding, 1px, 0px, 2px); - position: relative; - text-align: center; - @include S(min-width, 50px); - // @include S(max-width, 100px); - overflow: hidden; - width: 100%; - - @include DarkThemeOverride { - background: #333438; - color: #fff; - } - - .progressBar { - bottom: 0; - left: 0; - right: 0; - top: 0; - @include S(border-radius, $globalBorderRadius); - position: absolute; - display: inline-block; - z-index: -1; - transition: all 0.2s ease-in-out; - transition-property: width, background-color; - background: #bdbfca; - - @include DarkThemeOverride { - background: #8c8d96; - } - - &.complete { - background-color: $colorGreenBright; - - @include DarkThemeOverride { - background-color: $colorGreenBright; - } - } - } - } - } - } - - button.buy { - grid-column: 3 / 4; - grid-row: 3 / 4; - align-self: center; - justify-self: end; - // @include S(padding, 4px, 5px); - // @include PlainText; - background-color: $colorGreenBright; - color: #fff; - - transition: all 0.2s ease-in-out; - transition-property: background-color, opacity; - - &:not(.buyable) { - background-color: #aaa; - cursor: default; - pointer-events: none; - opacity: 0.3; - } - - &.buyable { - @include InlineAnimation(1s ease-in-out infinite) { - 0% { - } - - 50% { - background-color: lighten($colorGreenBright, 10); - } - 100% { - } - } - } - } - - &.maxLevel { - button.buy { - opacity: 0 !important; - } - .requirements { - display: none; - } - .description { - color: $colorGreenBright; - } - } - } - } -} +#ingame_HUD_Shop { + .content { + @include S(padding-right, 10px); + display: flex; + flex-direction: column; + @include S(width, 500px); + + .upgrade { + display: grid; + grid-template-columns: auto 1fr auto; + background: #eee; + @include S(border-radius, $globalBorderRadius); + @include S(margin-bottom, 4px); + @include S(padding, 5px, 10px); + @include S(grid-row-gap, 1px); + @include S(height, 85px); + grid-template-rows: #{D(20px)} auto; + + &:last-child { + margin-bottom: 0; + } + + @include DarkThemeOverride { + background: $darkModeControlsBackground; + } + + .title { + grid-column: 1 / 3; + grid-row: 1 / 2; + @include PlainText; + display: flex; + align-items: center; + flex-direction: row-reverse; + justify-content: flex-end; + + @include DarkThemeOverride { + color: #fff; + } + + .tier { + @include S(margin-right, 9px); + background: $colorGreenBright; + @include S(border-radius, $globalBorderRadius); + text-transform: uppercase; + @include PlainText; + color: #fff; + text-align: center; + font-weight: bold; + @include S(min-width, 50px); + @include S(padding, 0px, 5px); + + &[data-tier="0"] { + background-color: rgb(73, 186, 190); + } + &[data-tier="1"] { + background-color: rgb(88, 110, 207); + } + &[data-tier="2"] { + background-color: rgb(189, 100, 192); + } + &[data-tier="3"] { + background-color: rgb(117, 192, 98); + } + &[data-tier="4"] { + background-color: rgb(243, 77, 48); + } + &[data-tier="5"] { + background-color: rgb(255, 209, 6); + } + &[data-tier="6"] { + background-color: rgb(44, 41, 46); + } + } + } + + .icon { + @include S(width, 40px); + @include S(height, 40px); + background: center center / 80% no-repeat; + align-self: center; + justify-self: center; + grid-column: 1 / 2; + grid-row: 2 / 4; + @include S(margin-right, 30px); + @include S(margin-left, 10px); + opacity: 0.32; + display: none; + } + + .description { + grid-column: 2 / 4; + grid-row: 1 / 2; + @include PlainText; + color: #aaa; + align-self: start; + justify-self: end; + } + + .requirements { + grid-column: 2 / 3; + grid-row: 3 / 4; + display: grid; + grid-auto-flow: column; + @include S(grid-gap, 9px); + justify-content: start; + + .requirement { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + @include S(width, 70px); + overflow: hidden; + + button.pin { + & { + /* @load-async */ + background: uiResource("icons/pin.png") center center / 95% no-repeat; + } + + @include S(width, 12px); + @include S(height, 12px); + position: absolute; + @include S(top, 2px); + @include S(right, 2px); + opacity: 0.6; + cursor: pointer; + pointer-events: all; + @include IncreasedClickArea(5px); + transition: opacity 0.12s ease-in-out; + + @include DarkThemeInvert; + + $disabledOpacity: 0.2; + $enabledOpacity: 0.6; + + &:hover { + opacity: $enabledOpacity + 0.1; + } + + &.alreadyPinned { + opacity: $disabledOpacity !important; + + &:hover { + opacity: $disabledOpacity + 0.1 !important; + } + } + + &.isGoal { + /* @load-async */ + background: uiResource("icons/current_goal_marker.png") center center / 95% + no-repeat; + opacity: $disabledOpacity !important; + cursor: default; + pointer-events: none; + } + + &.pinned { + opacity: $disabledOpacity; + @include InlineAnimation(0.3s ease-in-out) { + 0% { + opacity: 1; + transform: scale(0.8); + } + + 30% { + opacity: 1; + transform: scale(1.2); + } + + 100% { + transform: scale(1); + } + } + &:hover { + opacity: $disabledOpacity + 0.1; + } + } + + &.unpinned { + opacity: $enabledOpacity; + @include InlineAnimation(0.3s ease-in-out) { + 0% { + opacity: 1; + transform: scale(0.8); + } + + 30% { + opacity: 1; + transform: scale(1.2); + } + + 100% { + transform: scale(1); + } + } + &:hover { + opacity: $enabledOpacity + 0.1; + } + } + } + + button.showInfo { + @include S(width, 11px); + @include S(height, 11px); + position: absolute; + @include S(top, 17px); + @include S(right, 2.5px); + opacity: 0.5; + cursor: pointer; + pointer-events: all; + @include IncreasedClickArea(5px); + transition: opacity 0.12s ease-in-out; + @include DarkThemeInvert; + + &:hover { + opacity: 0.6; + } + } + button.showInfo { + /* @load-async */ + background: uiResource("icons/info_button.png") center center / 95% no-repeat; + } + + canvas { + @include S(width, 40px); + @include S(height, 40px); + } + + .amount { + @include S(margin-top, 4px); + z-index: 10; + @include SuperSmallText; + letter-spacing: 0; + background: #e2e4e6; + + @include S(line-height, 13px); + @include S(border-radius, $globalBorderRadius); + @include S(padding, 1px, 0px, 2px); + position: relative; + text-align: center; + @include S(min-width, 50px); + // @include S(max-width, 100px); + overflow: hidden; + width: 100%; + + @include DarkThemeOverride { + background: #333438; + color: #fff; + } + + .progressBar { + bottom: 0; + left: 0; + right: 0; + top: 0; + @include S(border-radius, $globalBorderRadius); + position: absolute; + display: inline-block; + z-index: -1; + transition: all 0.2s ease-in-out; + transition-property: width, background-color; + background: #bdbfca; + + @include DarkThemeOverride { + background: #8c8d96; + } + + &.complete { + background-color: $colorGreenBright; + + @include DarkThemeOverride { + background-color: $colorGreenBright; + } + } + } + } + } + } + + button.buy { + grid-column: 3 / 4; + grid-row: 3 / 4; + align-self: center; + justify-self: end; + // @include S(padding, 4px, 5px); + // @include PlainText; + background-color: $colorGreenBright; + color: #fff; + + transition: all 0.2s ease-in-out; + transition-property: background-color, opacity; + + &:not(.buyable) { + background-color: #aaa; + cursor: default; + pointer-events: none; + opacity: 0.3; + } + + &.buyable { + @include InlineAnimation(1s ease-in-out infinite) { + 0% { + } + + 50% { + background-color: lighten($colorGreenBright, 10); + } + 100% { + } + } + } + } + + &.maxLevel { + button.buy { + opacity: 0 !important; + } + .requirements { + display: none; + } + .description { + color: $colorGreenBright; + } + } + } + } +} diff --git a/src/css/ingame_hud/standalone_advantages.scss b/src/css/ingame_hud/standalone_advantages.scss new file mode 100644 index 00000000..065ad6ac --- /dev/null +++ b/src/css/ingame_hud/standalone_advantages.scss @@ -0,0 +1,169 @@ +#ingame_HUD_StandaloneAdvantages { + .content { + @include S(width, 440px); + @include S(min-height, 300px); + } + p { + @include PlainText; + } + + .points { + display: grid; + grid-template-columns: 1fr 1fr; + @include S(grid-column-gap, 10px); + @include S(grid-row-gap, 20px); + @include S(margin, 10px, 0, 20px); + grid-template-rows: #{D(40px)}; + align-items: center; + } + + .lowerBar { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + overflow: hidden; + + > button { + transition: opacity 0.12s ease-in-out; + &:hover { + opacity: 0.85; + } + } + + .otherCloseButton { + @include SuperSmallText; + @include S(margin-right, 30px); + color: #aaa; + @include S(margin, 0); + @include IncreasedClickArea(0px); + @include S(margin-top, 15px); + + @include InlineAnimation(5s ease-in-out) { + 0% { + opacity: 0.05; + } + 50% { + opacity: 0.05; + } + 100% { + opacity: 1; + } + } + } + + .steamLinkButton { + @include IncreasedClickArea(5px); + @include S(margin, 0); + @include S(width, 180px); + @include S(height, 40px); + background: #171a23 center center / contain no-repeat; + + @include S(border-radius, $globalBorderRadius); + } + } + + .point { + display: grid; + grid-template-columns: #{D(55px)} auto; + grid-template-rows: 1fr 1fr; + + > strong { + grid-column: 2 / 3; + grid-row: 1 / 2; + @include PlainText; + text-transform: uppercase; + font-weight: bold; + } + + > p { + grid-column: 2 / 3; + grid-row: 2 / 3; + @include SuperSmallText; + opacity: 0.8; + } + + background: transparent #{D(10px)} center / #{D(30px)} no-repeat; + + &.levels { + & { + /* @load-async */ + background-image: uiResource("res/ui/icons/advantage_new_levels.png"); + } + > strong { + color: #f13555; + } + } + + &.upgrades { + & { + /* @load-async */ + background-image: uiResource("res/ui/icons/advantage_upgrades.png"); + } + > strong { + color: #8a00ff; + } + } + + &.buildings { + & { + /* @load-async */ + background-image: uiResource("res/ui/icons/advantage_buildings.png"); + } + > strong { + color: #3fce8b; + } + } + + &.wires { + & { + /* @load-async */ + background-image: uiResource("res/ui/icons/advantage_wires.png"); + } + > strong { + color: #ef2fdb; + } + } + + &.markers { + & { + /* @load-async */ + background-image: uiResource("res/ui/icons/advantage_markers.png"); + } + > strong { + color: #4294ff; + } + } + + &.savegames { + & { + /* @load-async */ + background-image: uiResource("res/ui/icons/advantage_savegames.png"); + } + > strong { + color: #ff9500; + } + } + + &.darkmode { + & { + /* @load-async */ + background-image: uiResource("res/ui/icons/advantage_dark_mode.png"); + } + > strong { + color: #292c32; + } + } + + &.support { + & { + /* @load-async */ + background-image: uiResource("res/ui/icons/advantage_support.png"); + } + > strong { + color: #e72d2d; + } + } + } +} diff --git a/src/css/ingame_hud/statistics.scss b/src/css/ingame_hud/statistics.scss index e53a80d1..cdc428c1 100644 --- a/src/css/ingame_hud/statistics.scss +++ b/src/css/ingame_hud/statistics.scss @@ -14,24 +14,74 @@ @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, + &.displaySorted, + &.displayIterateUnit { + background: transparent center center / #{D(15px)} no-repeat; + } + &.displayDetailed { - 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)}; + /* @load-async */ + background-image: uiResource("icons/display_list.png"); + } + + &.displayIcons { + /* @load-async */ + background-image: uiResource("icons/display_icons.png"); + background-size: #{D(11.5px)}; + } + + &.displayDetailed { + @include S(border-top-left-radius, $globalBorderRadius); + @include S(border-bottom-left-radius, $globalBorderRadius); + } + + &.displaySorted { + & { + /* @load-async */ + background-image: uiResource("icons/display_sorted.png"); } + background-size: #{D(11.5px)}; + margin-right: 5px; + @include S(border-top-right-radius, $globalBorderRadius); + @include S(border-bottom-right-radius, $globalBorderRadius); + + @include S(padding, 1px, 0); + } + + &.displayIterateUnit { + & { + /* @load-async */ + background-image: uiResource("icons/toggle_unit.png"); + } + opacity: 0.8; + @include S(padding, 1px, 0); } background-color: #44484a !important; transition: opacity 0.2s ease-in-out; + + @include DarkThemeOverride { + background-color: lighten($darkModeControlsBackground, 10) !important; + } } .filtersDataSource, @@ -80,10 +130,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 +138,18 @@ margin-bottom: 0; } + &.pinned { + background: #e3e5e9; + } + + @include DarkThemeOverride { + background: $darkModeControlsBackground; + + &.pinned { + background: mix($darkModeControlsBackground, $colorBlueBright, 90%); + } + } + canvas.icon { grid-column: 1 / 2; grid-row: 1 / 2; @@ -100,7 +159,6 @@ .counter { @include SuperSmallText; - @include S(padding, 0, 3px); } } @@ -109,6 +167,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,8 +191,12 @@ .counter { grid-column: 1 / 2; grid-row: 2 / 3; - background: rgba(0, 10, 20, 0.05); justify-self: end; + color: #55595a; + + @include DarkThemeOverride { + color: #aaa; + } } } } @@ -151,6 +214,10 @@ align-self: center; text-align: right; color: #55595a; + + @include DarkThemeOverride { + color: #aaa; + } } canvas.graph { diff --git a/src/css/ingame_hud/tutorial_hints.scss b/src/css/ingame_hud/tutorial_hints.scss index ad1096af..27d85fe1 100644 --- a/src/css/ingame_hud/tutorial_hints.scss +++ b/src/css/ingame_hud/tutorial_hints.scss @@ -1,117 +1,120 @@ -#ingame_HUD_TutorialHints { - position: absolute; - @include S(left, 10px); - @include S(bottom, 10px); - - @include StyleBelowWidth(1430px) { - @include S(bottom, 50px); - } - - display: flex; - flex-direction: column; - background: rgba(50, 60, 70, 0); - - transition: all 0.2s ease-in-out; - pointer-events: all; - - transition-property: background-color, transform, bottom, left; - - @include S(padding, 5px); - video { - transition: all 0.2s ease-in-out; - transition-property: opacity, width; - @include S(width, 0px); - opacity: 0; - z-index: 10; - position: relative; - } - - .header { - color: #333438; - display: grid; - align-items: center; - @include S(grid-gap, 2px); - grid-template-columns: 1fr; - @include S(margin-bottom, 3px); - z-index: 11; - position: relative; - - > span { - @include DarkThemeInvert; - - display: flex; - @include SuperSmallText; - justify-content: flex-start; - align-items: center; - &::before { - @include S(margin-right, 4px); - content: " "; - @include S(width, 12px); - @include S(height, 12px); - display: inline-block; - background: uiResource("icons/help.png") center center / 95% no-repeat; - } - } - - button.toggleHint { - @include PlainText; - @include IncreasedClickArea(0px); - } - } - - button.toggleHint { - .hide { - display: none; - } - } - - &.enlarged { - background: $ingameHudBg; - left: 50%; - bottom: 50%; - transform: translate(-50%, 50%); - - &::before { - pointer-events: all; - content: " "; - position: fixed; - top: -1000px; - left: -1000px; - right: -1000px; - bottom: -1000px; - z-index: 0; - - background: rgba($ingameHudBg, 0.3); - } - - .header { - grid-template-columns: 1fr auto; - > span { - display: none; - } - button.toggleHint { - grid-column: 2 / 3; - } - } - - video { - @include InlineAnimation(0.2s ease-in-out) { - 0% { - opacity: 0; - @include S(width, 0px); - } - } - - opacity: 1; - @include S(width, 500px); - } - button.toggleHint { - .hide { - display: block; - } - .show { - display: none; - } - } - } -} +#ingame_HUD_TutorialHints { + position: absolute; + @include S(left, 10px); + @include S(bottom, 10px); + + @include StyleBelowWidth(1430px) { + @include S(bottom, 50px); + } + + display: flex; + flex-direction: column; + background: rgba(50, 60, 70, 0); + + transition: all 0.2s ease-in-out; + pointer-events: all; + + transition-property: background-color, transform, bottom, left; + + @include S(padding, 5px); + video { + transition: all 0.2s ease-in-out; + transition-property: opacity, width; + @include S(width, 0px); + opacity: 0; + z-index: 10; + position: relative; + } + + .header { + color: #333438; + display: grid; + align-items: center; + @include S(grid-gap, 2px); + grid-template-columns: 1fr; + @include S(margin-bottom, 3px); + z-index: 11; + position: relative; + + > span { + @include DarkThemeInvert; + + display: flex; + @include SuperSmallText; + justify-content: flex-start; + align-items: center; + &::before { + @include S(margin-right, 4px); + content: " "; + @include S(width, 12px); + @include S(height, 12px); + display: inline-block; + & { + /* @load-async */ + background: uiResource("icons/help.png") center center / 95% no-repeat; + } + } + } + + button.toggleHint { + @include PlainText; + @include IncreasedClickArea(0px); + } + } + + button.toggleHint { + .hide { + display: none; + } + } + + &.enlarged { + background: $ingameHudBg; + left: 50%; + bottom: 50%; + transform: translate(-50%, 50%); + + &::before { + pointer-events: all; + content: " "; + position: fixed; + top: -1000px; + left: -1000px; + right: -1000px; + bottom: -1000px; + z-index: 0; + + background: rgba($ingameHudBg, 0.3); + } + + .header { + grid-template-columns: 1fr auto; + > span { + display: none; + } + button.toggleHint { + grid-column: 2 / 3; + } + } + + video { + @include InlineAnimation(0.2s ease-in-out) { + 0% { + opacity: 0; + @include S(width, 0px); + } + } + + opacity: 1; + @include S(width, 500px); + } + button.toggleHint { + .hide { + display: block; + } + .show { + display: none; + } + } + } +} diff --git a/src/css/ingame_hud/unlock_notification.scss b/src/css/ingame_hud/unlock_notification.scss index 56720d7a..828c55a9 100644 --- a/src/css/ingame_hud/unlock_notification.scss +++ b/src/css/ingame_hud/unlock_notification.scss @@ -1,177 +1,178 @@ -#ingame_HUD_UnlockNotification { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: rgba(#333538, 0.98) uiResource("dialog_bg_pattern.png") top left / #{D(10px)} repeat; - display: flex; - justify-content: center; - align-items: center; - pointer-events: all; - - @include InlineAnimation(0.1s ease-in-out) { - 0% { - opacity: 0; - } - } - - .dialog { - // background: rgba(#222428, 0.5); - @include S(border-radius, $globalBorderRadius); - @include S(padding, 30px); - - @include InlineAnimation(0.5s ease-in-out) { - 0% { - opacity: 0; - } - } - display: flex; - align-items: center; - flex-direction: column; - max-height: 100vh; - - color: #fff; - text-align: center; - .title, - .subTitle { - @include SuperHeading; - text-transform: uppercase; - @include S(font-size, 40px); - - @include InlineAnimation(0.5s ease-in-out) { - 0% { - transform: translateY(-50vh); - } - 50% { - transform: translateY(5vh); - } - 75% { - transform: translateY(-2vh); - } - } - } - - .subTitle { - @include PlainText; - display: inline-block; - @include S(margin, 5px, 0, 20px); - color: $colorGreenBright; - - @include S(border-radius, $globalBorderRadius); - @include InlineAnimation(0.5s ease-in-out) { - 0% { - transform: translateY(-60vh); - } - 50% { - transform: translateY(6vh); - } - 75% { - transform: translateY(-3vh); - } - } - } - - .contents { - @include S(width, 400px); - @include InlineAnimation(0.5s ease-in-out) { - 0% { - transform: translateX(-100vw); - } - 50% { - transform: translateX(5vw); - } - - 75% { - transform: translateX(-2vw); - } - } - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - @include S(grid-gap, 10px); - - .rewardName { - grid-column: 1 / 3; - display: none; - @include InlineAnimation(0.5s ease-in-out) { - 0% { - transform: translateX(200vw); - } - 50% { - transform: translateX(-10vw); - } - - 75% { - transform: translateX(4vw); - } - } - } - - .rewardDesc { - grid-column: 1 / 3; - @include PlainText; - @include S(margin-bottom, 15px); - color: #aaacaf; - @include S(width, 400px); - text-align: left; - strong { - color: #fff; - } - } - - .images { - display: flex; - .buildingExplanation { - @include S(width, 200px); - @include S(height, 200px); - display: inline-block; - background-position: center center; - background-size: cover; - background-repeat: no-repeat; - @include S(border-radius, $globalBorderRadius); - box-shadow: #{D(2px)} #{D(3px)} 0 0 rgba(0, 0, 0, 0.15); - } - } - } - - button.close { - border: 0; - position: relative; - @include S(margin-top, 30px); - - &:not(.unlocked) { - pointer-events: none; - opacity: 0.8; - cursor: default; - } - - &.unlocked { - &::after { - animation: none !important; - } - } - - &::after { - content: " "; - display: inline-block; - position: absolute; - top: 0; - left: 100%; - right: 0; - bottom: 0; - background: rgba(0, 10, 20, 0.8); - - @include InlineAnimation(5s linear) { - 0% { - left: 0; - } - 100% { - left: 100%; - } - } - } - } - } -} +#ingame_HUD_UnlockNotification { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + overflow: auto; + pointer-events: all; + + & { + /* @load-async */ + background: rgba(#333538, 0.98) uiResource("dialog_bg_pattern.png") top left / #{D(10px)} repeat; + } + + @include InlineAnimation(0.1s ease-in-out) { + 0% { + opacity: 0; + } + } + + .dialog { + // background: rgba(#222428, 0.5); + @include S(border-radius, $globalBorderRadius); + @include S(padding, 30px); + + @include InlineAnimation(0.5s ease-in-out) { + 0% { + opacity: 0; + } + } + display: flex; + align-items: center; + flex-direction: column; + + color: #fff; + text-align: center; + .title, + .subTitle { + @include SuperHeading; + text-transform: uppercase; + @include S(font-size, 40px); + + @include InlineAnimation(0.5s ease-in-out) { + 0% { + transform: translateY(-50vh); + } + 50% { + transform: translateY(5vh); + } + 75% { + transform: translateY(-2vh); + } + } + } + + .subTitle { + @include PlainText; + display: inline-block; + @include S(margin, 5px, 0, 20px); + color: $colorGreenBright; + + @include S(border-radius, $globalBorderRadius); + @include InlineAnimation(0.5s ease-in-out) { + 0% { + transform: translateY(-60vh); + } + 50% { + transform: translateY(6vh); + } + 75% { + transform: translateY(-3vh); + } + } + } + + .contents { + @include S(width, 400px); + @include InlineAnimation(0.5s ease-in-out) { + 0% { + transform: translateX(-100vw); + } + 50% { + transform: translateX(5vw); + } + + 75% { + transform: translateX(-2vw); + } + } + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + @include S(grid-gap, 10px); + + .rewardName { + grid-column: 1 / 3; + display: none; + @include InlineAnimation(0.5s ease-in-out) { + 0% { + transform: translateX(200vw); + } + 50% { + transform: translateX(-10vw); + } + + 75% { + transform: translateX(4vw); + } + } + } + + .rewardDesc { + grid-column: 1 / 3; + @include PlainText; + @include S(margin-bottom, 15px); + color: #aaacaf; + @include S(width, 400px); + text-align: left; + strong { + color: #fff; + } + } + + .images { + display: flex; + .buildingExplanation { + @include S(width, 200px); + @include S(height, 200px); + display: inline-block; + background-position: center center; + background-size: cover; + background-repeat: no-repeat; + @include S(border-radius, $globalBorderRadius); + box-shadow: #{D(2px)} #{D(3px)} 0 0 rgba(0, 0, 0, 0.15); + } + } + } + + button.close { + border: 0; + position: relative; + @include S(margin-top, 30px); + + &:not(.unlocked) { + pointer-events: none; + opacity: 0.8; + cursor: default; + } + + &.unlocked { + &::after { + animation: none !important; + } + } + + &::after { + content: " "; + display: inline-block; + position: absolute; + top: 0; + left: 100%; + right: 0; + bottom: 0; + background: rgba(0, 10, 20, 0.8); + + @include InlineAnimation(5s linear) { + 0% { + left: 0; + } + 100% { + left: 100%; + } + } + } + } + } +} diff --git a/src/css/ingame_hud/vignette_overlay.scss b/src/css/ingame_hud/vignette_overlay.scss index ce569fd4..6efe109f 100644 --- a/src/css/ingame_hud/vignette_overlay.scss +++ b/src/css/ingame_hud/vignette_overlay.scss @@ -4,7 +4,10 @@ left: 0; right: 0; bottom: 0; - background: uiResource("vignette.lossless.png") center center / cover no-repeat; + & { + /* @load-async */ + background: uiResource("vignette.lossless.png") center center / cover no-repeat; + } pointer-events: none; @include DarkThemeOverride { diff --git a/src/css/ingame_hud/watermark.scss b/src/css/ingame_hud/watermark.scss index d14a7fc8..76ec224c 100644 --- a/src/css/ingame_hud/watermark.scss +++ b/src/css/ingame_hud/watermark.scss @@ -1,18 +1,85 @@ -#ingame_HUD_Watermark { - position: absolute; - background: uiResource("get_on_steam.png") center center / contain no-repeat; - @include S(width, 110px); - @include S(height, 40px); - @include S(top, 10px); - pointer-events: all; - cursor: pointer; - @include S(left, 160px); - - transition: all 0.12s ease-in; - transition-property: opacity, transform; - transform: skewX(-0.5deg); - &:hover { - transform: skewX(-1deg) scale(1.02); - opacity: 0.9; - } -} +#ingame_HUD_Watermark { + position: absolute; + + @include S(border-radius, $globalBorderRadius); + @include S(top, 70px); + pointer-events: all; + cursor: pointer; + left: 50%; + text-align: center; + + background: rgba(207, 65, 65, 0.8); + color: #fff; + transform: translateX(-50%); + @include PlainText; + @include S(padding, 10px); + + &:hover { + transform: translateX(-50%) scale(1.02) !important; + } + + > strong { + @include PlainText; + text-transform: uppercase; + } + > p { + @include SuperSmallText; + opacity: 0.7; + } + + opacity: 0; + + &.visible { + @include InlineAnimation(0.5s ease-in-out) { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } + } + opacity: 1; + } + + &:not(.visible) { + @include InlineAnimation(0.5s ease-in-out) { + 0% { + opacity: 1; + } + 100% { + opacity: 0; + } + } + } +} + +#ingame_HUD_WatermarkClicker { + @include S(top, 55px); + position: absolute; + left: 50%; + transform: translateX(-50%) !important; + @include SuperSmallText; + color: $colorBlueBright; + text-transform: uppercase; + pointer-events: all; + cursor: pointer; + display: flex; + align-items: center; + + &:hover { + opacity: 0.9; + } + + &::after { + @include S(margin-left, 4px); + content: ""; + @include S(width, 10px); + @include S(height, 10px); + display: inline-flex; + background: center center / contain no-repeat; + & { + /* @load-async */ + background-image: uiResource("res/ui/icons/demo_steam_link_indicator.png"); + } + } +} diff --git a/src/css/ingame_hud/waypoints.scss b/src/css/ingame_hud/waypoints.scss index 7a9941c0..d30c5120 100644 --- a/src/css/ingame_hud/waypoints.scss +++ b/src/css/ingame_hud/waypoints.scss @@ -1,95 +1,115 @@ -#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); + @include S(padding-bottom, 5px); + @include S(padding-top, 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; + & { + /* @load-async */ + 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); + & { + /* @load-async */ + 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..4f6a771e 100644 --- a/src/css/main.scss +++ b/src/css/main.scss @@ -1,124 +1,129 @@ -// 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 "resources"; +@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"; +@import "ingame_hud/standalone_advantages"; +@import "ingame_hud/cat_memes"; + +// 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_TutorialHints, +ingame_HUD_InteractiveTutorial, +ingame_HUD_BuildingsToolbar, +ingame_HUD_wires_toolbar, +ingame_HUD_BlueprintPlacer, +ingame_HUD_Waypoints_Hint, +ingame_HUD_WatermarkClicker, +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_StandaloneAdvantages, +ingame_HUD_UnlockNotification, +ingame_HUD_SettingsMenu, +ingame_HUD_ModalDialogs, +ingame_HUD_CatMemes; + +$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..43f7a259 100644 --- a/src/css/mixins.scss +++ b/src/css/mixins.scss @@ -1,363 +1,316 @@ -// ---------------------------------------- -/* 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); - backface-visibility: hidden; - -webkit-backface-visibility: hidden; -} - -// Helper which includes the translateZ webkit fix, use together with Fast animation -// $hardwareAcc: translateZ(0); -$hardwareAcc: null; - -// ---------------------------------------- -/** Increased click area for this element, helpful on mobile */ -@mixin IncreasedClickArea($size) { - &::after { - content: ""; - position: absolute; - top: #{D(-$size)}; - bottom: #{D(-$size)}; - left: #{D(-$size)}; - right: #{D(-$size)}; - // background: rgba(255, 0, 0, 0.3); - } -} -button, -.increasedClickArea { - position: relative; - @include IncreasedClickArea(15px); -} - -// ---------------------------------------- -/* Duplicates an animation and adds two classes .Even and .Odd which uses the - animation. This can be used to replay the animation by toggling between the classes, because - it is not possible to restart a css animation */ -@mixin MakeAnimationWrappedEvenOdd($duration, $classPrefix: "anim", $childSelector: "") { - $animName: autogen_anim_#{unique-id()}; - - @at-root { - @keyframes #{$animName}_even { - @content; - } - - @keyframes #{$animName}_odd { - @content; - } - } - - &.#{$classPrefix}Even #{$childSelector} { - animation: #{$animName}_even $duration; - } - - &.#{$classPrefix}Odd #{$childSelector} { - animation: #{$animName}_odd $duration; - } -} - -// ---------------------------------------- -/* Allows to use and define an animation without specifying its name */ -@mixin InlineAnimation($duration) { - $animName: autogen_anim_#{unique-id()}; - - @at-root { - @keyframes #{$animName} { - @content; - } - } - - animation: $animName $duration !important; -} - -// ---------------------------------------- -/* Animation prefab for a double bounce pop-in animation, useful for dialogs */ -@mixin DoubleBounceAnim($duration: 0.5s ease-in-out, $amount: 0.2, $initialOpacity: 0) { - @include InlineAnimation($duration) { - 0% { - opacity: $initialOpacity; - transform: scale(0) $hardwareAcc; - } - - 25% { - opacity: 0.5; - transform: scale(1 + $amount) $hardwareAcc; - } - - 50% { - opacity: 1; - transform: scale(1 - $amount * 0.5) $hardwareAcc; - } - - 75% { - transform: scale(1 + $amount * 0.25) $hardwareAcc; - } - - 100% { - transform: scale(1) $hardwareAcc; - } - } - - opacity: 1; -} - -// ---------------------------------------- -/* Define a style which is only applied in horizontal mode */ -@mixin HorizontalStyle { - @include AppendGlobal(".h") { - @content; - } -} - -// ---------------------------------------- -/* Define a style which is only applied in vertical mode */ -@mixin VerticalStyle { - @include AppendGlobal(".v") { - @content; - } -} - -// ---------------------------------------- -/* Define a style which is only while the hardware keyboard is open */ -@mixin AndroidHwKeyboardOpen { - @include AppendGlobal(".kb") { - @content; - } -} - -// ---------------------------------------- -/* Automatically transforms the game state if a hardware keyboard is open */ -@mixin TransformToMatchKeyboard { - transition: transform 0.2s ease-in-out; - @include AndroidHwKeyboardOpen { - @include VerticalStyle { - transform: translateY(#{D(-125px)}) $hardwareAcc; - } - @include HorizontalStyle { - transform: translateY(#{D(-100px)}) $hardwareAcc; - } - } -} - -// ---------------------------------------- -/* Define a style which is only applied when the viewport is at least X pixels wide */ -@mixin StyleAtWidth($minW) { - @media (min-width: #{$minW}) { - @content; - } -} - -// ---------------------------------------- -/* Define a style which is only applied when the viewport is at least X pixels height */ -@mixin StyleAtHeight($minH) { - @media (min-height: #{$minH}) { - @content; - } -} - -// ---------------------------------------- -/* Define a style which is only applied when the viewport has at least the given dimensions */ -@mixin StyleAtDims($minW, $minH) { - @media (min-height: #{$minH}) and (min-width: #{$minW}) { - @content; - } -} - -// ---------------------------------------- -/* Define a style which is only applied when the viewport has at maximum the given dimensions */ -@mixin StyleBelowDims($maxW, $maxH) { - @media (max-height: #{$maxH}) and (max-width: #{$maxW}) { - @content; - } -} - -// ---------------------------------------- -/* Define a style which is only applied when the viewport has at maximum the given height */ -@mixin StyleBelowHeight($maxH) { - @media (max-height: #{$maxH}) { - @content; - } -} -// ---------------------------------------- -/* Define a style which is only applied when the viewport has at maximum the given width */ -@mixin StyleBelowWidth($maxW) { - @media (max-width: #{$maxW}) { - @content; - } -} - -// ---------------------------------------- -// Dynamic graphics quality styles - -@mixin BoxShadow3D($bgColor, $size: 3px, $pressEffect: true) { - background-color: $bgColor; - - $borderSize: 1.5px; - $borderColor: rgb(18, 20, 24); - - // box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($size) 0 0px rgba(mix(darken($bgColor, 9), #b0e2ff, 95%), 1), - // 0 D($size) 0 D($borderSize) $borderColor; - - // box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($size) 0 D($borderSize) $borderColor, - // D(-$size * 1.5) D($size * 2) 0 D($borderSize) rgba(0, 0, 0, 0.1); - - // transition: box-shadow 0.1s ease-in-out; - - // @if $pressEffect { - // &.pressed { - // transform: none !important; - // $pSize: max(0, $size - 1.5px); - // transition: none !important; - // box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($pSize) 0 0px rgba(mix(darken($bgColor, 9), #b0e2ff, 95%), 1), - // 0 D($pSize) 0 D($borderSize) $borderColor; - // top: D($size - $pSize); - // } - // } -} - -@mixin BorderRadius($v1: 2px, $v2: "", $v3: "", $v4: "") { - @include S(border-radius, $v1, $v2, $v3, $v4); -} - -@mixin BoxShadow($x, $y, $blur, $offset, $color) { - box-shadow: D($x) D($y) D($blur) D($offset) $color; -} - -@mixin DropShadow($yOffset: 2px, $blur: 2px, $amount: 0.2) { - @include BoxShadow(0, $yOffset, $blur, 0, rgba(#000, $amount)); -} - -@mixin TextShadow($yOffset: 2px, $blur: 1px, $amount: 0.6) { - text-shadow: 0 D($yOffset) D($blur) rgba(#000, $amount); -} - -@mixin Button3D($bgColor, $pressEffect: true) { - @include BoxShadow3D($bgColor, 2px, $pressEffect); -} - -@mixin ButtonDisabled3D($bgColor) { - @include BoxShadow3D($bgColor, 0.5px, false); -} - -@mixin BoxShadowInset($bgColor, $size: 3px) { - background-color: $bgColor; - - $borderSize: 1px; - $borderColor: rgb(15, 19, 24); - box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($size) 0 rgba(#fff, 0.07); - border-top: D($size) solid rgba(#000, 0.1); - - //, 0 D($size) 0 0px rgba(mix(darken($bgColor, 9), #b0e2ff, 95%), 1), - // 0 D($size + $borderSize) 0 0 $borderColor; -} - -@mixin TextShadow3D($color: rgb(222, 234, 238), $borderColor: #000) { - color: $color; -} - -// ---------------------------------------- -/* Shine animation prefab, useful for buttons etc. Adds a bright shine which moves over - the button like a reflection. Performance heavy. */ -@mixin ShineAnimation($duration, $bgColor, $w: 200px, $shineAlpha: 0.25, $lightenAmount: 7, $bgAnim: true) { - $bgBase: darken($bgColor, 5); - background-color: $bgBase; - - @include HighQualityOrMore { - position: relative; - // overflow: hidden; - // overflow: visible; - - &:before { - content: " "; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: uiResource("misc/shine_bg.png") 0px center / 100% 100% no-repeat; - - @include InlineAnimation($duration ease-in-out infinite) { - 0% { - background-position-x: #{D(-$w)}; - } - 100% { - background-position-x: #{D($w)}; - } - } - } - - @if ($bgAnim) { - @include InlineAnimation($duration ease-in-out infinite) { - 0% { - background-color: $bgBase; - } - 50% { - background-color: lighten($bgBase, $lightenAmount); - } - 100% { - background-color: $bgBase; - } - } - } - } -} - -// ---------------------------------------- -/* String replacement */ -@function str-replace($string, $search, $replace: "") { - $index: str-index($string, $search); - - @if $index { - @return str-slice($string, 1, $index - 1) + $replace + - str-replace(str-slice($string, $index + str-length($search)), $search, $replace); - } - - @return $string; -} - -@mixin BounceInFromSide($mul, $duration: 0.18s ease-in-out) { - @include InlineAnimation($duration) { - 0% { - transform: translateY(#{D(-100px * $mul)}) scale(0.9); - opacity: 0; - } - - 100% { - opacity: 1; - transform: none; - } - } - opacity: 1; - transform: none; -} - -@mixin BreakText { - word-wrap: break-word; - word-break: break-all; - overflow-wrap: break-all; -} - -@mixin SupportsAndroidNotchQuery { - @supports (color: constant(--notch-inset-left)) { - @content; - } -} -@mixin SupportsiOsNotchQuery { - @supports (color: env(safe-area-inset-left, 0px)) { - @content; - } -} - -@mixin DarkThemeOverride { - @at-root html[data-theme="dark"] &, - &[data-theme="dark"] { - @content; - } -} - -@mixin DarkThemeInvert { - @include DarkThemeOverride { - filter: invert(1); - } -} +// ---------------------------------------- +/* 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, filter; + // transform: translateZ(0); + backface-visibility: hidden; + -webkit-backface-visibility: hidden; +} + +// Helper which includes the translateZ webkit fix, use together with Fast animation +// $hardwareAcc: translateZ(0); +$hardwareAcc: null; + +// ---------------------------------------- +/** Increased click area for this element, helpful on mobile */ +@mixin IncreasedClickArea($size) { + &::after { + content: ""; + position: absolute; + top: #{D(-$size)}; + bottom: #{D(-$size)}; + left: #{D(-$size)}; + right: #{D(-$size)}; + // background: rgba(255, 0, 0, 0.3); + } +} +button, +.increasedClickArea { + position: relative; + @include IncreasedClickArea(15px); +} + +// ---------------------------------------- +/* Duplicates an animation and adds two classes .Even and .Odd which uses the + animation. This can be used to replay the animation by toggling between the classes, because + it is not possible to restart a css animation */ +@mixin MakeAnimationWrappedEvenOdd($duration, $classPrefix: "anim", $childSelector: "") { + $animName: autogen_anim_#{unique-id()}; + + @at-root { + @keyframes #{$animName}_even { + @content; + } + + @keyframes #{$animName}_odd { + @content; + } + } + + &.#{$classPrefix}Even #{$childSelector} { + animation: #{$animName}_even $duration; + } + + &.#{$classPrefix}Odd #{$childSelector} { + animation: #{$animName}_odd $duration; + } +} + +// ---------------------------------------- +/* Allows to use and define an animation without specifying its name */ +@mixin InlineAnimation($duration) { + $animName: autogen_anim_#{unique-id()}; + + @at-root { + @keyframes #{$animName} { + @content; + } + } + + animation: $animName $duration !important; +} + +// ---------------------------------------- +/* Animation prefab for a double bounce pop-in animation, useful for dialogs */ +@mixin DoubleBounceAnim($duration: 0.5s ease-in-out, $amount: 0.2, $initialOpacity: 0) { + @include InlineAnimation($duration) { + 0% { + opacity: $initialOpacity; + transform: scale(0) $hardwareAcc; + } + + 25% { + opacity: 0.5; + transform: scale(1 + $amount) $hardwareAcc; + } + + 50% { + opacity: 1; + transform: scale(1 - $amount * 0.5) $hardwareAcc; + } + + 75% { + transform: scale(1 + $amount * 0.25) $hardwareAcc; + } + + 100% { + transform: scale(1) $hardwareAcc; + } + } + + opacity: 1; +} + +// ---------------------------------------- +/* Define a style which is only applied in horizontal mode */ +@mixin HorizontalStyle { + @include AppendGlobal(".h") { + @content; + } +} + +// ---------------------------------------- +/* Define a style which is only applied in vertical mode */ +@mixin VerticalStyle { + @include AppendGlobal(".v") { + @content; + } +} + +// ---------------------------------------- +/* Define a style which is only while the hardware keyboard is open */ +@mixin AndroidHwKeyboardOpen { + @include AppendGlobal(".kb") { + @content; + } +} + +// ---------------------------------------- +/* Automatically transforms the game state if a hardware keyboard is open */ +@mixin TransformToMatchKeyboard { + transition: transform 0.2s ease-in-out; + @include AndroidHwKeyboardOpen { + @include VerticalStyle { + transform: translateY(#{D(-125px)}) $hardwareAcc; + } + @include HorizontalStyle { + transform: translateY(#{D(-100px)}) $hardwareAcc; + } + } +} + +// ---------------------------------------- +/* Define a style which is only applied when the viewport is at least X pixels wide */ +@mixin StyleAtWidth($minW) { + @media (min-width: #{$minW}) { + @content; + } +} + +// ---------------------------------------- +/* Define a style which is only applied when the viewport is at least X pixels height */ +@mixin StyleAtHeight($minH) { + @media (min-height: #{$minH}) { + @content; + } +} + +// ---------------------------------------- +/* Define a style which is only applied when the viewport has at least the given dimensions */ +@mixin StyleAtDims($minW, $minH) { + @media (min-height: #{$minH}) and (min-width: #{$minW}) { + @content; + } +} + +// ---------------------------------------- +/* Define a style which is only applied when the viewport has at maximum the given dimensions */ +@mixin StyleBelowDims($maxW, $maxH) { + @media (max-height: #{$maxH}) and (max-width: #{$maxW}) { + @content; + } +} + +// ---------------------------------------- +/* Define a style which is only applied when the viewport has at maximum the given height */ +@mixin StyleBelowHeight($maxH) { + @media (max-height: #{$maxH}) { + @content; + } +} +// ---------------------------------------- +/* Define a style which is only applied when the viewport has at maximum the given width */ +@mixin StyleBelowWidth($maxW) { + @media (max-width: #{$maxW}) { + @content; + } +} + +// ---------------------------------------- +// Dynamic graphics quality styles + +@mixin BoxShadow3D($bgColor, $size: 3px, $pressEffect: true) { + background-color: $bgColor; + + $borderSize: 1.5px; + $borderColor: rgb(18, 20, 24); + + // box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($size) 0 0px rgba(mix(darken($bgColor, 9), #b0e2ff, 95%), 1), + // 0 D($size) 0 D($borderSize) $borderColor; + + // box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($size) 0 D($borderSize) $borderColor, + // D(-$size * 1.5) D($size * 2) 0 D($borderSize) rgba(0, 0, 0, 0.1); + + // transition: box-shadow 0.1s ease-in-out; + + // @if $pressEffect { + // &.pressed { + // transform: none !important; + // $pSize: max(0, $size - 1.5px); + // transition: none !important; + // box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($pSize) 0 0px rgba(mix(darken($bgColor, 9), #b0e2ff, 95%), 1), + // 0 D($pSize) 0 D($borderSize) $borderColor; + // top: D($size - $pSize); + // } + // } +} + +@mixin BorderRadius($v1: 2px, $v2: "", $v3: "", $v4: "") { + @include S(border-radius, $v1, $v2, $v3, $v4); +} + +@mixin BoxShadow($x, $y, $blur, $offset, $color) { + box-shadow: D($x) D($y) D($blur) D($offset) $color; +} + +@mixin DropShadow($yOffset: 2px, $blur: 2px, $amount: 0.2) { + @include BoxShadow(0, $yOffset, $blur, 0, rgba(#000, $amount)); +} + +@mixin TextShadow($yOffset: 2px, $blur: 1px, $amount: 0.6) { + text-shadow: 0 D($yOffset) D($blur) rgba(#000, $amount); +} + +@mixin Button3D($bgColor, $pressEffect: true) { + @include BoxShadow3D($bgColor, 2px, $pressEffect); +} + +@mixin ButtonDisabled3D($bgColor) { + @include BoxShadow3D($bgColor, 0.5px, false); +} + +@mixin BoxShadowInset($bgColor, $size: 3px) { + background-color: $bgColor; + + $borderSize: 1px; + $borderColor: rgb(15, 19, 24); + box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($size) 0 rgba(#fff, 0.07); + border-top: D($size) solid rgba(#000, 0.1); + + //, 0 D($size) 0 0px rgba(mix(darken($bgColor, 9), #b0e2ff, 95%), 1), + // 0 D($size + $borderSize) 0 0 $borderColor; +} + +@mixin TextShadow3D($color: rgb(222, 234, 238), $borderColor: #000) { + color: $color; +} + +// ---------------------------------------- +/* String replacement */ +@function str-replace($string, $search, $replace: "") { + $index: str-index($string, $search); + + @if $index { + @return str-slice($string, 1, $index - 1) + $replace + + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); + } + + @return $string; +} + +@mixin BounceInFromSide($mul, $duration: 0.18s ease-in-out) { + @include InlineAnimation($duration) { + 0% { + transform: translateY(#{D(-100px * $mul)}) scale(0.9); + opacity: 0; + } + + 100% { + opacity: 1; + transform: none; + } + } + opacity: 1; + transform: none; +} + +@mixin BreakText { + word-wrap: break-word; + word-break: break-all; + overflow-wrap: break-all; +} + +@mixin SupportsAndroidNotchQuery { + @supports (color: constant(--notch-inset-left)) { + @content; + } +} +@mixin SupportsiOsNotchQuery { + @supports (color: env(safe-area-inset-left, 0px)) { + @content; + } +} + +@mixin DarkThemeOverride { + @at-root html[data-theme="dark"] &, + &[data-theme="dark"] { + @content; + } +} + +@mixin DarkThemeInvert { + @include DarkThemeOverride { + filter: invert(1); + } +} diff --git a/src/css/resources.scss b/src/css/resources.scss new file mode 100644 index 00000000..08bfa43f --- /dev/null +++ b/src/css/resources.scss @@ -0,0 +1,91 @@ +$buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, trash, underground_belt, wire, + constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader, storage, + transistor, analyzer, comparator, item_producer; + +@each $building in $buildings { + [data-icon="building_icons/#{$building}.png"] { + /* @load-async */ + background-image: uiResource("res/ui/building_icons/#{$building}.png") !important; + } +} + +$buildingsAndVariants: belt, balancer, underground_belt, underground_belt-tier2, miner, miner-chainable, + cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer, painter-double, painter-quad, trash, storage, + reader, rotater-rotate180, display, constant_signal, wire, wire_tunnel, logic_gate-or, logic_gate-not, + logic_gate-xor, analyzer, virtual_processor-rotater, virtual_processor-unstacker, item_producer, + virtual_processor-stacker, virtual_processor-painter, wire-second, painter, painter-mirrored, comparator; +@each $building in $buildingsAndVariants { + [data-icon="building_tutorials/#{$building}.png"] { + /* @load-async */ + background-image: uiResource("res/ui/building_tutorials/#{$building}.png") !important; + } +} + +[data-icon="building_tutorials/balancer-merger.png"], +[data-icon="building_tutorials/balancer-merger-inverse.png"] { + /* @load-async */ + background-image: uiResource("res/ui/building_tutorials/balancer-merger.png") !important; +} + +[data-icon="building_tutorials/balancer-splitter.png"], +[data-icon="building_tutorials/balancer-splitter-inverse.png"] { + /* @load-async */ + background-image: uiResource("res/ui/building_tutorials/balancer-splitter.png") !important; +} + +[data-icon="building_tutorials/transistor.png"], +[data-icon="building_tutorials/transistor-mirrored.png"] { + /* @load-async */ + background-image: uiResource("res/ui/building_tutorials/transistor.png") !important; +} + +// Filter and lever share tutorials +[data-icon="building_tutorials/filter.png"], +[data-icon="building_tutorials/lever.png"] { + /* @load-async */ + background-image: uiResource("res/ui/building_tutorials/lever.png") !important; +} + +// Logic gate +[data-icon="building_tutorials/logic_gate.png"] { + /* @load-async */ + background-image: uiResource("res/ui/building_tutorials/logic_gate-and.png") !important; +} + +// Virtual processor +[data-icon="building_tutorials/virtual_processor.png"] { + /* @load-async */ + background-image: uiResource("res/ui/building_tutorials/virtual_processor-cutter.png") !important; +} + +$icons: notification_saved, notification_success, notification_upgrade; +@each $icon in $icons { + [data-icon="icons/#{$icon}.png"] { + /* @load-async */ + 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}"] { + /* @load-async */ + background-image: uiResource("languages/#{$language}.svg") !important; + } +} + +/* +PRICE +*/ + +.steam_1_pr { + /* @load-async */ + background-image: uiResource("get_on_steam_with_price.png") !important; +} + +.steam_2_npr { + /* @load-async */ + background-image: uiResource("get_on_steam.png") !important; +} 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/ingame.scss b/src/css/states/ingame.scss index 3f220a5d..d67ee00f 100644 --- a/src/css/states/ingame.scss +++ b/src/css/states/ingame.scss @@ -1,37 +1,52 @@ -#state_InGameState { - .gameLoadingOverlay { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 9999; - align-items: center; - justify-content: center; - pointer-events: all; - display: flex; - background: $mainBgColor; - flex-direction: column; - } - - #ingame_Canvas { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - } - #ingame_HUD_ModalDialogs { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - } - - @include DarkThemeOverride { - .gameLoadingOverlay { - background: $darkModeGameBackground; - } - } -} +#state_InGameState { + .gameLoadingOverlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 9999; + align-items: center; + justify-content: center; + pointer-events: all; + display: flex; + background: $mainBgColor; + flex-direction: column; + } + + .prefab_GameHint { + position: absolute; + @include S(bottom, 40px); + @include S(left, 20px); + @include S(right, 20px); + @include PlainText; + text-align: center; + + color: #666; + + @include DarkThemeOverride() { + color: lighten($darkModeGameBackground, 50); + } + } + + #ingame_Canvas { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + } + #ingame_HUD_ModalDialogs { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + } + + @include DarkThemeOverride { + .gameLoadingOverlay { + background: $darkModeGameBackground; + } + } +} diff --git a/src/css/states/keybindings.scss b/src/css/states/keybindings.scss index cf211403..186a8bef 100644 --- a/src/css/states/keybindings.scss +++ b/src/css/states/keybindings.scss @@ -1,71 +1,73 @@ -#state_KeybindingsState { - .content { - .topEntries { - display: grid; - grid-template-columns: 1fr auto; - @include S(grid-gap, 5px); - @include S(margin-bottom, 10px); - } - - .hint { - display: block; - background: #eee; - @include S(padding, 4px); - @include PlainText; - } - - .category { - .entry { - display: grid; - @include S(margin-top, 2px); - @include S(padding-top, 2px); - @include S(grid-gap, 4px); - grid-template-columns: 1fr #{D(100px)} auto auto; - border-bottom: #{D(1px)} dotted #eee; - color: #888c8f; - .mapping { - color: $colorBlueBright; - text-align: center; - } - - button { - @include S(height, 15px); - @include S(width, 15px); - @include IncreasedClickArea(0px); - background: transparent center center / 40% no-repeat; - opacity: 0.9; - &.editKeybinding { - background-image: uiResource("icons/edit_key.png"); - } - - &.resetKeybinding { - background-image: uiResource("icons/reset_key.png"); - } - - &.disabled { - pointer-events: none; - cursor: default; - opacity: 0.1 !important; - } - } - } - } - } - - @include DarkThemeOverride { - .content { - .hint { - background: #3b3d40; - } - - .category .entry { - color: #c0c4c8; - border-bottom-color: #888; - - button { - filter: invert(1); - } - } - } - } -} +#state_KeybindingsState { + .content { + .topEntries { + display: grid; + grid-template-columns: 1fr auto; + @include S(grid-gap, 5px); + @include S(margin-bottom, 10px); + } + + .hint { + display: block; + background: #eee; + @include S(padding, 4px); + @include PlainText; + } + + .category { + .entry { + display: grid; + @include S(margin-top, 2px); + @include S(padding-top, 2px); + @include S(grid-gap, 4px); + grid-template-columns: 1fr #{D(100px)} auto auto; + border-bottom: #{D(1px)} dotted #eee; + color: #888c8f; + .mapping { + color: $colorBlueBright; + text-align: center; + } + + button { + @include S(height, 15px); + @include S(width, 15px); + @include IncreasedClickArea(0px); + background: transparent center center / 40% no-repeat; + opacity: 0.9; + &.editKeybinding { + /* @load-async */ + background-image: uiResource("icons/edit_key.png"); + } + + &.resetKeybinding { + /* @load-async */ + background-image: uiResource("icons/reset_key.png"); + } + + &.disabled { + pointer-events: none; + cursor: default; + opacity: 0.1 !important; + } + } + } + } + } + + @include DarkThemeOverride { + .content { + .hint { + background: darken($darkModeControlsBackground, 4); + } + + .category .entry { + color: #c0c4c8; + border-bottom-color: #888; + + button { + filter: invert(1); + } + } + } + } +} diff --git a/src/css/states/main_menu.scss b/src/css/states/main_menu.scss index 0981cdfc..cf0ab718 100644 --- a/src/css/states/main_menu.scss +++ b/src/css/states/main_menu.scss @@ -1,518 +1,602 @@ -#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; + & { + /* @load-async */ + background: uiResource("icons/main_menu_settings.png") center center / contain no-repeat; + } + transition: opacity 0.12s ease-in-out; + @include IncreasedClickArea(2px); + opacity: 0.7; + &:hover { + opacity: 1; + } + } + + .exitAppButton { + /* @load-async */ + background-image: uiResource("icons/main_menu_exit.png"); + background-size: 90%; + } + + .languageChoose { + @include S(border-radius, 8px); + border: solid #222428; + background-color: #fff; + @include S(border-width, 2px); + background-size: cover; + opacity: 0.8; + } + } + + .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.07; + &.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 { + align-self: center; + justify-self: center; + width: 100%; + @include S(height, 40px); + @include S(width, 180px); + background: #171a23 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); + + @include S(border-radius, $globalBorderRadius); + + &:hover { + transform: 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); + & { + /* @load-async */ + 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 center center / 40% no-repeat; + } + + button.resumeGame { + background-color: #44484a; + & { + /* @load-async */ + background-image: uiResource("icons/play.png"); + } + } + + button.downloadGame { + grid-column: 3 / 4; + grid-row: 1 / 2; + background-color: transparent; + + & { + /* @load-async */ + background-image: uiResource("icons/download.png"); + } + @include S(width, 15px); + @include IncreasedClickArea(0px); + @include S(height, 15px); + background-size: 80%; + align-self: start; + opacity: 0.4; + + &:hover { + opacity: 0.5; + } + + @include DarkThemeInvert; + } + + button.deleteGame { + grid-column: 3 / 4; + grid-row: 2 / 3; + background-color: transparent; + @include IncreasedClickArea(0px); + + & { + /* @load-async */ + background-image: uiResource("icons/delete.png"); + } + @include S(width, 15px); + @include S(height, 15px); + align-self: end; + background-size: 80%; + opacity: 0.4; + + &:hover { + opacity: 0.5; + } + + @include DarkThemeInvert; + } + + button.renameGame { + background-color: transparent; + @include IncreasedClickArea(2px); + + & { + /* @load-async */ + 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.4; + @include S(margin-left, 4px); + + &:hover { + opacity: 0.5; + } + + @include DarkThemeInvert; + } + + button.resumeGame { + grid-column: 4 / 5; + grid-row: 1 / 3; + margin: 0; + @include S(width, 32px); + height: 100%; + @include S(margin-left, 4px); + + @include DarkThemeOverride { + background-color: lighten($darkModeControlsBackground, 10); + } + } + } + } + } + + .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); + + $linkBg: #fdfdff; + $linkBgHover: darken($linkBg, 2); + $linkColor: #55586a; + + > .boxLink { + display: grid; + align-items: center; + grid-template-columns: 1fr auto; + + justify-content: center; + + & { + /* @load-async */ + background: $linkBg 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: $linkColor; + + transition: background-color 0.12s ease-in-out; + pointer-events: all; + @include S(width, 120px); + @include S(height, 60px); + + cursor: pointer; + &:hover { + background-color: $linkBgHover; + } + + .thirdpartyLogo { + display: inline-block; + @include S(width, 50px); + @include S(height, 50px); + background: center center / 80% no-repeat; + &.githubLogo { + /* @load-async */ + background-image: uiResource("main_menu/github.png"); + } + &.discordLogo { + /* @load-async */ + 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: $linkColor; + background: $linkBg; + height: 100%; + + &:hover { + background-color: $linkBgHover; + } + @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 { + /* @load-async */ + background-image: uiResource("main_menu/reddit.svg"); + } + &.changelog { + /* @load-async */ + background-image: uiResource("main_menu/changelog.svg"); + } + &.helpTranslate { + /* @load-async */ + background-image: uiResource("main_menu/translate.svg"); + } + } + } + } + + @include DarkThemeOverride { + background: $darkModeGameBackground center center / cover !important; + + .mainContainer { + background: $darkModeControlsBackground; + + .savegames .savegame { + background: darken($darkModeControlsBackground, 5); + color: white; + } + } + + .footer { + > a, + .sidelinks > a { + background-color: $darkModeControlsBackground; + color: #eee; + + &:hover { + background-color: darken($darkModeControlsBackground, 5); + } + } + + .author { + color: #bdbdbd; + + > a { + color: white; + } + } + + .thirdpartyLogo.githubLogo { + filter: invert(1); + } + } + } +} diff --git a/src/css/states/mobile_warning.scss b/src/css/states/mobile_warning.scss index 6dc84e3c..25e3d9ba 100644 --- a/src/css/states/mobile_warning.scss +++ b/src/css/states/mobile_warning.scss @@ -1,48 +1,51 @@ -#state_MobileWarningState { - display: flex; - align-items: center; - background: #333438 !important; - @include S(padding, 20px); - box-sizing: border-box; - justify-content: center; - flex-direction: column; - - .logo { - width: 80%; - max-width: 200px; - margin-bottom: 10px; - } - - p { - color: #aaacaf; - display: block; - margin-bottom: 13px; - font-size: 16px; - line-height: 20px; - max-width: 300px; - text-align: left; - a { - color: $colorBlueBright; - } - } - - .standaloneLink { - width: 200px; - height: 80px; - min-height: 40px; - background: uiResource("get_on_steam.png") center center / contain no-repeat; - overflow: hidden; - display: block; - text-indent: -999em; - cursor: pointer; - margin-top: 10px; - 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; - } - } -} +#state_MobileWarningState { + display: flex; + align-items: center; + background: #333438 !important; + @include S(padding, 20px); + box-sizing: border-box; + justify-content: center; + flex-direction: column; + + .logo { + width: 80%; + max-width: 200px; + margin-bottom: 10px; + } + + p { + color: #aaacaf; + display: block; + margin-bottom: 13px; + font-size: 16px; + line-height: 20px; + max-width: 300px; + text-align: left; + a { + color: $colorBlueBright; + } + } + + .standaloneLink { + width: 200px; + height: 80px; + min-height: 40px; + & { + /* @load-async */ + background: uiResource("get_on_steam.png") center center / contain no-repeat; + } + overflow: hidden; + display: block; + text-indent: -999em; + cursor: pointer; + margin-top: 10px; + 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; + } + } +} diff --git a/src/css/states/preload.scss b/src/css/states/preload.scss index ba0a372d..1187a2d4 100644 --- a/src/css/states/preload.scss +++ b/src/css/states/preload.scss @@ -1,145 +1,145 @@ -#state_PreloadState { - &.failure { - .loadingImage, - .loadingStatus { - display: none; - } - } - - .changelogDialogEntry { - margin-top: 10px; - width: 100%; - flex-direction: column; - text-align: left; - padding: 10px; - box-sizing: border-box; - background: #eef1f4; - - @include DarkThemeOverride { - background: #424242; - } - - .version { - @include Heading; - } - .date { - @include PlainText; - &::before { - content: " | "; - } - color: #aaabaf; - } - - .changes { - @include PlainText; - @include S(padding-left, 15px); - strong { - background: $colorBlueBright; - color: #fff; - text-transform: uppercase; - @include S(padding, 1px, 2px); - @include S(margin-right, 3px); - } - a { - color: $colorBlueBright; - } - li { - @include SuperSmallText; - @include S(margin-bottom, 10px); - } - } - } - - .failureBox { - .logo { - img { - @include S(width, 240px); - } - - @include S(margin-bottom, 30px); - } - - @include InlineAnimation(0.3s ease-in-out) { - 0% { - opacity: 0; - } - 100% { - opacity: 1; - } - } - - .failureInner { - // background: darken($mainBgColor, 6); - @include S(max-width, 350px); - margin: 0 20px; - text-align: left; - - @include BoxShadow3D(#fff); - @include S(padding, 15px); - @include S(border-radius, $globalBorderRadius); - @include DropShadow; - - .errorHeader { - color: #ef5072; - } - - .errorMessage { - @include PlainText; - display: block; - color: #666; - text-align: left; - @include BreakText; - hyphens: auto; - // border: dotted #666; - // @include S(border-width, 1px, 0); - @include S(padding, 10px, 0); - @include S(margin-top, 10px); - } - - .supportHelp { - @include S(margin-top, 10px); - @include PlainText; - - .email { - color: $themeColor; - cursor: pointer; - pointer-events: all; - } - } - - .lower { - display: flex; - align-items: center; - @include S(margin-top, 16px); - - i { - flex-grow: 1; - text-align: right; - color: #777; - @include PlainText; - } - - button.resetApp { - @include Button3D($colorRedBright); - @include PlainText; - @include S(padding, 5px, 8px, 4px); - color: #fff; - } - } - } - } - - /* Animations */ - .status { - transform: scale(0.7) $hardwareAcc; - opacity: 0; - @include StateAnim(transform, opacity); - } - - &.arrived { - .status { - opacity: 1; - transform: none; - } - } -} +#state_PreloadState { + &.failure { + .loadingImage, + .loadingStatus { + display: none; + } + } + + .changelogDialogEntry { + margin-top: 10px; + width: 100%; + flex-direction: column; + text-align: left; + padding: 10px; + box-sizing: border-box; + background: #eef1f4; + + @include DarkThemeOverride { + background: #424242; + } + + .version { + @include Heading; + } + .date { + @include PlainText; + &::before { + content: " | "; + } + color: #aaabaf; + } + + .changes { + @include PlainText; + @include S(padding-left, 15px); + strong { + background: $colorBlueBright; + color: #fff; + text-transform: uppercase; + @include S(padding, 1px, 2px); + @include S(margin-right, 3px); + } + a { + color: $colorBlueBright; + } + li { + @include SuperSmallText; + @include S(margin-bottom, 10px); + } + } + } + + .failureBox { + .logo { + img { + @include S(width, 240px); + } + + @include S(margin-bottom, 30px); + } + + @include InlineAnimation(0.3s ease-in-out) { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } + } + + .failureInner { + // background: darken($mainBgColor, 6); + @include S(max-width, 350px); + margin: 0 20px; + text-align: left; + + @include BoxShadow3D(#fff); + @include S(padding, 15px); + @include S(border-radius, $globalBorderRadius); + @include DropShadow; + + .errorHeader { + color: #ef5072; + } + + .errorMessage { + @include PlainText; + display: block; + color: #666; + text-align: left; + @include BreakText; + hyphens: auto; + // border: dotted #666; + // @include S(border-width, 1px, 0); + @include S(padding, 10px, 0); + @include S(margin-top, 10px); + } + + .supportHelp { + @include S(margin-top, 10px); + @include PlainText; + + .email { + color: $themeColor; + cursor: pointer; + pointer-events: all; + } + } + + .lower { + display: flex; + align-items: center; + @include S(margin-top, 16px); + + i { + flex-grow: 1; + text-align: right; + color: #777; + @include PlainText; + } + + button.resetApp { + @include Button3D($colorRedBright); + @include PlainText; + @include S(padding, 5px, 8px, 4px); + color: #fff; + } + } + } + } + + /* Animations */ + .status { + transform: scale(0.7) $hardwareAcc; + opacity: 0; + @include StateAnim(transform, opacity); + } + + &.arrived { + .status { + opacity: 1; + transform: none; + } + } +} diff --git a/src/css/states/settings.scss b/src/css/states/settings.scss index f06c9b31..50afcaa3 100644 --- a/src/css/states/settings.scss +++ b/src/css/states/settings.scss @@ -1,113 +1,226 @@ -#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: #eeeff5; + $colorCategoryButtonSelected: $colorBlueBright; + + $layoutBreak: 1000px; + + .container .content { + display: grid; + grid-template-columns: auto 1fr; + @include S(grid-gap, 10px); + + @include StyleBelowWidth($layoutBreak) { + grid-template-columns: 1fr; + grid-template-rows: auto 1fr; + } + + .sidebar { + display: grid; + @include S(min-width, 210px); + @include S(max-width, 320px); + @include S(grid-gap, 3px); + grid-template-rows: auto auto auto auto auto 1fr; + + @include StyleBelowWidth($layoutBreak) { + grid-template-rows: 1fr 1fr; + grid-template-columns: auto auto; + max-width: unset !important; + } + + button { + text-align: left; + &::after { + content: unset; + } + width: 100%; + box-sizing: border-box; + + @include StyleBelowWidth($layoutBreak) { + text-align: center; + } + } + + .other { + @include S(margin-top, 10px); + align-self: end; + + @include StyleBelowWidth($layoutBreak) { + margin-top: 0; + } + } + + 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, 10px); + + @include StyleBelowWidth($layoutBreak) { + display: none; + } + + @include SuperSmallText; + display: grid; + align-items: center; + grid-template-columns: 1fr auto; + .buildVersion { + display: flex; + flex-direction: column; + color: #aaadaf; + } + } + } + + .categoryContainer { + overflow-y: scroll; + pointer-events: all; + @include S(padding-right, 10px); + + .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); + + & { + /* @load-async */ + 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 { + .container .content { + .sidebar { + button.categoryButton, + button.about { + color: #ccc; + background-color: darken($darkModeControlsBackground, 5); + + &.active { + color: #fff; + background-color: $colorCategoryButtonSelected; + } + } + } + + .categoryContainer { + .category { + .setting { + background: darken($darkModeGameBackground, 10); + + .value.enum { + // dirty but works + // color: #222; + background-color: $darkModeControlsBackground; + + & { + /* @load-async */ + background-image: uiResource("icons/enum_selector_white.png"); + } + color: #ddd; + &:hover { + background-color: darken($darkModeControlsBackground, 2); + } + } + + .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..d5967523 100644 --- a/src/css/textual_game_state.scss +++ b/src/css/textual_game_state.scss @@ -1,81 +1,83 @@ -.gameState.textualState { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - $padding: 15px; - - .headerBar, - > .container .content { - @include S(width, 500px); - } - - .headerBar { - display: flex; - align-items: center; - justify-content: flex-start; - - h1 { - display: flex; - pointer-events: all; - align-items: center; - cursor: pointer; - @include SuperHeading; - text-transform: uppercase; - color: #333438; - position: relative; - @include IncreasedClickArea(10px); - } - - .backButton { - @include S(width, 30px); - @include S(height, 30px); - @include S(margin-right, 10px); - @include S(margin-left, -5px); - background: uiResource("icons/state_back_button.png") center center / 70% no-repeat; - } - - @include S(margin-bottom, 20px); - } - - > .container { - > .content { - background: #fff; - @include S(border-radius, $globalBorderRadius); - @include S(padding, 10px); - height: calc(80vh - #{D(60px)}); - overflow-y: auto; - box-sizing: border-box; - pointer-events: all; - - a { - color: $colorBlueBright; - } - - .categoryLabel { - display: block; - text-transform: uppercase; - @include S(margin-top, 15px); - @include S(margin-bottom, 15px); - @include Heading; - } - } - } - - @include DarkThemeOverride { - .headerBar { - h1 { - color: #e2e0db; - } - - .backButton { - filter: invert(1); - } - } - - > .container > .content { - background: darken($darkModeGameBackground, 3); - color: #eee; - } - } -} +.gameState.textualState { + display: grid; + grid-template-rows: auto 1fr; + box-sizing: border-box; + @include S(padding, 32px); + height: 100vh; + + .headerBar { + display: flex; + + h1 { + display: grid; + grid-template-columns: auto 1fr; + align-items: center; + pointer-events: all; + cursor: pointer; + @include SuperHeading; + text-transform: uppercase; + color: #333438; + position: relative; + @include IncreasedClickArea(10px); + } + + .backButton { + @include S(width, 30px); + @include S(height, 30px); + @include S(margin-right, 10px); + @include S(margin-left, -5px); + & { + /* @load-async */ + background: uiResource("icons/state_back_button.png") center center / 70% no-repeat; + } + } + @include S(margin-bottom, 20px); + } + + > .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: 100%; + overflow-y: auto; + box-sizing: border-box; + pointer-events: all; + + a { + color: $colorBlueBright; + } + + .categoryLabel { + display: block; + text-transform: uppercase; + @include S(margin-top, 15px); + @include S(margin-bottom, 15px); + @include Heading; + } + } + } + + @include DarkThemeOverride { + .headerBar { + h1 { + color: #e2e0db; + } + + .backButton { + filter: invert(1); + } + } + + > .container > .content { + background: $darkModeControlsBackground; + color: #eee; + } + } +} diff --git a/src/css/variables.scss b/src/css/variables.scss index c1c69371..d2798f41 100644 --- a/src/css/variables.scss +++ b/src/css/variables.scss @@ -1,198 +1,199 @@ -$globalBorderRadius: 0px; - -// When to reduce control elements size for small devices -$layoutExpandMinWidth: 340px; - -// Font sizes and line heights -$superHeadingFontSize: 25px; -$superHeadingLineHeight: 24px; - -$breakTooltipShowStatsPx: 1023px; - -$headingFontSize: 19px; -$headingLineHeight: 21px; - -$textFontSize: 16px; -$textLineHeight: 21px; - -$plainTextFontSize: 13px; -$plainTextLineHeight: 17px; - -$supersmallTextFontSize: 10px; -$supersmallTextLineHeight: 13px; -$buttonFontSize: 14px; -$buttonLineHeight: 18px; - -// Main background color -$mainBgColor: #dee1ea; - -// Accent colors - -$accentColorBright: #e1e4ed; -$accentColorDark: #7d808a; -$colorGreenBright: #66bb6a; -$colorBlueBright: rgb(74, 163, 223); -$colorRedBright: #ef5072; -$themeColor: #393747; -$ingameHudBg: rgba(#333438, 0.9); - -$text3dColor: #f4ffff; - -$darkModeGameBackground: #5c606c; - -// Dialog properties -$modalDialogBg: rgba(160, 165, 180, 0.8); -$dialogBgColor: lighten($mainBgColor, 10); - -$lightFontWeight: normal; -$boldFontWeight: 600; - -$iconSizeSmall: 30px; -$iconSizeMedium: 40px; -$iconSizeLarge: 60px; - -// Poppins 500 -// Rubik 400 -// Cairo 400 -// Viga 400 -// Sniglet 400 - -$mainFont: "GameFont", sans-serif; -// $mainFont: "DK Canoodle"; -// $mainFont: "MADE Florence Sans"; -$numberFont: $mainFont; -$textFont: $mainFont; - -$mainFontWeight: 400; -$mainFontSpacing: 0.04em; -$mainFontScale: 1; - -@mixin DebugText($color) { - // font-size: 3px; - // &, - // * { - // color: $color !important; - // } -} - -@mixin SuperSmallText { - @include ScaleFont($supersmallTextFontSize, $supersmallTextLineHeight); - font-weight: $mainFontWeight; - font-family: $mainFont; - letter-spacing: $mainFontSpacing; - @include DebugText(green); -} - -@mixin PlainText { - @include ScaleFont($plainTextFontSize, $plainTextLineHeight); - font-weight: $mainFontWeight; - font-family: $mainFont; - letter-spacing: $mainFontSpacing; - - @include DebugText(red); -} - -@mixin Text { - @include ScaleFont($textFontSize, $textLineHeight); - font-weight: $mainFontWeight; - font-family: $mainFont; - - letter-spacing: $mainFontSpacing; - - @include DebugText(blue); -} - -@mixin Heading { - @include ScaleFont($headingFontSize, $headingLineHeight); - font-weight: $mainFontWeight; - font-family: $mainFont; - letter-spacing: $mainFontSpacing; - - @include DebugText(yellow); -} - -@mixin SuperHeading { - @include ScaleFont($superHeadingFontSize, $superHeadingLineHeight); - font-weight: $mainFontWeight; - font-family: $mainFont; - letter-spacing: $mainFontSpacing; - - @include DebugText(orange); -} - -@mixin ButtonText { - @include ScaleFont($buttonFontSize, $buttonLineHeight); - font-weight: $mainFontWeight; - font-family: $mainFont; - letter-spacing: $mainFontSpacing; - @include DebugText(purple); -} - -@function str-split($string, $separator) { - // empty array/list - $split-arr: (); - // first index of separator in string - $index: str-index($string, $separator); - // loop through string - @while $index != null { - // get the substring from the first character to the separator - $item: str-slice($string, 1, $index - 1); - // push item to array - $split-arr: append($split-arr, $item); - // remove item and separator from string - $string: str-slice($string, $index + 1); - // find new index of separator - $index: str-index($string, $separator); - } - // add the remaining string to list (the last item) - $split-arr: append($split-arr, $string); - - @return $split-arr; -} - -@function _first-index($string, $direction: "left") { - @for $i from 1 through str-length($string) { - $index: if($direction == "left", $i, -$i); - - @if str-slice($string, $index, $index) != " " { - @return $index; - } - } - - @return 0; -} - -@function trim($string) { - @return str-slice($string, _first-index($string, "left"), _first-index($string, "right")); -} - -@mixin AppendGlobal($prefix) { - $strSelector: quote(&); - $selectors: str-split($strSelector, ","); - - $builtSelector: null; - - @if (& == null) { - $builtSelector: "html" + $prefix; - } @else { - $builtSelector: (); - // @debug ($strSelector, "->>>", $selectors); - @each $srcSelector in $selectors { - $srcSelector: trim($srcSelector); - // @debug ("___", $srcSelector); - $selector: "html" + $prefix + " " + $srcSelector; - @if str-index($srcSelector, "html.") { - $selector: "html" + - $prefix + - "." + - str-slice($srcSelector, str-index($srcSelector, "html.") + 5); - } - // @debug ("_______", $selector); - $builtSelector: append($builtSelector, $selector, comma); - } - } - - @at-root #{$builtSelector} { - @content; - } -} +$globalBorderRadius: 2px; + +// When to reduce control elements size for small devices +$layoutExpandMinWidth: 340px; + +// Font sizes and line heights +$superHeadingFontSize: 25px; +$superHeadingLineHeight: 24px; + +$breakTooltipShowStatsPx: 1023px; + +$headingFontSize: 19px; +$headingLineHeight: 21px; + +$textFontSize: 16px; +$textLineHeight: 21px; + +$plainTextFontSize: 13px; +$plainTextLineHeight: 17px; + +$supersmallTextFontSize: 10px; +$supersmallTextLineHeight: 13px; +$buttonFontSize: 14px; +$buttonLineHeight: 18px; + +// Main background color +$mainBgColor: #dee1ea; + +// Accent colors + +$accentColorBright: #e1e4ed; +$accentColorDark: #7d808a; +$colorGreenBright: #66bb6a; +$colorBlueBright: rgb(74, 151, 223); +$colorRedBright: #ef5072; +$themeColor: #393747; +$ingameHudBg: rgba(#333438, 0.9); + +$text3dColor: #f4ffff; + +$darkModeGameBackground: #535866; +$darkModeControlsBackground: darken($darkModeGameBackground, 5); + +// Dialog properties +$modalDialogBg: rgba(160, 165, 180, 0.8); +$dialogBgColor: lighten($mainBgColor, 10); + +$lightFontWeight: normal; +$boldFontWeight: 600; + +$iconSizeSmall: 30px; +$iconSizeMedium: 40px; +$iconSizeLarge: 60px; + +// Poppins 500 +// Rubik 400 +// Cairo 400 +// Viga 400 +// Sniglet 400 + +$mainFont: "GameFont", sans-serif; +// $mainFont: "DK Canoodle"; +// $mainFont: "MADE Florence Sans"; +$numberFont: $mainFont; +$textFont: $mainFont; + +$mainFontWeight: 400; +$mainFontSpacing: 0.04em; +$mainFontScale: 1; + +@mixin DebugText($color) { + // font-size: 3px; + // &, + // * { + // color: $color !important; + // } +} + +@mixin SuperSmallText { + @include ScaleFont($supersmallTextFontSize, $supersmallTextLineHeight); + font-weight: $mainFontWeight; + font-family: $mainFont; + letter-spacing: $mainFontSpacing; + @include DebugText(green); +} + +@mixin PlainText { + @include ScaleFont($plainTextFontSize, $plainTextLineHeight); + font-weight: $mainFontWeight; + font-family: $mainFont; + letter-spacing: $mainFontSpacing; + + @include DebugText(red); +} + +@mixin Text { + @include ScaleFont($textFontSize, $textLineHeight); + font-weight: $mainFontWeight; + font-family: $mainFont; + + letter-spacing: $mainFontSpacing; + + @include DebugText(blue); +} + +@mixin Heading { + @include ScaleFont($headingFontSize, $headingLineHeight); + font-weight: $mainFontWeight; + font-family: $mainFont; + letter-spacing: $mainFontSpacing; + + @include DebugText(yellow); +} + +@mixin SuperHeading { + @include ScaleFont($superHeadingFontSize, $superHeadingLineHeight); + font-weight: $mainFontWeight; + font-family: $mainFont; + letter-spacing: $mainFontSpacing; + + @include DebugText(orange); +} + +@mixin ButtonText { + @include ScaleFont($buttonFontSize, $buttonLineHeight); + font-weight: $mainFontWeight; + font-family: $mainFont; + letter-spacing: $mainFontSpacing; + @include DebugText(purple); +} + +@function str-split($string, $separator) { + // empty array/list + $split-arr: (); + // first index of separator in string + $index: str-index($string, $separator); + // loop through string + @while $index != null { + // get the substring from the first character to the separator + $item: str-slice($string, 1, $index - 1); + // push item to array + $split-arr: append($split-arr, $item); + // remove item and separator from string + $string: str-slice($string, $index + 1); + // find new index of separator + $index: str-index($string, $separator); + } + // add the remaining string to list (the last item) + $split-arr: append($split-arr, $string); + + @return $split-arr; +} + +@function _first-index($string, $direction: "left") { + @for $i from 1 through str-length($string) { + $index: if($direction == "left", $i, -$i); + + @if str-slice($string, $index, $index) != " " { + @return $index; + } + } + + @return 0; +} + +@function trim($string) { + @return str-slice($string, _first-index($string, "left"), _first-index($string, "right")); +} + +@mixin AppendGlobal($prefix) { + $strSelector: quote(&); + $selectors: str-split($strSelector, ","); + + $builtSelector: null; + + @if (& == null) { + $builtSelector: "html" + $prefix; + } @else { + $builtSelector: (); + // @debug ($strSelector, "->>>", $selectors); + @each $srcSelector in $selectors { + $srcSelector: trim($srcSelector); + // @debug ("___", $srcSelector); + $selector: "html" + $prefix + " " + $srcSelector; + @if str-index($srcSelector, "html.") { + $selector: "html" + + $prefix + + "." + + str-slice($srcSelector, str-index($srcSelector, "html.") + 5); + } + // @debug ("_______", $selector); + $builtSelector: append($builtSelector, $selector, comma); + } + } + + @at-root #{$builtSelector} { + @content; + } +} diff --git a/src/js/application.js b/src/js/application.js index 1726bd2d..d9ca7641 100644 --- a/src/js/application.js +++ b/src/js/application.js @@ -1,406 +1,415 @@ -import { AnimationFrame } from "./core/animation_frame"; -import { BackgroundResourcesLoader } from "./core/background_resources_loader"; -import { IS_MOBILE } from "./core/config"; -import { GameState } from "./core/game_state"; -import { GLOBAL_APP, setGlobalApp } from "./core/globals"; -import { InputDistributor } from "./core/input_distributor"; -import { Loader } from "./core/loader"; -import { createLogger, logSection } from "./core/logging"; -import { StateManager } from "./core/state_manager"; -import { TrackedState } from "./core/tracked_state"; -import { getPlatformName, waitNextFrame } from "./core/utils"; -import { Vector } from "./core/vector"; -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"; -import { AboutState } from "./states/about"; -import { ChangelogState } from "./states/changelog"; -import { InGameState } from "./states/ingame"; -import { KeybindingsState } from "./states/keybindings"; -import { MainMenuState } from "./states/main_menu"; -import { MobileWarningState } from "./states/mobile_warning"; -import { PreloadState } from "./states/preload"; -import { SettingsState } from "./states/settings"; -import { ShapezGameAnalytics } from "./platform/browser/game_analytics"; - -const logger = createLogger("application"); - -// Set the name of the hidden property and the change event for visibility -let pageHiddenPropName, pageVisibilityEventName; -if (typeof document.hidden !== "undefined") { - // Opera 12.10 and Firefox 18 and later support - pageHiddenPropName = "hidden"; - pageVisibilityEventName = "visibilitychange"; - // @ts-ignore -} else if (typeof document.msHidden !== "undefined") { - pageHiddenPropName = "msHidden"; - pageVisibilityEventName = "msvisibilitychange"; - // @ts-ignore -} else if (typeof document.webkitHidden !== "undefined") { - pageHiddenPropName = "webkitHidden"; - pageVisibilityEventName = "webkitvisibilitychange"; -} - -export class Application { - constructor() { - assert(!GLOBAL_APP, "Tried to construct application twice"); - logger.log("Creating application, platform =", getPlatformName()); - setGlobalApp(this); - - this.unloaded = false; - - // Global stuff - this.settings = new ApplicationSettings(this); - this.ticker = new AnimationFrame(); - this.stateMgr = new StateManager(this); - this.savegameMgr = new SavegameManager(this); - this.inputMgr = new InputDistributor(this); - this.backgroundResourceLoader = new BackgroundResourcesLoader(this); - - // Platform dependent stuff - - /** @type {StorageInterface} */ - this.storage = null; - - /** @type {SoundInterface} */ - this.sound = null; - - /** @type {PlatformWrapperInterface} */ - this.platformWrapper = null; - - /** @type {AdProviderInterface} */ - this.adProvider = null; - - /** @type {AnalyticsInterface} */ - this.analytics = null; - - /** @type {GameAnalyticsInterface} */ - this.gameAnalytics = null; - - this.initPlatformDependentInstances(); - - // Track if the window is focused (only relevant for browser) - this.focused = true; - - // Track if the window is visible - this.pageVisible = true; - - // Track if the app is paused (cordova) - this.applicationPaused = false; - - /** @type {TypedTrackedState} */ - this.trackedIsRenderable = new TrackedState(this.onAppRenderableStateChanged, this); - - // Dimensions - this.screenWidth = 0; - this.screenHeight = 0; - - // Store the timestamp where we last checked for a screen resize, since orientationchange is unreliable with cordova - this.lastResizeCheck = null; - - // Store the mouse position, or null if not available - /** @type {Vector|null} */ - this.mousePosition = null; - } - - /** - * Initializes all platform instances - */ - initPlatformDependentInstances() { - logger.log("Creating platform dependent instances (standalone=", G_IS_STANDALONE, ")"); - - if (G_IS_STANDALONE) { - this.platformWrapper = new PlatformWrapperImplElectron(this); - } else { - this.platformWrapper = new PlatformWrapperImplBrowser(this); - } - - // Start with empty ad provider - this.adProvider = new NoAdProvider(this); - this.sound = new SoundImplBrowser(this); - this.analytics = new GoogleAnalyticsImpl(this); - this.gameAnalytics = new ShapezGameAnalytics(this); - } - - /** - * Registers all game states - */ - registerStates() { - /** @type {Array} */ - const states = [ - PreloadState, - MobileWarningState, - MainMenuState, - InGameState, - SettingsState, - KeybindingsState, - AboutState, - ChangelogState, - ]; - - for (let i = 0; i < states.length; ++i) { - this.stateMgr.register(states[i]); - } - } - - /** - * Registers all event listeners - */ - registerEventListeners() { - window.addEventListener("focus", this.onFocus.bind(this)); - window.addEventListener("blur", this.onBlur.bind(this)); - - window.addEventListener("resize", () => this.checkResize(), true); - window.addEventListener("orientationchange", () => this.checkResize(), true); - - if (!G_IS_MOBILE_APP && !IS_MOBILE) { - window.addEventListener("mousemove", this.handleMousemove.bind(this)); - } - - // Unload events - window.addEventListener("beforeunload", this.onBeforeUnload.bind(this), true); - window.addEventListener("unload", this.onUnload.bind(this), true); - - document.addEventListener(pageVisibilityEventName, this.handleVisibilityChange.bind(this), false); - - // Track touches so we can update the focus appropriately - document.addEventListener("touchstart", this.updateFocusAfterUserInteraction.bind(this), true); - document.addEventListener("touchend", this.updateFocusAfterUserInteraction.bind(this), true); - } - - /** - * Checks the focus after a touch - * @param {TouchEvent} event - */ - updateFocusAfterUserInteraction(event) { - const target = /** @type {HTMLElement} */ (event.target); - if (!target || !target.tagName) { - // Safety check - logger.warn("Invalid touchstart/touchend event:", event); - return; - } - - // When clicking an element which is not the currently focused one, defocus it - if (target !== document.activeElement) { - // @ts-ignore - if (document.activeElement.blur) { - // @ts-ignore - document.activeElement.blur(); - } - } - - // If we click an input field, focus it now - if (target.tagName.toLowerCase() === "input") { - // We *really* need the focus - waitNextFrame().then(() => target.focus()); - } - } - - /** - * Handles a page visibility change event - * @param {Event} event - */ - handleVisibilityChange(event) { - window.focus(); - const pageVisible = !document[pageHiddenPropName]; - if (pageVisible !== this.pageVisible) { - this.pageVisible = pageVisible; - logger.log("Visibility changed:", this.pageVisible); - this.trackedIsRenderable.set(this.isRenderable()); - } - } - - /** - * Handles a mouse move event - * @param {MouseEvent} event - */ - handleMousemove(event) { - this.mousePosition = new Vector(event.clientX, event.clientY); - } - - /** - * Internal on focus handler - */ - onFocus() { - this.focused = true; - } - - /** - * Internal blur handler - */ - onBlur() { - this.focused = false; - } - - /** - * Returns if the app is currently visible - */ - isRenderable() { - return !this.applicationPaused && this.pageVisible; - } - - onAppRenderableStateChanged(renderable) { - logger.log("Application renderable:", renderable); - window.focus(); - const currentState = this.stateMgr.getCurrentState(); - if (!renderable) { - if (currentState) { - currentState.onAppPause(); - } - } else { - if (currentState) { - currentState.onAppResume(); - } - this.checkResize(); - } - - this.sound.onPageRenderableStateChanged(renderable); - } - - /** - * Internal unload handler - */ - onUnload(event) { - if (!this.unloaded) { - logSection("UNLOAD HANDLER", "#f77"); - this.unloaded = true; - const currentState = this.stateMgr.getCurrentState(); - if (currentState) { - currentState.onBeforeExit(); - } - this.deinitialize(); - } - } - - /** - * Internal before-unload handler - */ - onBeforeUnload(event) { - logSection("BEFORE UNLOAD HANDLER", "#f77"); - const currentState = this.stateMgr.getCurrentState(); - - if (!G_IS_DEV && currentState && currentState.getHasUnloadConfirmation()) { - if (!G_IS_STANDALONE) { - // Need to show a "Are you sure you want to exit" - event.preventDefault(); - event.returnValue = "Are you sure you want to exit?"; - } - } - } - - /** - * Boots the application - */ - boot() { - console.log("Booting ..."); - this.registerStates(); - this.registerEventListeners(); - - Loader.linkAppAfterBoot(this); - - // Check for mobile - if (IS_MOBILE) { - this.stateMgr.moveToState("MobileWarningState"); - } else { - this.stateMgr.moveToState("PreloadState"); - } - - // Starting rendering - this.ticker.frameEmitted.add(this.onFrameEmitted, this); - this.ticker.bgFrameEmitted.add(this.onBackgroundFrame, this); - this.ticker.start(); - - window.focus(); - } - - /** - * Deinitializes the application - */ - deinitialize() { - return this.sound.deinitialize(); - } - - /** - * Background frame update callback - * @param {number} dt - */ - onBackgroundFrame(dt) { - if (this.isRenderable()) { - return; - } - - const currentState = this.stateMgr.getCurrentState(); - if (currentState) { - currentState.onBackgroundTick(dt); - } - } - - /** - * Frame update callback - * @param {number} dt - */ - onFrameEmitted(dt) { - if (!this.isRenderable()) { - return; - } - - const time = performance.now(); - - // Periodically check for resizes, this is expensive (takes 2-3ms so only do it once in a while!) - if (!this.lastResizeCheck || time - this.lastResizeCheck > 1000) { - this.checkResize(); - this.lastResizeCheck = time; - } - - const currentState = this.stateMgr.getCurrentState(); - if (currentState) { - currentState.onRender(dt); - } - } - - /** - * Checks if the app resized. Only does this once in a while - * @param {boolean} forceUpdate Forced update of the dimensions - */ - checkResize(forceUpdate = false) { - const w = window.innerWidth; - const h = window.innerHeight; - if (this.screenWidth !== w || this.screenHeight !== h || forceUpdate) { - this.screenWidth = w; - this.screenHeight = h; - const currentState = this.stateMgr.getCurrentState(); - if (currentState) { - currentState.onResized(this.screenWidth, this.screenHeight); - } - - const scale = this.getEffectiveUiScale(); - waitNextFrame().then(() => document.documentElement.style.setProperty("--ui-scale", scale)); - window.focus(); - } - } - - /** - * Returns the effective ui sclae - */ - getEffectiveUiScale() { - return this.platformWrapper.getUiScale() * this.settings.getInterfaceScaleValue(); - } - - /** - * Callback after ui scale has changed - */ - updateAfterUiScaleChanged() { - this.checkResize(true); - } -} +import { AnimationFrame } from "./core/animation_frame"; +import { BackgroundResourcesLoader } from "./core/background_resources_loader"; +import { IS_MOBILE } from "./core/config"; +import { GameState } from "./core/game_state"; +import { GLOBAL_APP, setGlobalApp } from "./core/globals"; +import { InputDistributor } from "./core/input_distributor"; +import { Loader } from "./core/loader"; +import { createLogger, logSection } from "./core/logging"; +import { StateManager } from "./core/state_manager"; +import { TrackedState } from "./core/tracked_state"; +import { getPlatformName, waitNextFrame } from "./core/utils"; +import { Vector } from "./core/vector"; +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 { SoundImplBrowser } from "./platform/browser/sound"; +import { PlatformWrapperImplBrowser } from "./platform/browser/wrapper"; +import { PlatformWrapperImplElectron } from "./platform/electron/wrapper"; +import { PlatformWrapperInterface } from "./platform/wrapper"; +import { ApplicationSettings } from "./profile/application_settings"; +import { SavegameManager } from "./savegame/savegame_manager"; +import { AboutState } from "./states/about"; +import { ChangelogState } from "./states/changelog"; +import { InGameState } from "./states/ingame"; +import { KeybindingsState } from "./states/keybindings"; +import { MainMenuState } from "./states/main_menu"; +import { MobileWarningState } from "./states/mobile_warning"; +import { PreloadState } from "./states/preload"; +import { SettingsState } from "./states/settings"; +import { ShapezGameAnalytics } from "./platform/browser/game_analytics"; +import { RestrictionManager } from "./core/restriction_manager"; + +/** + * @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 +let pageHiddenPropName, pageVisibilityEventName; +if (typeof document.hidden !== "undefined") { + // Opera 12.10 and Firefox 18 and later support + pageHiddenPropName = "hidden"; + pageVisibilityEventName = "visibilitychange"; + // @ts-ignore +} else if (typeof document.msHidden !== "undefined") { + pageHiddenPropName = "msHidden"; + pageVisibilityEventName = "msvisibilitychange"; + // @ts-ignore +} else if (typeof document.webkitHidden !== "undefined") { + pageHiddenPropName = "webkitHidden"; + pageVisibilityEventName = "webkitvisibilitychange"; +} + +export class Application { + constructor() { + assert(!GLOBAL_APP, "Tried to construct application twice"); + logger.log("Creating application, platform =", getPlatformName()); + setGlobalApp(this); + + this.unloaded = false; + + // Global stuff + this.settings = new ApplicationSettings(this); + this.ticker = new AnimationFrame(); + this.stateMgr = new StateManager(this); + this.savegameMgr = new SavegameManager(this); + this.inputMgr = new InputDistributor(this); + this.backgroundResourceLoader = new BackgroundResourcesLoader(this); + + // Restrictions (Like demo etc) + this.restrictionMgr = new RestrictionManager(this); + + // Platform dependent stuff + + /** @type {StorageInterface} */ + this.storage = null; + + /** @type {SoundInterface} */ + this.sound = null; + + /** @type {PlatformWrapperInterface} */ + this.platformWrapper = null; + + /** @type {AdProviderInterface} */ + this.adProvider = null; + + /** @type {AnalyticsInterface} */ + this.analytics = null; + + /** @type {GameAnalyticsInterface} */ + this.gameAnalytics = null; + + this.initPlatformDependentInstances(); + + // Track if the window is focused (only relevant for browser) + this.focused = true; + + // Track if the window is visible + this.pageVisible = true; + + // Track if the app is paused (cordova) + this.applicationPaused = false; + + /** @type {TypedTrackedState} */ + this.trackedIsRenderable = new TrackedState(this.onAppRenderableStateChanged, this); + + // Dimensions + this.screenWidth = 0; + this.screenHeight = 0; + + // Store the timestamp where we last checked for a screen resize, since orientationchange is unreliable with cordova + this.lastResizeCheck = null; + + // Store the mouse position, or null if not available + /** @type {Vector|null} */ + this.mousePosition = null; + } + + /** + * Initializes all platform instances + */ + initPlatformDependentInstances() { + logger.log("Creating platform dependent instances (standalone=", G_IS_STANDALONE, ")"); + + if (G_IS_STANDALONE) { + this.platformWrapper = new PlatformWrapperImplElectron(this); + } else { + this.platformWrapper = new PlatformWrapperImplBrowser(this); + } + + // Start with empty ad provider + this.adProvider = new NoAdProvider(this); + this.sound = new SoundImplBrowser(this); + this.analytics = new GoogleAnalyticsImpl(this); + this.gameAnalytics = new ShapezGameAnalytics(this); + } + + /** + * Registers all game states + */ + registerStates() { + /** @type {Array} */ + const states = [ + PreloadState, + MobileWarningState, + MainMenuState, + InGameState, + SettingsState, + KeybindingsState, + AboutState, + ChangelogState, + ]; + + for (let i = 0; i < states.length; ++i) { + this.stateMgr.register(states[i]); + } + } + + /** + * Registers all event listeners + */ + registerEventListeners() { + window.addEventListener("focus", this.onFocus.bind(this)); + window.addEventListener("blur", this.onBlur.bind(this)); + + window.addEventListener("resize", () => this.checkResize(), true); + window.addEventListener("orientationchange", () => this.checkResize(), true); + + if (!G_IS_MOBILE_APP && !IS_MOBILE) { + window.addEventListener("mousemove", this.handleMousemove.bind(this)); + window.addEventListener("mouseout", this.handleMousemove.bind(this)); + window.addEventListener("mouseover", this.handleMousemove.bind(this)); + window.addEventListener("mouseleave", this.handleMousemove.bind(this)); + } + + // Unload events + window.addEventListener("beforeunload", this.onBeforeUnload.bind(this), true); + window.addEventListener("unload", this.onUnload.bind(this), true); + + document.addEventListener(pageVisibilityEventName, this.handleVisibilityChange.bind(this), false); + + // Track touches so we can update the focus appropriately + document.addEventListener("touchstart", this.updateFocusAfterUserInteraction.bind(this), true); + document.addEventListener("touchend", this.updateFocusAfterUserInteraction.bind(this), true); + } + + /** + * Checks the focus after a touch + * @param {TouchEvent} event + */ + updateFocusAfterUserInteraction(event) { + const target = /** @type {HTMLElement} */ (event.target); + if (!target || !target.tagName) { + // Safety check + logger.warn("Invalid touchstart/touchend event:", event); + return; + } + + // When clicking an element which is not the currently focused one, defocus it + if (target !== document.activeElement) { + // @ts-ignore + if (document.activeElement.blur) { + // @ts-ignore + document.activeElement.blur(); + } + } + + // If we click an input field, focus it now + if (target.tagName.toLowerCase() === "input") { + // We *really* need the focus + waitNextFrame().then(() => target.focus()); + } + } + + /** + * Handles a page visibility change event + * @param {Event} event + */ + handleVisibilityChange(event) { + window.focus(); + const pageVisible = !document[pageHiddenPropName]; + if (pageVisible !== this.pageVisible) { + this.pageVisible = pageVisible; + logger.log("Visibility changed:", this.pageVisible); + this.trackedIsRenderable.set(this.isRenderable()); + } + } + + /** + * Handles a mouse move event + * @param {MouseEvent} event + */ + handleMousemove(event) { + this.mousePosition = new Vector(event.clientX, event.clientY); + } + + /** + * Internal on focus handler + */ + onFocus() { + this.focused = true; + } + + /** + * Internal blur handler + */ + onBlur() { + this.focused = false; + } + + /** + * Returns if the app is currently visible + */ + isRenderable() { + return !this.applicationPaused && this.pageVisible; + } + + onAppRenderableStateChanged(renderable) { + logger.log("Application renderable:", renderable); + window.focus(); + const currentState = this.stateMgr.getCurrentState(); + if (!renderable) { + if (currentState) { + currentState.onAppPause(); + } + } else { + if (currentState) { + currentState.onAppResume(); + } + this.checkResize(); + } + + this.sound.onPageRenderableStateChanged(renderable); + } + + /** + * Internal unload handler + */ + onUnload(event) { + if (!this.unloaded) { + logSection("UNLOAD HANDLER", "#f77"); + this.unloaded = true; + const currentState = this.stateMgr.getCurrentState(); + if (currentState) { + currentState.onBeforeExit(); + } + this.deinitialize(); + } + } + + /** + * Internal before-unload handler + */ + onBeforeUnload(event) { + logSection("BEFORE UNLOAD HANDLER", "#f77"); + const currentState = this.stateMgr.getCurrentState(); + + if (!G_IS_DEV && currentState && currentState.getHasUnloadConfirmation()) { + if (!G_IS_STANDALONE) { + // Need to show a "Are you sure you want to exit" + event.preventDefault(); + event.returnValue = "Are you sure you want to exit?"; + } + } + } + + /** + * Boots the application + */ + boot() { + console.log("Booting ..."); + this.registerStates(); + this.registerEventListeners(); + + Loader.linkAppAfterBoot(this); + + // Check for mobile + if (IS_MOBILE) { + this.stateMgr.moveToState("MobileWarningState"); + } else { + this.stateMgr.moveToState("PreloadState"); + } + + // Starting rendering + this.ticker.frameEmitted.add(this.onFrameEmitted, this); + this.ticker.bgFrameEmitted.add(this.onBackgroundFrame, this); + this.ticker.start(); + + window.focus(); + } + + /** + * Deinitializes the application + */ + deinitialize() { + return this.sound.deinitialize(); + } + + /** + * Background frame update callback + * @param {number} dt + */ + onBackgroundFrame(dt) { + if (this.isRenderable()) { + return; + } + + const currentState = this.stateMgr.getCurrentState(); + if (currentState) { + currentState.onBackgroundTick(dt); + } + } + + /** + * Frame update callback + * @param {number} dt + */ + onFrameEmitted(dt) { + if (!this.isRenderable()) { + return; + } + + const time = performance.now(); + + // Periodically check for resizes, this is expensive (takes 2-3ms so only do it once in a while!) + if (!this.lastResizeCheck || time - this.lastResizeCheck > 1000) { + this.checkResize(); + this.lastResizeCheck = time; + } + + const currentState = this.stateMgr.getCurrentState(); + if (currentState) { + currentState.onRender(dt); + } + } + + /** + * Checks if the app resized. Only does this once in a while + * @param {boolean} forceUpdate Forced update of the dimensions + */ + checkResize(forceUpdate = false) { + const w = window.innerWidth; + const h = window.innerHeight; + if (this.screenWidth !== w || this.screenHeight !== h || forceUpdate) { + this.screenWidth = w; + this.screenHeight = h; + const currentState = this.stateMgr.getCurrentState(); + if (currentState) { + currentState.onResized(this.screenWidth, this.screenHeight); + } + + const scale = this.getEffectiveUiScale(); + waitNextFrame().then(() => document.documentElement.style.setProperty("--ui-scale", `${scale}`)); + window.focus(); + } + } + + /** + * Returns the effective ui sclae + */ + getEffectiveUiScale() { + return this.platformWrapper.getUiScale() * this.settings.getInterfaceScaleValue(); + } + + /** + * Callback after ui scale has changed + */ + updateAfterUiScaleChanged() { + this.checkResize(true); + } +} diff --git a/src/js/changelog.js b/src/js/changelog.js index 16a9d692..84f0bc07 100644 --- a/src/js/changelog.js +++ b/src/js/changelog.js @@ -1,298 +1,284 @@ -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.1", + date: "unreleased", + entries: [ + "Fixed stacking bug for level 26 which required restarting the game", + "Fix reward notification being too long sometimes (by LeopoldTal)", + "Updated translations", + ], + }, + { + version: "1.2.0", + date: "09.10.2020", + entries: [ + "⚠️⚠️This update is HUGE, view the full changelog here! ⚠️⚠️", + ], + }, + { + 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 separate '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..bbd37036 100644 --- a/src/js/core/background_resources_loader.js +++ b/src/js/core/background_resources_loader.js @@ -1,214 +1,232 @@ -/* typehints:start */ -import { Application } from "../application"; -/* typehints:end */ - -import { Loader } from "./loader"; -import { createLogger } from "./logging"; -import { Signal } from "./signal"; -import { SOUNDS, MUSIC } from "../platform/sound"; -import { AtlasDefinition, atlasFiles } from "./atlas_definitions"; - -const logger = createLogger("background_loader"); - -const essentialMainMenuSprites = [ - "logo.png", - ...G_ALL_UI_IMAGES.filter(src => src.startsWith("ui/") && src.indexOf(".gif") < 0), -]; -const essentialMainMenuSounds = [ - SOUNDS.uiClick, - SOUNDS.uiError, - SOUNDS.dialogError, - SOUNDS.dialogOk, - SOUNDS.swishShow, - SOUNDS.swishHide, -]; - -const essentialBareGameAtlases = atlasFiles; -const essentialBareGameSprites = G_ALL_UI_IMAGES.filter(src => src.indexOf(".gif") < 0); -const essentialBareGameSounds = [MUSIC.theme]; - -const additionalGameSprites = []; -// @ts-ignore -const additionalGameSounds = [...Object.values(SOUNDS), ...Object.values(MUSIC)]; - -export class BackgroundResourcesLoader { - /** - * - * @param {Application} app - */ - constructor(app) { - this.app = app; - - this.registerReady = false; - this.mainMenuReady = false; - this.bareGameReady = false; - this.additionalReady = false; - - this.signalMainMenuLoaded = new Signal(); - this.signalBareGameLoaded = new Signal(); - this.signalAdditionalLoaded = new Signal(); - - this.numAssetsLoaded = 0; - this.numAssetsToLoadTotal = 0; - - // Avoid loading stuff twice - this.spritesLoaded = []; - this.soundsLoaded = []; - } - - getNumAssetsLoaded() { - return this.numAssetsLoaded; - } - - getNumAssetsTotal() { - return this.numAssetsToLoadTotal; - } - - getPromiseForMainMenu() { - if (this.mainMenuReady) { - return Promise.resolve(); - } - - return new Promise(resolve => { - this.signalMainMenuLoaded.add(resolve); - }); - } - - getPromiseForBareGame() { - if (this.bareGameReady) { - return Promise.resolve(); - } - - return new Promise(resolve => { - this.signalBareGameLoaded.add(resolve); - }); - } - - startLoading() { - this.internalStartLoadingEssentialsForMainMenu(); - } - - internalStartLoadingEssentialsForMainMenu() { - logger.log("⏰ Start load: main menu"); - this.internalLoadSpritesAndSounds(essentialMainMenuSprites, essentialMainMenuSounds) - .catch(err => { - logger.warn("⏰ Failed to load essentials for main menu:", err); - }) - .then(() => { - logger.log("⏰ Finish load: main menu"); - this.mainMenuReady = true; - this.signalMainMenuLoaded.dispatch(); - this.internalStartLoadingEssentialsForBareGame(); - }); - } - - internalStartLoadingEssentialsForBareGame() { - logger.log("⏰ Start load: bare game"); - this.internalLoadSpritesAndSounds( - essentialBareGameSprites, - essentialBareGameSounds, - essentialBareGameAtlases - ) - .catch(err => { - logger.warn("⏰ Failed to load essentials for bare game:", err); - }) - .then(() => { - logger.log("⏰ Finish load: bare game"); - Loader.createAtlasLinks(); - this.bareGameReady = true; - this.signalBareGameLoaded.dispatch(); - this.internalStartLoadingAdditionalGameAssets(); - }); - } - - internalStartLoadingAdditionalGameAssets() { - const additionalAtlases = []; - logger.log("⏰ Start load: additional assets (", additionalAtlases.length, "images)"); - this.internalLoadSpritesAndSounds(additionalGameSprites, additionalGameSounds, additionalAtlases) - .catch(err => { - logger.warn("⏰ Failed to load additional assets:", err); - }) - .then(() => { - logger.log("⏰ Finish load: additional assets"); - this.additionalReady = true; - this.signalAdditionalLoaded.dispatch(); - }); - } - - /** - * @param {Array} sprites - * @param {Array} sounds - * @param {Array} atlases - * @returns {Promise} - */ - internalLoadSpritesAndSounds(sprites, sounds, atlases = []) { - this.numAssetsToLoadTotal = sprites.length + sounds.length + atlases.length; - this.numAssetsLoaded = 0; - - let promises = []; - - for (let i = 0; i < sounds.length; ++i) { - if (this.soundsLoaded.indexOf(sounds[i]) >= 0) { - // Already loaded - continue; - } - - this.soundsLoaded.push(sounds[i]); - promises.push( - this.app.sound - .loadSound(sounds[i]) - .catch(err => { - logger.warn("Failed to load sound:", sounds[i]); - }) - .then(() => { - this.numAssetsLoaded++; - }) - ); - } - - for (let i = 0; i < sprites.length; ++i) { - if (this.spritesLoaded.indexOf(sprites[i]) >= 0) { - // Already loaded - continue; - } - this.spritesLoaded.push(sprites[i]); - promises.push( - Loader.preloadCSSSprite(sprites[i]) - .catch(err => { - logger.warn("Failed to load css sprite:", sprites[i]); - }) - .then(() => { - this.numAssetsLoaded++; - }) - ); - } - - for (let i = 0; i < atlases.length; ++i) { - const atlas = atlases[i]; - promises.push( - Loader.preloadAtlas(atlas) - .catch(err => { - logger.warn("Failed to load atlas:", atlas.sourceFileName); - }) - .then(() => { - this.numAssetsLoaded++; - }) - ); - } - - return ( - Promise.all(promises) - - // // Remove some pressure by waiting a bit - // .then(() => { - // return new Promise(resolve => { - // setTimeout(resolve, 200); - // }); - // }) - .then(() => { - this.numAssetsToLoadTotal = 0; - this.numAssetsLoaded = 0; - }) - ); - } -} +/* typehints:start */ +import { Application } from "../application"; +/* typehints:end */ + +import { Loader } from "./loader"; +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"; +import { cachebust } from "./cachebust"; + +const logger = createLogger("background_loader"); + +const essentialMainMenuSprites = [ + "logo.png", + ...G_ALL_UI_IMAGES.filter(src => src.startsWith("ui/") && src.indexOf(".gif") < 0), +]; +const essentialMainMenuSounds = [ + SOUNDS.uiClick, + SOUNDS.uiError, + SOUNDS.dialogError, + SOUNDS.dialogOk, + SOUNDS.swishShow, + SOUNDS.swishHide, +]; + +const essentialBareGameAtlases = atlasFiles; +const essentialBareGameSprites = G_ALL_UI_IMAGES.filter(src => src.indexOf(".gif") < 0); +const essentialBareGameSounds = [MUSIC.theme]; + +const additionalGameSprites = []; +// @ts-ignore +const additionalGameSounds = [...Object.values(SOUNDS), ...Object.values(MUSIC)]; + +export class BackgroundResourcesLoader { + /** + * + * @param {Application} app + */ + constructor(app) { + this.app = app; + + this.registerReady = false; + this.mainMenuReady = false; + this.bareGameReady = false; + this.additionalReady = false; + + this.signalMainMenuLoaded = new Signal(); + this.signalBareGameLoaded = new Signal(); + this.signalAdditionalLoaded = new Signal(); + + this.numAssetsLoaded = 0; + this.numAssetsToLoadTotal = 0; + + // Avoid loading stuff twice + this.spritesLoaded = []; + this.soundsLoaded = []; + } + + getNumAssetsLoaded() { + return this.numAssetsLoaded; + } + + getNumAssetsTotal() { + return this.numAssetsToLoadTotal; + } + + getPromiseForMainMenu() { + if (this.mainMenuReady) { + return Promise.resolve(); + } + + return new Promise(resolve => { + this.signalMainMenuLoaded.add(resolve); + }); + } + + getPromiseForBareGame() { + if (this.bareGameReady) { + return Promise.resolve(); + } + + return new Promise(resolve => { + this.signalBareGameLoaded.add(resolve); + }); + } + + startLoading() { + this.internalStartLoadingEssentialsForMainMenu(); + } + + internalStartLoadingEssentialsForMainMenu() { + logger.log("⏰ Start load: main menu"); + this.internalLoadSpritesAndSounds(essentialMainMenuSprites, essentialMainMenuSounds) + .catch(err => { + logger.warn("⏰ Failed to load essentials for main menu:", err); + }) + .then(() => { + logger.log("⏰ Finish load: main menu"); + this.mainMenuReady = true; + this.signalMainMenuLoaded.dispatch(); + this.internalStartLoadingEssentialsForBareGame(); + }); + } + + internalStartLoadingEssentialsForBareGame() { + logger.log("⏰ Start load: bare game"); + this.internalLoadSpritesAndSounds( + essentialBareGameSprites, + essentialBareGameSounds, + essentialBareGameAtlases + ) + .then(() => this.internalPreloadCss("async-resources.scss")) + .catch(err => { + logger.warn("⏰ Failed to load essentials for bare game:", err); + }) + .then(() => { + logger.log("⏰ Finish load: bare game"); + this.bareGameReady = true; + initBuildingCodesAfterResourcesLoaded(); + this.signalBareGameLoaded.dispatch(); + this.internalStartLoadingAdditionalGameAssets(); + }); + } + + internalStartLoadingAdditionalGameAssets() { + const additionalAtlases = []; + logger.log("⏰ Start load: additional assets (", additionalAtlases.length, "images)"); + this.internalLoadSpritesAndSounds(additionalGameSprites, additionalGameSounds, additionalAtlases) + .catch(err => { + logger.warn("⏰ Failed to load additional assets:", err); + }) + .then(() => { + logger.log("⏰ Finish load: additional assets"); + this.additionalReady = true; + this.signalAdditionalLoaded.dispatch(); + }); + } + + internalPreloadCss(name) { + return new Promise((resolve, reject) => { + const link = document.createElement("link"); + + link.onload = resolve; + link.onerror = reject; + + link.setAttribute("rel", "stylesheet"); + link.setAttribute("media", "all"); + link.setAttribute("type", "text/css"); + link.setAttribute("href", cachebust("async-resources.css")); + document.head.appendChild(link); + }); + } + + /** + * @param {Array} sprites + * @param {Array} sounds + * @param {Array} atlases + * @returns {Promise} + */ + internalLoadSpritesAndSounds(sprites, sounds, atlases = []) { + this.numAssetsToLoadTotal = sprites.length + sounds.length + atlases.length; + this.numAssetsLoaded = 0; + + let promises = []; + + for (let i = 0; i < sounds.length; ++i) { + if (this.soundsLoaded.indexOf(sounds[i]) >= 0) { + // Already loaded + continue; + } + + this.soundsLoaded.push(sounds[i]); + promises.push( + this.app.sound + .loadSound(sounds[i]) + .catch(err => { + logger.warn("Failed to load sound:", sounds[i]); + }) + .then(() => { + this.numAssetsLoaded++; + }) + ); + } + + for (let i = 0; i < sprites.length; ++i) { + if (this.spritesLoaded.indexOf(sprites[i]) >= 0) { + // Already loaded + continue; + } + this.spritesLoaded.push(sprites[i]); + promises.push( + Loader.preloadCSSSprite(sprites[i]) + .catch(err => { + logger.warn("Failed to load css sprite:", sprites[i]); + }) + .then(() => { + this.numAssetsLoaded++; + }) + ); + } + + for (let i = 0; i < atlases.length; ++i) { + const atlas = atlases[i]; + promises.push( + Loader.preloadAtlas(atlas) + .catch(err => { + logger.warn("Failed to load atlas:", atlas.sourceFileName); + }) + .then(() => { + this.numAssetsLoaded++; + }) + ); + } + + return ( + Promise.all(promises) + + // // Remove some pressure by waiting a bit + // .then(() => { + // return new Promise(resolve => { + // setTimeout(resolve, 200); + // }); + // }) + .then(() => { + this.numAssetsToLoadTotal = 0; + this.numAssetsLoaded = 0; + }) + ); + } +} diff --git a/src/js/core/buffer_maintainer.js b/src/js/core/buffer_maintainer.js index c92a92a5..1d506803 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 = 0.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; } /** @@ -61,27 +86,29 @@ export class BufferMaintainer { // Make sure our backlog never gets too big clearBufferBacklog(); - const bufferStats = getBufferStats(); - const mbUsed = round1Digit(bufferStats.vramUsage / (1024 * 1024)); - logger.log( - "GC: Remove", - (deletedKeys + "").padStart(4), - ", Remain", - (totalKeys + "").padStart(4), - "(", - (bufferStats.bufferCount + "").padStart(4), - "total", - ")", + // if (G_IS_DEV) { + // const bufferStats = getBufferStats(); + // const mbUsed = round1Digit(bufferStats.vramUsage / (1024 * 1024)); + // logger.log( + // "GC: Remove", + // (deletedKeys + "").padStart(4), + // ", Remain", + // (totalKeys + "").padStart(4), + // "(", + // (bufferStats.bufferCount + "").padStart(4), + // "total", + // ")", - "(", - (bufferStats.backlog + "").padStart(4), - "backlog", - ")", + // "(", + // (bufferStats.backlogSize + "").padStart(4), + // "backlog", + // ")", - "VRAM:", - mbUsed, - "MB" - ); + // "VRAM:", + // mbUsed, + // "MB" + // ); + // } ++this.iterationIndex; } @@ -95,15 +122,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/buffer_utils.js b/src/js/core/buffer_utils.js index 228560bc..310c315f 100644 --- a/src/js/core/buffer_utils.js +++ b/src/js/core/buffer_utils.js @@ -25,17 +25,43 @@ export function disableImageSmoothing(context) { context.webkitImageSmoothingEnabled = false; } -const registeredCanvas = []; -const freeCanvasList = []; +/** + * @typedef {{ + * canvas: HTMLCanvasElement, + * context: CanvasRenderingContext2D + * }} CanvasCacheEntry + */ -let vramUsage = 0; -let bufferCount = 0; +/** + * @type {Array} + */ +const registeredCanvas = []; + +/** + * Buckets for each width * height combination + * @type {Map>} + */ +const freeCanvasBuckets = new Map(); + +/** + * Track statistics + */ +const stats = { + vramUsage: 0, + backlogVramUsage: 0, + bufferCount: 0, + numReused: 0, + numCreated: 0, +}; /** * * @param {HTMLCanvasElement} canvas */ export function getBufferVramUsageBytes(canvas) { + assert(canvas, "no canvas given"); + assert(Number.isFinite(canvas.width), "bad canvas width: " + canvas.width); + assert(Number.isFinite(canvas.height), "bad canvas height" + canvas.height); return canvas.width * canvas.height * 4; } @@ -43,17 +69,31 @@ export function getBufferVramUsageBytes(canvas) { * Returns stats on the allocated buffers */ export function getBufferStats() { + let numBuffersFree = 0; + freeCanvasBuckets.forEach(bucket => { + numBuffersFree += bucket.length; + }); + return { - vramUsage, - bufferCount, - backlog: freeCanvasList.length, + ...stats, + backlogKeys: freeCanvasBuckets.size, + backlogSize: numBuffersFree, }; } +/** + * Clears the backlog buffers if they grew too much + */ export function clearBufferBacklog() { - while (freeCanvasList.length > 50) { - freeCanvasList.pop(); - } + freeCanvasBuckets.forEach(bucket => { + while (bucket.length > 500) { + const entry = bucket[bucket.length - 1]; + stats.backlogVramUsage -= getBufferVramUsageBytes(entry.canvas); + delete entry.canvas; + delete entry.context; + bucket.pop(); + } + }); } /** @@ -84,53 +124,29 @@ export function makeOffscreenBuffer(w, h, { smooth = true, reusable = true, labe let canvas = null; let context = null; - let bestMatchingOne = null; - let bestMatchingPixelsDiff = 1e50; - - const currentPixels = w * h; - // Ok, search in cache first - for (let i = 0; i < freeCanvasList.length; ++i) { - const { canvas: useableCanvas, context: useableContext } = freeCanvasList[i]; + const bucket = freeCanvasBuckets.get(w * h) || []; + + for (let i = 0; i < bucket.length; ++i) { + const { canvas: useableCanvas, context: useableContext } = bucket[i]; if (useableCanvas.width === w && useableCanvas.height === h) { // Ok we found one canvas = useableCanvas; context = useableContext; - fastArrayDelete(freeCanvasList, i); + // Restore past state + context.restore(); + context.save(); + context.clearRect(0, 0, canvas.width, canvas.height); + + delete canvas.style.width; + delete canvas.style.height; + + stats.numReused++; + stats.backlogVramUsage -= getBufferVramUsageBytes(canvas); + fastArrayDelete(bucket, i); break; } - - const otherPixels = useableCanvas.width * useableCanvas.height; - const diff = Math.abs(otherPixels - currentPixels); - if (diff < bestMatchingPixelsDiff) { - bestMatchingPixelsDiff = diff; - bestMatchingOne = { - canvas: useableCanvas, - context: useableContext, - index: i, - }; - } - } - - // Ok none matching, reuse one though - if (!canvas && bestMatchingOne) { - canvas = bestMatchingOne.canvas; - context = bestMatchingOne.context; - canvas.width = w; - canvas.height = h; - fastArrayDelete(freeCanvasList, bestMatchingOne.index); - } - - // Reset context - if (context) { - // Restore past state - context.restore(); - context.save(); - context.clearRect(0, 0, canvas.width, canvas.height); - - delete canvas.style.width; - delete canvas.style.height; } // None found , create new one @@ -138,6 +154,8 @@ export function makeOffscreenBuffer(w, h, { smooth = true, reusable = true, labe canvas = document.createElement("canvas"); context = canvas.getContext("2d" /*, { alpha } */); + stats.numCreated++; + canvas.width = w; canvas.height = h; @@ -145,6 +163,7 @@ export function makeOffscreenBuffer(w, h, { smooth = true, reusable = true, labe context.save(); } + // @ts-ignore canvas.label = label; if (smooth) { @@ -167,8 +186,9 @@ export function makeOffscreenBuffer(w, h, { smooth = true, reusable = true, labe export function registerCanvas(canvas, context) { registeredCanvas.push({ canvas, context }); - bufferCount += 1; - vramUsage += getBufferVramUsageBytes(canvas); + stats.bufferCount += 1; + const bytesUsed = getBufferVramUsageBytes(canvas); + stats.vramUsage += bytesUsed; } /** @@ -180,6 +200,7 @@ export function freeCanvas(canvas) { let index = -1; let data = null; + for (let i = 0; i < registeredCanvas.length; ++i) { if (registeredCanvas[i].canvas === canvas) { index = i; @@ -193,8 +214,18 @@ export function freeCanvas(canvas) { return; } fastArrayDelete(registeredCanvas, index); - freeCanvasList.push(data); - bufferCount -= 1; - vramUsage -= getBufferVramUsageBytes(canvas); + const key = canvas.width * canvas.height; + const bucket = freeCanvasBuckets.get(key); + if (bucket) { + bucket.push(data); + } else { + freeCanvasBuckets.set(key, [data]); + } + + stats.bufferCount -= 1; + + const bytesUsed = getBufferVramUsageBytes(canvas); + stats.vramUsage -= bytesUsed; + stats.backlogVramUsage += bytesUsed; } diff --git a/src/js/core/click_detector.js b/src/js/core/click_detector.js index ea6abf48..fb62f0f1 100644 --- a/src/js/core/click_detector.js +++ b/src/js/core/click_detector.js @@ -1,467 +1,465 @@ -import { createLogger } from "../core/logging"; -import { Signal } from "../core/signal"; -import { fastArrayDelete, fastArrayDeleteValueIfContained } from "./utils"; -import { Vector } from "./vector"; -import { IS_MOBILE, SUPPORT_TOUCH } from "./config"; -import { SOUNDS } from "../platform/sound"; -import { GLOBAL_APP } from "./globals"; - -const logger = createLogger("click_detector"); - -export const MAX_MOVE_DISTANCE_PX = IS_MOBILE ? 20 : 80; - -// For debugging -const registerClickDetectors = G_IS_DEV && true; -if (registerClickDetectors) { - /** @type {Array} */ - window.activeClickDetectors = []; -} - -// Store active click detectors so we can cancel them -/** @type {Array} */ -const ongoingClickDetectors = []; - -// Store when the last touch event was registered, to avoid accepting a touch *and* a click event - -export let clickDetectorGlobals = { - lastTouchTime: -1000, -}; - -/** - * Click detector creation payload typehints - * @typedef {{ - * consumeEvents?: boolean, - * preventDefault?: boolean, - * applyCssClass?: string, - * captureTouchmove?: boolean, - * targetOnly?: boolean, - * maxDistance?: number, - * clickSound?: string, - * preventClick?: boolean, - * }} ClickDetectorConstructorArgs - */ - -// Detects clicks -export class ClickDetector { - /** - * - * @param {Element} element - * @param {object} param1 - * @param {boolean=} param1.consumeEvents Whether to call stopPropagation - * (Useful for nested elements where the parent has a click handler as wel) - * @param {boolean=} param1.preventDefault Whether to call preventDefault (Usually makes the handler faster) - * @param {string=} param1.applyCssClass The css class to add while the element is pressed - * @param {boolean=} param1.captureTouchmove Whether to capture touchmove events as well - * @param {boolean=} param1.targetOnly Whether to also accept clicks on child elements (e.target !== element) - * @param {number=} param1.maxDistance The maximum distance in pixels to accept clicks - * @param {string=} param1.clickSound Sound key to play on touchdown - * @param {boolean=} param1.preventClick Whether to prevent click events - */ - constructor( - element, - { - consumeEvents = false, - preventDefault = true, - applyCssClass = "pressed", - captureTouchmove = false, - targetOnly = false, - maxDistance = MAX_MOVE_DISTANCE_PX, - clickSound = SOUNDS.uiClick, - preventClick = false, - } - ) { - assert(element, "No element given!"); - this.clickDownPosition = null; - - this.consumeEvents = consumeEvents; - this.preventDefault = preventDefault; - this.applyCssClass = applyCssClass; - this.captureTouchmove = captureTouchmove; - this.targetOnly = targetOnly; - this.clickSound = clickSound; - this.maxDistance = maxDistance; - this.preventClick = preventClick; - - // Signals - this.click = new Signal(); - this.rightClick = new Signal(); - this.touchstart = new Signal(); - this.touchmove = new Signal(); - this.touchend = new Signal(); - this.touchcancel = new Signal(); - - // Simple signals which just receive the touch position - this.touchstartSimple = new Signal(); - this.touchmoveSimple = new Signal(); - this.touchendSimple = new Signal(); - - // Store time of touch start - this.clickStartTime = null; - - // A click can be cancelled if another detector registers a click - this.cancelled = false; - - this.internalBindTo(/** @type {HTMLElement} */ (element)); - } - - /** - * Cleans up all event listeners of this detector - */ - cleanup() { - if (this.element) { - if (registerClickDetectors) { - const index = window.activeClickDetectors.indexOf(this); - if (index < 0) { - logger.error("Click detector cleanup but is not active"); - } else { - window.activeClickDetectors.splice(index, 1); - } - } - const options = this.internalGetEventListenerOptions(); - - if (SUPPORT_TOUCH) { - this.element.removeEventListener("touchstart", this.handlerTouchStart, options); - this.element.removeEventListener("touchend", this.handlerTouchEnd, options); - this.element.removeEventListener("touchcancel", this.handlerTouchCancel, options); - } - - this.element.removeEventListener("mouseup", this.handlerTouchStart, options); - this.element.removeEventListener("mousedown", this.handlerTouchEnd, options); - this.element.removeEventListener("mouseout", this.handlerTouchCancel, options); - - if (this.captureTouchmove) { - if (SUPPORT_TOUCH) { - this.element.removeEventListener("touchmove", this.handlerTouchMove, options); - } - this.element.removeEventListener("mousemove", this.handlerTouchMove, options); - } - - if (this.preventClick) { - this.element.removeEventListener("click", this.handlerPreventClick, options); - } - - this.click.removeAll(); - this.touchstart.removeAll(); - this.touchmove.removeAll(); - this.touchend.removeAll(); - this.touchcancel.removeAll(); - - // TODO: Remove pointer captures - - this.element = null; - } - } - - // INTERNAL METHODS - - /** - * - * @param {Event} event - */ - internalPreventClick(event) { - window.focus(); - event.preventDefault(); - } - - /** - * Internal method to get the options to pass to an event listener - */ - internalGetEventListenerOptions() { - return { - capture: this.consumeEvents, - passive: !this.preventDefault, - }; - } - - /** - * Binds the click detector to an element - * @param {HTMLElement} element - */ - internalBindTo(element) { - const options = this.internalGetEventListenerOptions(); - - this.handlerTouchStart = this.internalOnPointerDown.bind(this); - this.handlerTouchEnd = this.internalOnPointerEnd.bind(this); - this.handlerTouchMove = this.internalOnPointerMove.bind(this); - this.handlerTouchCancel = this.internalOnTouchCancel.bind(this); - - if (this.preventClick) { - this.handlerPreventClick = this.internalPreventClick.bind(this); - element.addEventListener("click", this.handlerPreventClick, options); - } - - if (SUPPORT_TOUCH) { - element.addEventListener("touchstart", this.handlerTouchStart, options); - element.addEventListener("touchend", this.handlerTouchEnd, options); - element.addEventListener("touchcancel", this.handlerTouchCancel, options); - } - - element.addEventListener("mousedown", this.handlerTouchStart, options); - element.addEventListener("mouseup", this.handlerTouchEnd, options); - element.addEventListener("mouseout", this.handlerTouchCancel, options); - - if (this.captureTouchmove) { - if (SUPPORT_TOUCH) { - element.addEventListener("touchmove", this.handlerTouchMove, options); - } - element.addEventListener("mousemove", this.handlerTouchMove, options); - } - - if (registerClickDetectors) { - window.activeClickDetectors.push(this); - } - this.element = element; - } - - /** - * Returns if the bound element is currently in the DOM. - */ - internalIsDomElementAttached() { - return this.element && document.documentElement.contains(this.element); - } - - /** - * Checks if the given event is relevant for this detector - * @param {TouchEvent|MouseEvent} event - */ - internalEventPreHandler(event, expectedRemainingTouches = 1) { - if (!this.element) { - // Already cleaned up - return false; - } - - if (this.targetOnly && event.target !== this.element) { - // Clicked a child element - return false; - } - - // Stop any propagation and defaults if configured - if (this.consumeEvents && event.cancelable) { - event.stopPropagation(); - } - - if (this.preventDefault && event.cancelable) { - event.preventDefault(); - } - - if (window.TouchEvent && event instanceof TouchEvent) { - clickDetectorGlobals.lastTouchTime = performance.now(); - - // console.log("Got touches", event.targetTouches.length, "vs", expectedRemainingTouches); - if (event.targetTouches.length !== expectedRemainingTouches) { - return false; - } - } - - if (event instanceof MouseEvent) { - if (performance.now() - clickDetectorGlobals.lastTouchTime < 1000.0) { - return false; - } - } - - return true; - } - - /** - * Extracts the mous position from an event - * @param {TouchEvent|MouseEvent} event - * @returns {Vector} The client space position - */ - static extractPointerPosition(event) { - if (window.TouchEvent && event instanceof TouchEvent) { - if (event.changedTouches.length !== 1) { - logger.warn( - "Got unexpected target touches:", - event.targetTouches.length, - "->", - event.targetTouches - ); - return new Vector(0, 0); - } - - const touch = event.changedTouches[0]; - return new Vector(touch.clientX, touch.clientY); - } - - if (event instanceof MouseEvent) { - return new Vector(event.clientX, event.clientY); - } - - assertAlways(false, "Got unknown event: " + event); - - return new Vector(0, 0); - } - - /** - * Cacnels all ongoing events on this detector - */ - cancelOngoingEvents() { - if (this.applyCssClass && this.element) { - this.element.classList.remove(this.applyCssClass); - } - this.clickDownPosition = null; - this.clickStartTime = null; - this.cancelled = true; - fastArrayDeleteValueIfContained(ongoingClickDetectors, this); - } - - /** - * Internal pointer down handler - * @param {TouchEvent|MouseEvent} event - */ - internalOnPointerDown(event) { - window.focus(); - - if (!this.internalEventPreHandler(event, 1)) { - return false; - } - - const position = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event); - - if (event instanceof MouseEvent) { - const isRightClick = event.button === 2; - if (isRightClick) { - // Ignore right clicks - this.rightClick.dispatch(position, event); - this.cancelled = true; - this.clickDownPosition = null; - return; - } - } - - if (this.clickDownPosition) { - logger.warn("Ignoring double click"); - return false; - } - - this.cancelled = false; - this.touchstart.dispatch(event); - - // Store where the touch started - this.clickDownPosition = position; - this.clickStartTime = performance.now(); - this.touchstartSimple.dispatch(this.clickDownPosition.x, this.clickDownPosition.y); - - // If we are not currently within a click, register it - if (ongoingClickDetectors.indexOf(this) < 0) { - ongoingClickDetectors.push(this); - } else { - logger.warn("Click detector got pointer down of active pointer twice"); - } - - // If we should apply any classes, do this now - if (this.applyCssClass) { - this.element.classList.add(this.applyCssClass); - } - - // If we should play any sound, do this - if (this.clickSound) { - GLOBAL_APP.sound.playUiSound(this.clickSound); - } - - return false; - } - - /** - * Internal pointer move handler - * @param {TouchEvent|MouseEvent} event - */ - internalOnPointerMove(event) { - if (!this.internalEventPreHandler(event, 1)) { - return false; - } - this.touchmove.dispatch(event); - const pos = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event); - this.touchmoveSimple.dispatch(pos.x, pos.y); - return false; - } - - /** - * Internal pointer end handler - * @param {TouchEvent|MouseEvent} event - */ - internalOnPointerEnd(event) { - window.focus(); - - if (!this.internalEventPreHandler(event, 0)) { - return false; - } - - if (this.cancelled) { - // warn(this, "Not dispatching touchend on cancelled listener"); - return false; - } - - if (event instanceof MouseEvent) { - const isRightClick = event.button === 2; - if (isRightClick) { - return; - } - } - - const index = ongoingClickDetectors.indexOf(this); - if (index < 0) { - logger.warn("Got pointer end but click detector is not in pressed state"); - } else { - fastArrayDelete(ongoingClickDetectors, index); - } - - let dispatchClick = false; - let dispatchClickPos = null; - - // Check for correct down position, otherwise must have pinched or so - if (this.clickDownPosition) { - const pos = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event); - const distance = pos.distance(this.clickDownPosition); - if (!IS_MOBILE || distance <= this.maxDistance) { - dispatchClick = true; - dispatchClickPos = pos; - } else { - console.warn("[ClickDetector] Touch does not count as click:", "(was", distance, ")"); - } - } - - this.clickDownPosition = null; - this.clickStartTime = null; - - if (this.applyCssClass) { - this.element.classList.remove(this.applyCssClass); - } - - // Dispatch in the end to avoid the element getting invalidated - // Also make sure that the element is still in the dom - if (this.internalIsDomElementAttached()) { - this.touchend.dispatch(event); - this.touchendSimple.dispatch(); - - if (dispatchClick) { - const detectors = ongoingClickDetectors.slice(); - for (let i = 0; i < detectors.length; ++i) { - detectors[i].cancelOngoingEvents(); - } - this.click.dispatch(dispatchClickPos, event); - } - } - return false; - } - - /** - * Internal touch cancel handler - * @param {TouchEvent|MouseEvent} event - */ - internalOnTouchCancel(event) { - if (!this.internalEventPreHandler(event, 0)) { - return false; - } - - if (this.cancelled) { - // warn(this, "Not dispatching touchcancel on cancelled listener"); - return false; - } - - this.cancelOngoingEvents(); - this.touchcancel.dispatch(event); - this.touchendSimple.dispatch(event); - return false; - } -} +import { createLogger } from "../core/logging"; +import { Signal } from "../core/signal"; +import { fastArrayDelete, fastArrayDeleteValueIfContained } from "./utils"; +import { Vector } from "./vector"; +import { IS_MOBILE, SUPPORT_TOUCH } from "./config"; +import { SOUNDS } from "../platform/sound"; +import { GLOBAL_APP } from "./globals"; + +const logger = createLogger("click_detector"); + +export const MAX_MOVE_DISTANCE_PX = IS_MOBILE ? 20 : 80; + +// For debugging +const registerClickDetectors = G_IS_DEV && true; +if (registerClickDetectors) { + /** @type {Array} */ + window.activeClickDetectors = []; +} + +// Store active click detectors so we can cancel them +/** @type {Array} */ +const ongoingClickDetectors = []; + +// Store when the last touch event was registered, to avoid accepting a touch *and* a click event + +export let clickDetectorGlobals = { + lastTouchTime: -1000, +}; + +/** + * Click detector creation payload typehints + * @typedef {{ + * consumeEvents?: boolean, + * preventDefault?: boolean, + * applyCssClass?: string, + * captureTouchmove?: boolean, + * targetOnly?: boolean, + * maxDistance?: number, + * clickSound?: string, + * preventClick?: boolean, + * }} ClickDetectorConstructorArgs + */ + +// Detects clicks +export class ClickDetector { + /** + * + * @param {Element} element + * @param {object} param1 + * @param {boolean=} param1.consumeEvents Whether to call stopPropagation + * (Useful for nested elements where the parent has a click handler as wel) + * @param {boolean=} param1.preventDefault Whether to call preventDefault (Usually makes the handler faster) + * @param {string=} param1.applyCssClass The css class to add while the element is pressed + * @param {boolean=} param1.captureTouchmove Whether to capture touchmove events as well + * @param {boolean=} param1.targetOnly Whether to also accept clicks on child elements (e.target !== element) + * @param {number=} param1.maxDistance The maximum distance in pixels to accept clicks + * @param {string=} param1.clickSound Sound key to play on touchdown + * @param {boolean=} param1.preventClick Whether to prevent click events + */ + constructor( + element, + { + consumeEvents = false, + preventDefault = true, + applyCssClass = "pressed", + captureTouchmove = false, + targetOnly = false, + maxDistance = MAX_MOVE_DISTANCE_PX, + clickSound = SOUNDS.uiClick, + preventClick = false, + } + ) { + assert(element, "No element given!"); + this.clickDownPosition = null; + + this.consumeEvents = consumeEvents; + this.preventDefault = preventDefault; + this.applyCssClass = applyCssClass; + this.captureTouchmove = captureTouchmove; + this.targetOnly = targetOnly; + this.clickSound = clickSound; + this.maxDistance = maxDistance; + this.preventClick = preventClick; + + // Signals + this.click = new Signal(); + this.rightClick = new Signal(); + this.touchstart = new Signal(); + this.touchmove = new Signal(); + this.touchend = new Signal(); + this.touchcancel = new Signal(); + + // Simple signals which just receive the touch position + this.touchstartSimple = new Signal(); + this.touchmoveSimple = new Signal(); + this.touchendSimple = new Signal(); + + // Store time of touch start + this.clickStartTime = null; + + // A click can be cancelled if another detector registers a click + this.cancelled = false; + + this.internalBindTo(/** @type {HTMLElement} */ (element)); + } + + /** + * Cleans up all event listeners of this detector + */ + cleanup() { + if (this.element) { + if (registerClickDetectors) { + const index = window.activeClickDetectors.indexOf(this); + if (index < 0) { + logger.error("Click detector cleanup but is not active"); + } else { + window.activeClickDetectors.splice(index, 1); + } + } + const options = this.internalGetEventListenerOptions(); + + if (SUPPORT_TOUCH) { + this.element.removeEventListener("touchstart", this.handlerTouchStart, options); + this.element.removeEventListener("touchend", this.handlerTouchEnd, options); + this.element.removeEventListener("touchcancel", this.handlerTouchCancel, options); + } + + this.element.removeEventListener("mouseup", this.handlerTouchStart, options); + this.element.removeEventListener("mousedown", this.handlerTouchEnd, options); + this.element.removeEventListener("mouseout", this.handlerTouchCancel, options); + + if (this.captureTouchmove) { + if (SUPPORT_TOUCH) { + this.element.removeEventListener("touchmove", this.handlerTouchMove, options); + } + this.element.removeEventListener("mousemove", this.handlerTouchMove, options); + } + + if (this.preventClick) { + this.element.removeEventListener("click", this.handlerPreventClick, options); + } + + this.click.removeAll(); + this.touchstart.removeAll(); + this.touchmove.removeAll(); + this.touchend.removeAll(); + this.touchcancel.removeAll(); + + this.element = null; + } + } + + // INTERNAL METHODS + + /** + * + * @param {Event} event + */ + internalPreventClick(event) { + window.focus(); + event.preventDefault(); + } + + /** + * Internal method to get the options to pass to an event listener + */ + internalGetEventListenerOptions() { + return { + capture: this.consumeEvents, + passive: !this.preventDefault, + }; + } + + /** + * Binds the click detector to an element + * @param {HTMLElement} element + */ + internalBindTo(element) { + const options = this.internalGetEventListenerOptions(); + + this.handlerTouchStart = this.internalOnPointerDown.bind(this); + this.handlerTouchEnd = this.internalOnPointerEnd.bind(this); + this.handlerTouchMove = this.internalOnPointerMove.bind(this); + this.handlerTouchCancel = this.internalOnTouchCancel.bind(this); + + if (this.preventClick) { + this.handlerPreventClick = this.internalPreventClick.bind(this); + element.addEventListener("click", this.handlerPreventClick, options); + } + + if (SUPPORT_TOUCH) { + element.addEventListener("touchstart", this.handlerTouchStart, options); + element.addEventListener("touchend", this.handlerTouchEnd, options); + element.addEventListener("touchcancel", this.handlerTouchCancel, options); + } + + element.addEventListener("mousedown", this.handlerTouchStart, options); + element.addEventListener("mouseup", this.handlerTouchEnd, options); + element.addEventListener("mouseout", this.handlerTouchCancel, options); + + if (this.captureTouchmove) { + if (SUPPORT_TOUCH) { + element.addEventListener("touchmove", this.handlerTouchMove, options); + } + element.addEventListener("mousemove", this.handlerTouchMove, options); + } + + if (registerClickDetectors) { + window.activeClickDetectors.push(this); + } + this.element = element; + } + + /** + * Returns if the bound element is currently in the DOM. + */ + internalIsDomElementAttached() { + return this.element && document.documentElement.contains(this.element); + } + + /** + * Checks if the given event is relevant for this detector + * @param {TouchEvent|MouseEvent} event + */ + internalEventPreHandler(event, expectedRemainingTouches = 1) { + if (!this.element) { + // Already cleaned up + return false; + } + + if (this.targetOnly && event.target !== this.element) { + // Clicked a child element + return false; + } + + // Stop any propagation and defaults if configured + if (this.consumeEvents && event.cancelable) { + event.stopPropagation(); + } + + if (this.preventDefault && event.cancelable) { + event.preventDefault(); + } + + if (window.TouchEvent && event instanceof TouchEvent) { + clickDetectorGlobals.lastTouchTime = performance.now(); + + // console.log("Got touches", event.targetTouches.length, "vs", expectedRemainingTouches); + if (event.targetTouches.length !== expectedRemainingTouches) { + return false; + } + } + + if (event instanceof MouseEvent) { + if (performance.now() - clickDetectorGlobals.lastTouchTime < 1000.0) { + return false; + } + } + + return true; + } + + /** + * Extracts the mous position from an event + * @param {TouchEvent|MouseEvent} event + * @returns {Vector} The client space position + */ + static extractPointerPosition(event) { + if (window.TouchEvent && event instanceof TouchEvent) { + if (event.changedTouches.length !== 1) { + logger.warn( + "Got unexpected target touches:", + event.targetTouches.length, + "->", + event.targetTouches + ); + return new Vector(0, 0); + } + + const touch = event.changedTouches[0]; + return new Vector(touch.clientX, touch.clientY); + } + + if (event instanceof MouseEvent) { + return new Vector(event.clientX, event.clientY); + } + + assertAlways(false, "Got unknown event: " + event); + + return new Vector(0, 0); + } + + /** + * Cacnels all ongoing events on this detector + */ + cancelOngoingEvents() { + if (this.applyCssClass && this.element) { + this.element.classList.remove(this.applyCssClass); + } + this.clickDownPosition = null; + this.clickStartTime = null; + this.cancelled = true; + fastArrayDeleteValueIfContained(ongoingClickDetectors, this); + } + + /** + * Internal pointer down handler + * @param {TouchEvent|MouseEvent} event + */ + internalOnPointerDown(event) { + window.focus(); + + if (!this.internalEventPreHandler(event, 1)) { + return false; + } + + const position = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event); + + if (event instanceof MouseEvent) { + const isRightClick = event.button === 2; + if (isRightClick) { + // Ignore right clicks + this.rightClick.dispatch(position, event); + this.cancelled = true; + this.clickDownPosition = null; + return; + } + } + + if (this.clickDownPosition) { + logger.warn("Ignoring double click"); + return false; + } + + this.cancelled = false; + this.touchstart.dispatch(event); + + // Store where the touch started + this.clickDownPosition = position; + this.clickStartTime = performance.now(); + this.touchstartSimple.dispatch(this.clickDownPosition.x, this.clickDownPosition.y); + + // If we are not currently within a click, register it + if (ongoingClickDetectors.indexOf(this) < 0) { + ongoingClickDetectors.push(this); + } else { + logger.warn("Click detector got pointer down of active pointer twice"); + } + + // If we should apply any classes, do this now + if (this.applyCssClass) { + this.element.classList.add(this.applyCssClass); + } + + // If we should play any sound, do this + if (this.clickSound) { + GLOBAL_APP.sound.playUiSound(this.clickSound); + } + + return false; + } + + /** + * Internal pointer move handler + * @param {TouchEvent|MouseEvent} event + */ + internalOnPointerMove(event) { + if (!this.internalEventPreHandler(event, 1)) { + return false; + } + this.touchmove.dispatch(event); + const pos = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event); + this.touchmoveSimple.dispatch(pos.x, pos.y); + return false; + } + + /** + * Internal pointer end handler + * @param {TouchEvent|MouseEvent} event + */ + internalOnPointerEnd(event) { + window.focus(); + + if (!this.internalEventPreHandler(event, 0)) { + return false; + } + + if (this.cancelled) { + // warn(this, "Not dispatching touchend on cancelled listener"); + return false; + } + + if (event instanceof MouseEvent) { + const isRightClick = event.button === 2; + if (isRightClick) { + return; + } + } + + const index = ongoingClickDetectors.indexOf(this); + if (index < 0) { + logger.warn("Got pointer end but click detector is not in pressed state"); + } else { + fastArrayDelete(ongoingClickDetectors, index); + } + + let dispatchClick = false; + let dispatchClickPos = null; + + // Check for correct down position, otherwise must have pinched or so + if (this.clickDownPosition) { + const pos = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event); + const distance = pos.distance(this.clickDownPosition); + if (!IS_MOBILE || distance <= this.maxDistance) { + dispatchClick = true; + dispatchClickPos = pos; + } else { + console.warn("[ClickDetector] Touch does not count as click:", "(was", distance, ")"); + } + } + + this.clickDownPosition = null; + this.clickStartTime = null; + + if (this.applyCssClass) { + this.element.classList.remove(this.applyCssClass); + } + + // Dispatch in the end to avoid the element getting invalidated + // Also make sure that the element is still in the dom + if (this.internalIsDomElementAttached()) { + this.touchend.dispatch(event); + this.touchendSimple.dispatch(); + + if (dispatchClick) { + const detectors = ongoingClickDetectors.slice(); + for (let i = 0; i < detectors.length; ++i) { + detectors[i].cancelOngoingEvents(); + } + this.click.dispatch(dispatchClickPos, event); + } + } + return false; + } + + /** + * Internal touch cancel handler + * @param {TouchEvent|MouseEvent} event + */ + internalOnTouchCancel(event) { + if (!this.internalEventPreHandler(event, 0)) { + return false; + } + + if (this.cancelled) { + // warn(this, "Not dispatching touchcancel on cancelled listener"); + return false; + } + + this.cancelOngoingEvents(); + this.touchcancel.dispatch(event); + this.touchendSimple.dispatch(event); + return false; + } +} diff --git a/src/js/core/config.js b/src/js/core/config.js index e06f9422..a7df2a90 100644 --- a/src/js/core/config.js +++ b/src/js/core/config.js @@ -1,135 +1,145 @@ -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; -} +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 SUPPORT_TOUCH = false; + +export const IS_MAC = navigator.platform.toLowerCase().indexOf("mac") >= 0; + +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", + shapeViewer: "https://viewer.shapez.io", + + standaloneStorePage: "https://store.steampowered.com/app/1318690/shapezio/", + + levelTutorialVideos: { + 21: "https://www.youtube.com/watch?v=0nUfRLMCcgo&", + 25: "https://www.youtube.com/watch?v=7OCV1g40Iew&", + 26: "https://www.youtube.com/watch?v=gfm6dS1dCoY", + }, +}; + +export const A_B_TESTING_LINK_TYPE = Math.random() > 0.5 ? "steam_1_pr" : "steam_2_npr"; + +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: 10, + + buildingSpeeds: { + cutter: 1 / 4, + cutterQuad: 1 / 4, + rotater: 1 / 1, + rotaterCCW: 1 / 1, + rotater180: 1 / 1, + painter: 1 / 6, + painterDouble: 1 / 8, + painterQuad: 1 / 2, + mixer: 1 / 5, + stacker: 1 / 8, + }, + + // Zooming + initialZoom: 1.9, + minZoomLevel: 0.1, + maxZoomLevel: 3, + + // Global game speed + gameSpeed: 1, + + warmupTimeSecondsFast: 0.5, + warmupTimeSecondsRegular: 3, + + 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.noArtificialDelays = true; +} + +if (G_IS_DEV && globalConfig.debug.noArtificialDelays) { + globalConfig.warmupTimeSecondsFast = 0; + globalConfig.warmupTimeSecondsRegular = 0; +} diff --git a/src/js/core/config.local.js b/src/js/core/config.local.js index 7bf9a002..87aaaa14 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, + // ----------------------------------------------------------------------------------- + // 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, + // ----------------------------------------------------------------------------------- + // Disables slow asserts, useful for debugging performance + // disableSlowAsserts: true, + // ----------------------------------------------------------------------------------- + /* dev:end */ +}; diff --git a/src/js/core/dpi_manager.js b/src/js/core/dpi_manager.js index 0388c5f9..4fb792c0 100644 --- a/src/js/core/dpi_manager.js +++ b/src/js/core/dpi_manager.js @@ -17,12 +17,14 @@ export function getDeviceDPI() { export function smoothenDpi(dpi) { if (dpi < 0.05) { return 0.05; - } else if (dpi < 0.1) { - return round2Digits(dpi); + } else if (dpi < 0.2) { + return round2Digits(Math.round(dpi / 0.04) * 0.04); } else if (dpi < 1) { - return round1Digit(dpi); - } else { + return round1Digit(Math.round(dpi / 0.1) * 0.1); + } else if (dpi < 4) { return round1Digit(Math.round(dpi / 0.5) * 0.5); + } else { + return 4; } } diff --git a/src/js/core/draw_parameters.js b/src/js/core/draw_parameters.js index dcdf6d13..95e71bf2 100644 --- a/src/js/core/draw_parameters.js +++ b/src/js/core/draw_parameters.js @@ -1,30 +1,25 @@ -import { Rectangle } from "./rectangle"; -import { globalConfig } from "./config"; - -/* typehints:start */ -import { GameRoot } from "../game/root"; -/* typehints:end */ - -export class DrawParameters { - constructor({ context, visibleRect, desiredAtlasScale, zoomLevel, root }) { - /** @type {CanvasRenderingContext2D} */ - this.context = context; - - /** @type {Rectangle} */ - this.visibleRect = visibleRect; - - /** @type {number} */ - this.desiredAtlasScale = desiredAtlasScale; - - /** @type {number} */ - this.zoomLevel = zoomLevel; - - // FIXME: Not really nice - /** @type {GameRoot} */ - this.root = root; - - if (G_IS_DEV && globalConfig.debug.testClipping) { - this.visibleRect = this.visibleRect.expandedInAllDirections(-100); - } - } -} +import { globalConfig } from "./config"; + +/** + * @typedef {import("../game/root").GameRoot} GameRoot + * @typedef {import("./rectangle").Rectangle} Rectangle + */ + +export class DrawParameters { + constructor({ context, visibleRect, desiredAtlasScale, zoomLevel, root }) { + /** @type {CanvasRenderingContext2D} */ + this.context = context; + + /** @type {Rectangle} */ + this.visibleRect = visibleRect; + + /** @type {string} */ + this.desiredAtlasScale = desiredAtlasScale; + + /** @type {number} */ + this.zoomLevel = zoomLevel; + + /** @type {GameRoot} */ + this.root = root; + } +} 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..cadbc048 100644 --- a/src/js/core/loader.js +++ b/src/js/core/loader.js @@ -1,243 +1,230 @@ -/* 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"; - -const logger = createLogger("loader"); - -const missingSpriteIds = {}; - -class LoaderImpl { - constructor() { - /** @type {Application} */ - this.app = null; - - /** @type {Map} */ - this.sprites = new Map(); - - this.rawImages = []; - } - - linkAppAfterBoot(app) { - this.app = app; - this.makeSpriteNotFoundCanvas(); - } - - /** - * Fetches a given sprite from the cache - * @param {string} key - * @returns {BaseSprite} - */ - getSpriteInternal(key) { - const sprite = this.sprites.get(key); - if (!sprite) { - if (!missingSpriteIds[key]) { - // Only show error once - missingSpriteIds[key] = true; - logger.error("Sprite '" + key + "' not found!"); - } - return this.spriteNotFoundSprite; - } - return sprite; - } - - /** - * Returns an atlas sprite from the cache - * @param {string} key - * @returns {AtlasSprite} - */ - getSprite(key) { - const sprite = this.getSpriteInternal(key); - assert(sprite instanceof AtlasSprite || sprite === this.spriteNotFoundSprite, "Not an atlas sprite"); - return /** @type {AtlasSprite} */ (sprite); - } - - /** - * Retursn a regular sprite from the cache - * @param {string} key - * @returns {RegularSprite} - */ - getRegularSprite(key) { - const sprite = this.getSpriteInternal(key); - assert( - sprite instanceof RegularSprite || sprite === this.spriteNotFoundSprite, - "Not a regular sprite" - ); - return /** @type {RegularSprite} */ (sprite); - } - - /** - * - * @param {string} key - * @returns {Promise} - */ - internalPreloadImage(key) { - const url = cachebust("res/" + key); - const image = new Image(); - - let triesSoFar = 0; - - return Promise.race([ - new Promise((resolve, reject) => { - setTimeout(reject, G_IS_DEV ? 500 : 10000); - }), - - new Promise(resolve => { - image.onload = () => { - image.onerror = null; - image.onload = null; - - if (typeof image.decode === "function") { - // SAFARI: Image.decode() fails on safari with svgs -> we dont want to fail - // on that - // FIREFOX: Decode never returns if the image is in cache, so call it in background - image.decode().then( - () => null, - () => null - ); - } - resolve(image); - }; - - image.onerror = reason => { - logger.warn("Failed to load '" + url + "':", reason); - if (++triesSoFar < 4) { - logger.log("Retrying to load image from", url); - image.src = url + "?try=" + triesSoFar; - } else { - logger.warn("Failed to load", url, "after", triesSoFar, "tries with reason", reason); - image.onerror = null; - image.onload = null; - resolve(null); - } - }; - - image.src = url; - }), - ]); - } - - /** - * Preloads a sprite - * @param {string} key - * @returns {Promise} - */ - preloadCSSSprite(key) { - return this.internalPreloadImage(key).then(image => { - if (key.indexOf("game_misc") >= 0) { - // Allow access to regular sprites - this.sprites.set(key, new RegularSprite(image, image.width, image.height)); - } - this.rawImages.push(image); - }); - } - - /** - * Preloads an atlas - * @param {AtlasDefinition} atlas - * @returns {Promise} - */ - preloadAtlas(atlas) { - return this.internalPreloadImage(atlas.getFullSourcePath()).then(image => { - // @ts-ignore - image.label = atlas.sourceFileName; - return this.internalParseAtlas(atlas, image); - }); - } - - /** - * - * @param {AtlasDefinition} atlas - * @param {HTMLImageElement} loadedImage - */ - internalParseAtlas(atlas, loadedImage) { - this.rawImages.push(loadedImage); - - for (const spriteKey in atlas.sourceData) { - const spriteData = atlas.sourceData[spriteKey]; - - let sprite = /** @type {AtlasSprite} */ (this.sprites.get(spriteKey)); - - if (!sprite) { - sprite = new AtlasSprite({ - spriteName: spriteKey, - }); - this.sprites.set(spriteKey, 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, - atlas: loadedImage, - w: spriteData.sourceSize.w, - h: spriteData.sourceSize.h, - }); - sprite.linksByResolution[atlas.meta.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 - */ - makeSpriteNotFoundCanvas() { - const dims = 128; - - const [canvas, context] = makeOffscreenBuffer(dims, dims, { - smooth: false, - label: "not-found-sprite", - }); - context.fillStyle = "#f77"; - context.fillRect(0, 0, dims, dims); - - context.textAlign = "center"; - context.textBaseline = "middle"; - context.fillStyle = "#eee"; - context.font = "25px Arial"; - context.fillText("???", dims / 2, dims / 2); - - // TODO: Not sure why this is set here - // @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({ - packedX: 0, - packedY: 0, - w: dims, - h: dims, - packOffsetX: 0, - packOffsetY: 0, - packedW: dims, - packedH: dims, - atlas: canvas, - }); - sprite.linksByResolution[res] = link; - } - this.spriteNotFoundSprite = sprite; - } -} - -export const Loader = new LoaderImpl(); +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() { + this.app = null; + + /** @type {Map} */ + this.sprites = new Map(); + + this.rawImages = []; + } + + /** + * @param {Application} app + */ + linkAppAfterBoot(app) { + this.app = app; + this.makeSpriteNotFoundCanvas(); + } + + /** + * Fetches a given sprite from the cache + * @param {string} key + * @returns {BaseSprite} + */ + getSpriteInternal(key) { + const sprite = this.sprites.get(key); + if (!sprite) { + if (!missingSpriteIds[key]) { + // Only show error once + missingSpriteIds[key] = true; + logger.error("Sprite '" + key + "' not found!"); + } + return this.spriteNotFoundSprite; + } + return sprite; + } + + /** + * Returns an atlas sprite from the cache + * @param {string} key + * @returns {AtlasSprite} + */ + getSprite(key) { + const sprite = this.getSpriteInternal(key); + assert(sprite instanceof AtlasSprite || sprite === this.spriteNotFoundSprite, "Not an atlas sprite"); + return /** @type {AtlasSprite} */ (sprite); + } + + /** + * Returns a regular sprite from the cache + * @param {string} key + * @returns {RegularSprite} + */ + getRegularSprite(key) { + const sprite = this.getSpriteInternal(key); + assert( + sprite instanceof RegularSprite || sprite === this.spriteNotFoundSprite, + "Not a regular sprite" + ); + return /** @type {RegularSprite} */ (sprite); + } + + /** + * + * @param {string} key + * @returns {Promise} + */ + internalPreloadImage(key) { + const url = cachebust("res/" + key); + const image = new Image(); + + let triesSoFar = 0; + + return Promise.race([ + new Promise((resolve, reject) => { + setTimeout(reject, G_IS_DEV ? 500 : 10000); + }), + + new Promise(resolve => { + image.onload = () => { + image.onerror = null; + image.onload = null; + + if (typeof image.decode === "function") { + // SAFARI: Image.decode() fails on safari with svgs -> we dont want to fail + // on that + // FIREFOX: Decode never returns if the image is in cache, so call it in background + image.decode().then( + () => null, + () => null + ); + } + resolve(image); + }; + + image.onerror = reason => { + logger.warn("Failed to load '" + url + "':", reason); + if (++triesSoFar < 4) { + logger.log("Retrying to load image from", url); + image.src = url + "?try=" + triesSoFar; + } else { + logger.warn("Failed to load", url, "after", triesSoFar, "tries with reason", reason); + image.onerror = null; + image.onload = null; + resolve(null); + } + }; + + image.src = url; + }), + ]); + } + + /** + * Preloads a sprite + * @param {string} key + * @returns {Promise} + */ + preloadCSSSprite(key) { + return this.internalPreloadImage(key).then(image => { + if (key.indexOf("game_misc") >= 0) { + // Allow access to regular sprites + this.sprites.set(key, new RegularSprite(image, image.width, image.height)); + } + this.rawImages.push(image); + }); + } + + /** + * Preloads an atlas + * @param {AtlasDefinition} atlas + * @returns {Promise} + */ + preloadAtlas(atlas) { + return this.internalPreloadImage(atlas.getFullSourcePath()).then(image => { + // @ts-ignore + image.label = atlas.sourceFileName; + return this.internalParseAtlas(atlas, image); + }); + } + + /** + * + * @param {AtlasDefinition} atlas + * @param {HTMLImageElement} loadedImage + */ + internalParseAtlas({ meta: { scale }, sourceData }, loadedImage) { + this.rawImages.push(loadedImage); + + for (const spriteName in sourceData) { + const { frame, sourceSize, spriteSourceSize } = sourceData[spriteName]; + + let sprite = /** @type {AtlasSprite} */ (this.sprites.get(spriteName)); + + if (!sprite) { + sprite = new AtlasSprite(spriteName); + this.sprites.set(spriteName, sprite); + } + + const link = new SpriteAtlasLink({ + packedX: frame.x, + packedY: frame.y, + packedW: frame.w, + packedH: frame.h, + packOffsetX: spriteSourceSize.x, + packOffsetY: spriteSourceSize.y, + atlas: loadedImage, + w: sourceSize.w, + h: sourceSize.h, + }); + sprite.linksByResolution[scale] = link; + } + } + + /** + * Makes the canvas which shows the question mark, shown when a sprite was not found + */ + makeSpriteNotFoundCanvas() { + const dims = 128; + + const [canvas, context] = makeOffscreenBuffer(dims, dims, { + smooth: false, + label: "not-found-sprite", + }); + context.fillStyle = "#f77"; + context.fillRect(0, 0, dims, dims); + + context.textAlign = "center"; + context.textBaseline = "middle"; + context.fillStyle = "#eee"; + context.font = "25px Arial"; + context.fillText("???", dims / 2, dims / 2); + + // TODO: Not sure why this is set here + // @ts-ignore + canvas.src = "not-found"; + + 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, + h: dims, + packOffsetX: 0, + packOffsetY: 0, + packedW: dims, + packedH: dims, + atlas: canvas, + }); + }); + + this.spriteNotFoundSprite = sprite; + } +} + +export const Loader = new LoaderImpl(); diff --git a/src/js/core/modal_dialog_elements.js b/src/js/core/modal_dialog_elements.js index 8252487a..5f0ed59f 100644 --- a/src/js/core/modal_dialog_elements.js +++ b/src/js/core/modal_dialog_elements.js @@ -1,434 +1,457 @@ -/* 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"; + +/* + * *************************************************** + * + * LEGACY CODE WARNING + * + * This is old code from yorg3.io and needs to be refactored + * @TODO + * + * *************************************************** + */ + +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 separated 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 separated 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.valueChosen = 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); + }, 3000); + 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"); + 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); + elem.valueChosen.add(this.closeRequested.dispatch, this.closeRequested); + elem.valueChosen.add(this.valueChosen.dispatch, this.valueChosen); + } + + waitNextFrame().then(() => { + this.formElements[this.formElements.length - 1].focus(); + }); + + return div; + } +} diff --git a/src/js/core/modal_dialog_forms.js b/src/js/core/modal_dialog_forms.js index 1ded9a8b..1c5b1986 100644 --- a/src/js/core/modal_dialog_forms.js +++ b/src/js/core/modal_dialog_forms.js @@ -1,150 +1,232 @@ -import { ClickDetector } from "./click_detector"; - -export class FormElement { - constructor(id, label) { - this.id = id; - this.label = label; - } - - getHtml() { - abstract; - return ""; - } - - getFormElement(parent) { - return parent.querySelector("[data-formId='" + this.id + "']"); - } - - bindEvents(parent, clickTrackers) { - abstract; - } - - focus() {} - - isValid() { - return true; - } - - /** @returns {any} */ - getValue() { - abstract; - } -} - -export class FormElementInput extends FormElement { - constructor({ id, label = null, placeholder, defaultValue = "", inputType = "text", validator = null }) { - super(id, label); - this.placeholder = placeholder; - this.defaultValue = defaultValue; - this.inputType = inputType; - this.validator = validator; - - this.element = null; - } - - getHtml() { - let classes = []; - let inputType = "text"; - let maxlength = 256; - switch (this.inputType) { - case "text": { - classes.push("input-text"); - break; - } - - case "email": { - classes.push("input-email"); - inputType = "email"; - break; - } - - case "token": { - classes.push("input-token"); - inputType = "text"; - maxlength = 4; - break; - } - } - - return ` -
- ${this.label ? `` : ""} - -
- `; - } - - bindEvents(parent, clickTrackers) { - this.element = this.getFormElement(parent); - this.element.addEventListener("input", event => this.updateErrorState()); - this.updateErrorState(); - } - - updateErrorState() { - this.element.classList.toggle("errored", !this.isValid()); - } - - isValid() { - return !this.validator || this.validator(this.element.value); - } - - getValue() { - return this.element.value; - } - - focus() { - this.element.focus(); - } -} - -export class FormElementCheckbox extends FormElement { - constructor({ id, label, defaultValue = true }) { - super(id, label); - this.defaultValue = defaultValue; - this.value = this.defaultValue; - - this.element = null; - } - - getHtml() { - return ` -
- ${this.label ? `` : ""} -
- -
-
- `; - } - - bindEvents(parent, clickTrackers) { - this.element = this.getFormElement(parent); - const detector = new ClickDetector(this.element, { - consumeEvents: false, - preventDefault: false, - }); - clickTrackers.push(detector); - detector.click.add(this.toggle, this); - } - - getValue() { - return this.value; - } - - toggle() { - this.value = !this.value; - this.element.classList.toggle("checked", this.value); - } - - focus(parent) {} -} +import { BaseItem } from "../game/base_item"; +import { ClickDetector } from "./click_detector"; +import { Signal } from "./signal"; + +/* + * *************************************************** + * + * LEGACY CODE WARNING + * + * This is old code from yorg3.io and needs to be refactored + * @TODO + * + * *************************************************** + */ + +export class FormElement { + constructor(id, label) { + this.id = id; + this.label = label; + + this.valueChosen = new Signal(); + } + + getHtml() { + abstract; + return ""; + } + + getFormElement(parent) { + return parent.querySelector("[data-formId='" + this.id + "']"); + } + + bindEvents(parent, clickTrackers) { + abstract; + } + + focus() {} + + isValid() { + return true; + } + + /** @returns {any} */ + getValue() { + abstract; + } +} + +export class FormElementInput extends FormElement { + constructor({ id, label = null, placeholder, defaultValue = "", inputType = "text", validator = null }) { + super(id, label); + this.placeholder = placeholder; + this.defaultValue = defaultValue; + this.inputType = inputType; + this.validator = validator; + + this.element = null; + } + + getHtml() { + let classes = []; + let inputType = "text"; + let maxlength = 256; + switch (this.inputType) { + case "text": { + classes.push("input-text"); + break; + } + + case "email": { + classes.push("input-email"); + inputType = "email"; + break; + } + + case "token": { + classes.push("input-token"); + inputType = "text"; + maxlength = 4; + break; + } + } + + return ` +
+ ${this.label ? `` : ""} + +
+ `; + } + + bindEvents(parent, clickTrackers) { + this.element = this.getFormElement(parent); + this.element.addEventListener("input", event => this.updateErrorState()); + this.updateErrorState(); + } + + updateErrorState() { + this.element.classList.toggle("errored", !this.isValid()); + } + + isValid() { + return !this.validator || this.validator(this.element.value); + } + + getValue() { + return this.element.value; + } + + focus() { + this.element.focus(); + } +} + +export class FormElementCheckbox extends FormElement { + constructor({ id, label, defaultValue = true }) { + super(id, label); + this.defaultValue = defaultValue; + this.value = this.defaultValue; + + this.element = null; + } + + getHtml() { + return ` +
+ ${this.label ? `` : ""} +
+ +
+
+ `; + } + + bindEvents(parent, clickTrackers) { + this.element = this.getFormElement(parent); + const detector = new ClickDetector(this.element, { + consumeEvents: false, + preventDefault: false, + }); + clickTrackers.push(detector); + detector.click.add(this.toggle, this); + } + + getValue() { + return this.value; + } + + toggle() { + this.value = !this.value; + this.element.classList.toggle("checked", this.value); + } + + focus(parent) {} +} + +export class FormElementItemChooser extends FormElement { + /** + * + * @param {object} param0 + * @param {string} param0.id + * @param {string=} param0.label + * @param {Array} param0.items + */ + constructor({ id, label, items = [] }) { + super(id, label); + this.items = items; + this.element = null; + + /** + * @type {BaseItem} + */ + this.chosenItem = null; + } + + getHtml() { + let classes = []; + + return ` +
+ ${this.label ? `` : ""} +
+
+ `; + } + + /** + * @param {HTMLElement} parent + * @param {Array} clickTrackers + */ + bindEvents(parent, clickTrackers) { + this.element = this.getFormElement(parent); + + for (let i = 0; i < this.items.length; ++i) { + const item = this.items[i]; + + const canvas = document.createElement("canvas"); + canvas.width = 128; + canvas.height = 128; + const context = canvas.getContext("2d"); + item.drawFullSizeOnCanvas(context, 128); + this.element.appendChild(canvas); + + const detector = new ClickDetector(canvas, {}); + clickTrackers.push(detector); + detector.click.add(() => { + this.chosenItem = item; + this.valueChosen.dispatch(item); + }); + } + } + + isValid() { + return true; + } + + getValue() { + return null; + } + + focus() {} +} diff --git a/src/js/core/read_write_proxy.js b/src/js/core/read_write_proxy.js index 5474467a..7c96149b 100644 --- a/src/js/core/read_write_proxy.js +++ b/src/js/core/read_write_proxy.js @@ -1,342 +1,343 @@ -/* 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(); + } + + /** + * + * @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 that's 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/restriction_manager.js b/src/js/core/restriction_manager.js new file mode 100644 index 00000000..2912d30f --- /dev/null +++ b/src/js/core/restriction_manager.js @@ -0,0 +1,154 @@ +/* typehints:start */ +import { Application } from "../application"; +/* typehints:end */ +import { IS_MAC } from "./config"; +import { ExplainedResult } from "./explained_result"; +import { queryParamOptions } from "./query_parameters"; +import { ReadWriteProxy } from "./read_write_proxy"; + +export class RestrictionManager extends ReadWriteProxy { + /** + * @param {Application} app + */ + constructor(app) { + super(app, "restriction-flags.bin"); + + this.currentData = this.getDefaultData(); + } + + // -- RW Proxy Impl + + /** + * @param {any} data + */ + verify(data) { + return ExplainedResult.good(); + } + + /** + */ + getDefaultData() { + return { + version: this.getCurrentVersion(), + savegameV1119Imported: false, + }; + } + + /** + */ + getCurrentVersion() { + return 1; + } + + /** + * @param {any} data + */ + migrate(data) { + return ExplainedResult.good(); + } + + initialize() { + return this.readAsync().then(() => { + if (this.currentData.savegameV1119Imported) { + console.warn("Levelunlock is granted to current user due to past savegame"); + } + }); + } + + // -- End RW Proxy Impl + + /** + * Checks if there are any savegames from the 1.1.19 version + */ + onHasLegacySavegamesChanged(has119Savegames = false) { + if (has119Savegames && !this.currentData.savegameV1119Imported) { + this.currentData.savegameV1119Imported = true; + console.warn("Current user now has access to all levels due to 1119 savegame"); + return this.writeAsync(); + } + return Promise.resolve(); + } + + /** + * Returns if the app is currently running as the limited version + * @returns {boolean} + */ + isLimitedVersion() { + if (IS_MAC) { + // On mac, the full version is always active + return false; + } + + if (G_IS_STANDALONE) { + // Standalone is never limited + return false; + } + + if (queryParamOptions.fullVersion) { + // Full version is activated via flag + return false; + } + + if (G_IS_DEV) { + return typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0; + } + + return true; + } + + /** + * Returns if the app markets the standalone version on steam + * @returns {boolean} + */ + getIsStandaloneMarketingActive() { + return this.isLimitedVersion(); + } + + /** + * Returns if exporting the base as a screenshot is possible + * @returns {boolean} + */ + getIsExportingScreenshotsPossible() { + return !this.isLimitedVersion(); + } + + /** + * Returns the maximum number of supported waypoints + * @returns {number} + */ + getMaximumWaypoints() { + return this.isLimitedVersion() ? 2 : 1e20; + } + + /** + * Returns if the user has unlimited savegames + * @returns {boolean} + */ + getHasUnlimitedSavegames() { + return !this.isLimitedVersion(); + } + + /** + * Returns if the app has all settings available + * @returns {boolean} + */ + getHasExtendedSettings() { + return !this.isLimitedVersion(); + } + + /** + * Returns if all upgrades are available + * @returns {boolean} + */ + getHasExtendedUpgrades() { + return !this.isLimitedVersion() || this.currentData.savegameV1119Imported; + } + + /** + * Returns if all levels & freeplay is available + * @returns {boolean} + */ + getHasExtendedLevelsAndFreeplay() { + return !this.isLimitedVersion() || this.currentData.savegameV1119Imported; + } +} diff --git a/src/js/core/rng.js b/src/js/core/rng.js index 9c5c1c43..7a6766cd 100644 --- a/src/js/core/rng.js +++ b/src/js/core/rng.js @@ -108,17 +108,6 @@ export class RandomNumberGenerator { assert(max > min, "rng: max <= min"); return Math.floor(this.next() * (max - min) + min); } - /** - * @param {number} min - * @param {number} max - * @returns {number} Integer in range [min, max] - */ - nextIntRangeInclusive(min, max) { - assert(Number.isFinite(min), "Minimum is no integer"); - assert(Number.isFinite(max), "Maximum is no integer"); - assert(max > min, "rng: max <= min"); - return Math.round(this.next() * (max - min) + min); - } /** * @param {number} min 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..1019d8f7 100644 --- a/src/js/core/sprites.js +++ b/src/js/core/sprites.js @@ -1,357 +1,395 @@ -import { DrawParameters } from "./draw_parameters"; -import { Rectangle } from "./rectangle"; -import { epsilonCompare, round3Digits } from "./utils"; - -const floorSpriteCoordinates = false; - -const ORIGINAL_SCALE = "1"; - -export class BaseSprite { - /** - * Returns the raw handle - * @returns {HTMLImageElement|HTMLCanvasElement} - */ - getRawTexture() { - abstract; - return null; - } - - /** - * Draws the sprite - * @param {CanvasRenderingContext2D} context - * @param {number} x - * @param {number} y - * @param {number} w - * @param {number} h - */ - draw(context, x, y, w, h) { - // eslint-disable-line no-unused-vars - abstract; - } -} - -/** - * Position of a sprite within an atlas - */ -export class SpriteAtlasLink { - /** - * - * @param {object} param0 - * @param {number} param0.packedX - * @param {number} param0.packedY - * @param {number} param0.packOffsetX - * @param {number} param0.packOffsetY - * @param {number} param0.packedW - * @param {number} param0.packedH - * @param {number} param0.w - * @param {number} param0.h - * @param {HTMLImageElement|HTMLCanvasElement} param0.atlas - */ - constructor({ w, h, packedX, packedY, packOffsetX, packOffsetY, packedW, packedH, atlas }) { - this.packedX = packedX; - this.packedY = packedY; - this.packedW = packedW; - this.packedH = packedH; - this.packOffsetX = packOffsetX; - this.packOffsetY = packOffsetY; - this.atlas = atlas; - this.w = w; - this.h = h; - } -} - -export class AtlasSprite extends BaseSprite { - /** - * - * @param {object} param0 - * @param {string} param0.spriteName - */ - constructor({ spriteName = "sprite" }) { - super(); - /** @type {Object.} */ - this.linksByResolution = {}; - this.spriteName = spriteName; - } - - getRawTexture() { - return this.linksByResolution[ORIGINAL_SCALE].atlas; - } - - /** - * Draws the sprite onto a regular context using no contexts - * @see {BaseSprite.draw} - */ - draw(context, x, y, w, h) { - if (G_IS_DEV) { - assert(context instanceof CanvasRenderingContext2D, "Not a valid context"); - } - - const link = this.linksByResolution[ORIGINAL_SCALE]; - - assert( - link, - "Link not known: " + ORIGINAL_SCALE + " (having " + Object.keys(this.linksByResolution) + ")" - ); - - const width = w || link.w; - const height = h || link.h; - - const scaleW = width / link.w; - const scaleH = height / link.h; - - context.drawImage( - link.atlas, - - link.packedX, - link.packedY, - link.packedW, - link.packedH, - - x + link.packOffsetX * scaleW, - y + link.packOffsetY * scaleH, - link.packedW * scaleW, - link.packedH * scaleH - ); - } - - /** - * - * @param {DrawParameters} parameters - * @param {number} x - * @param {number} y - * @param {number} size - * @param {boolean=} clipping - */ - drawCachedCentered(parameters, x, y, size, clipping = true) { - this.drawCached(parameters, x - size / 2, y - size / 2, size, size, clipping); - } - - /** - * - * @param {CanvasRenderingContext2D} context - * @param {number} x - * @param {number} y - * @param {number} size - */ - drawCentered(context, x, y, size) { - this.draw(context, x - size / 2, y - size / 2, size, size); - } - - /** - * Draws the sprite - * @param {DrawParameters} parameters - * @param {number} x - * @param {number} y - * @param {number} w - * @param {number} h - * @param {boolean=} clipping Whether to perform culling - */ - drawCached(parameters, x, y, w = null, h = null, clipping = true) { - if (G_IS_DEV) { - assert(parameters instanceof DrawParameters, "Not a valid context"); - assert(!!w && w > 0, "Not a valid width:" + w); - assert(!!h && h > 0, "Not a valid height:" + h); - } - - const visibleRect = parameters.visibleRect; - - const scale = parameters.desiredAtlasScale; - const link = this.linksByResolution[scale]; - - assert(link, "Link not known: " + scale + " (having " + Object.keys(this.linksByResolution) + ")"); - - const scaleW = w / link.w; - const scaleH = h / link.h; - - let destX = x + link.packOffsetX * scaleW; - let destY = y + link.packOffsetY * scaleH; - let destW = link.packedW * scaleW; - let destH = link.packedH * scaleH; - - let srcX = link.packedX; - let srcY = link.packedY; - let srcW = link.packedW; - let srcH = link.packedH; - - let intersection = null; - - if (clipping) { - const rect = new Rectangle(destX, destY, destW, destH); - intersection = rect.getIntersection(visibleRect); - if (!intersection) { - return; - } - - srcX += (intersection.x - destX) / scaleW; - srcY += (intersection.y - destY) / scaleH; - - srcW *= intersection.w / destW; - srcH *= intersection.h / destH; - - destX = intersection.x; - destY = intersection.y; - - destW = intersection.w; - destH = intersection.h; - } - - // assert(epsilonCompare(scaleW, scaleH), "Sprite should be square for cached rendering"); - - if (floorSpriteCoordinates) { - parameters.context.drawImage( - link.atlas, - - // atlas src pos - Math.floor(srcX), - Math.floor(srcY), - - // atlas src size - Math.floor(srcW), - Math.floor(srcH), - - // dest pos - Math.floor(destX), - Math.floor(destY), - - // dest size - Math.floor(destW), - Math.floor(destH) - ); - } else { - parameters.context.drawImage( - link.atlas, - - // atlas src pos - srcX, - srcY, - - // atlas src siize - srcW, - srcH, - - // dest pos and size - destX, - destY, - destW, - destH - ); - } - } - - /** - * Renders into an html element - * @param {HTMLElement} element - * @param {number} w - * @param {number} h - */ - renderToHTMLElement(element, w = 1, h = 1) { - element.style.position = "relative"; - element.innerHTML = this.getAsHTML(w, h); - } - - /** - * Returns the html to render as icon - * @param {number} w - * @param {number} h - */ - getAsHTML(w, h) { - const link = this.linksByResolution["0.5"]; - - // Find out how much we have to scale it so that it fits - const scaleX = w / link.w; - const scaleY = h / link.h; - - // Find out how big the scaled atlas is - const atlasW = link.atlas.width * scaleX; - const atlasH = link.atlas.height * scaleY; - - // @ts-ignore - const srcSafe = link.atlas.src.replaceAll("\\", "/"); - - // Find out how big we render the sprite - const widthAbsolute = scaleX * link.packedW; - const heightAbsolute = scaleY * link.packedH; - - // Compute the position in the relative container - const leftRelative = (link.packOffsetX * scaleX) / w; - const topRelative = (link.packOffsetY * scaleY) / h; - const widthRelative = widthAbsolute / w; - const heightRelative = heightAbsolute / h; - - // Scale the atlas relative to the width and height of the element - const bgW = atlasW / widthAbsolute; - const bgH = atlasH / heightAbsolute; - - // Figure out what the position of the atlas is - const bgX = link.packedX * scaleX; - const bgY = link.packedY * scaleY; - - // Fuck you, whoever thought its a good idea to make background-position work like it does now - const bgXRelative = -bgX / (widthAbsolute - atlasW); - const bgYRelative = -bgY / (heightAbsolute - atlasH); - - return ` - - `; - } -} - -export class RegularSprite extends BaseSprite { - constructor(sprite, w, h) { - super(); - this.w = w; - this.h = h; - this.sprite = sprite; - } - - getRawTexture() { - return this.sprite; - } - - /** - * Draws the sprite, do *not* use this for sprites which are rendered! Only for drawing - * images into buffers - * @param {CanvasRenderingContext2D} context - * @param {number} x - * @param {number} y - * @param {number} w - * @param {number} h - */ - draw(context, x, y, w, h) { - assert(context, "No context given"); - assert(x !== undefined, "No x given"); - assert(y !== undefined, "No y given"); - assert(w !== undefined, "No width given"); - assert(h !== undefined, "No height given"); - context.drawImage(this.sprite, x, y, w, h); - } - - /** - * Draws the sprite, do *not* use this for sprites which are rendered! Only for drawing - * images into buffers - * @param {CanvasRenderingContext2D} context - * @param {number} x - * @param {number} y - * @param {number} w - * @param {number} h - */ - drawCentered(context, x, y, w, h) { - assert(context, "No context given"); - assert(x !== undefined, "No x given"); - assert(y !== undefined, "No y given"); - assert(w !== undefined, "No width given"); - assert(h !== undefined, "No height given"); - context.drawImage(this.sprite, x - w / 2, y - h / 2, w, h); - } -} +import { DrawParameters } from "./draw_parameters"; +import { Rectangle } from "./rectangle"; +import { round3Digits } from "./utils"; + +export const ORIGINAL_SPRITE_SCALE = "0.75"; +export const FULL_CLIP_RECT = new Rectangle(0, 0, 1, 1); + +const EXTRUDE = 0.1; + +export class BaseSprite { + /** + * Returns the raw handle + * @returns {HTMLImageElement|HTMLCanvasElement} + */ + getRawTexture() { + abstract; + return null; + } + + /** + * Draws the sprite + * @param {CanvasRenderingContext2D} context + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + */ + draw(context, x, y, w, h) { + // eslint-disable-line no-unused-vars + abstract; + } +} + +/** + * Position of a sprite within an atlas + */ +export class SpriteAtlasLink { + /** + * + * @param {object} param0 + * @param {number} param0.packedX + * @param {number} param0.packedY + * @param {number} param0.packOffsetX + * @param {number} param0.packOffsetY + * @param {number} param0.packedW + * @param {number} param0.packedH + * @param {number} param0.w + * @param {number} param0.h + * @param {HTMLImageElement|HTMLCanvasElement} param0.atlas + */ + constructor({ w, h, packedX, packedY, packOffsetX, packOffsetY, packedW, packedH, atlas }) { + this.packedX = packedX; + this.packedY = packedY; + this.packedW = packedW; + this.packedH = packedH; + this.packOffsetX = packOffsetX; + this.packOffsetY = packOffsetY; + this.atlas = atlas; + this.w = w; + this.h = h; + } +} + +export class AtlasSprite extends BaseSprite { + /** + * + * @param {string} spriteName + */ + constructor(spriteName = "sprite") { + super(); + /** @type {Object.} */ + this.linksByResolution = {}; + this.spriteName = spriteName; + } + + getRawTexture() { + return this.linksByResolution[ORIGINAL_SPRITE_SCALE].atlas; + } + + /** + * Draws the sprite onto a regular context using no contexts + * @see {BaseSprite.draw} + */ + draw(context, x, y, w, h) { + if (G_IS_DEV) { + assert(context instanceof CanvasRenderingContext2D, "Not a valid context"); + } + + const link = this.linksByResolution[ORIGINAL_SPRITE_SCALE]; + + assert( + link, + "Link not known: " + + ORIGINAL_SPRITE_SCALE + + " (having " + + Object.keys(this.linksByResolution) + + ")" + ); + + const width = w || link.w; + const height = h || link.h; + + const scaleW = width / link.w; + const scaleH = height / link.h; + + context.drawImage( + link.atlas, + + link.packedX, + link.packedY, + link.packedW, + link.packedH, + + x + link.packOffsetX * scaleW, + y + link.packOffsetY * scaleH, + link.packedW * scaleW, + link.packedH * scaleH + ); + } + + /** + * + * @param {DrawParameters} parameters + * @param {number} x + * @param {number} y + * @param {number} size + * @param {boolean=} clipping + */ + drawCachedCentered(parameters, x, y, size, clipping = true) { + this.drawCached(parameters, x - size / 2, y - size / 2, size, size, clipping); + } + + /** + * + * @param {CanvasRenderingContext2D} context + * @param {number} x + * @param {number} y + * @param {number} size + */ + drawCentered(context, x, y, size) { + this.draw(context, x - size / 2, y - size / 2, size, size); + } + + /** + * Draws the sprite + * @param {DrawParameters} parameters + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {boolean=} clipping Whether to perform culling + */ + drawCached(parameters, x, y, w = null, h = null, clipping = true) { + if (G_IS_DEV) { + assert(parameters instanceof DrawParameters, "Not a valid context"); + assert(!!w && w > 0, "Not a valid width:" + w); + assert(!!h && h > 0, "Not a valid height:" + h); + } + + const visibleRect = parameters.visibleRect; + + const scale = parameters.desiredAtlasScale; + const link = this.linksByResolution[scale]; + + if (!link) { + assert(false, `Link not known: ${scale} (having ${Object.keys(this.linksByResolution)})`); + } + + const scaleW = w / link.w; + const scaleH = h / link.h; + + let destX = x + link.packOffsetX * scaleW; + let destY = y + link.packOffsetY * scaleH; + let destW = link.packedW * scaleW; + let destH = link.packedH * scaleH; + + let srcX = link.packedX; + let srcY = link.packedY; + let srcW = link.packedW; + let srcH = link.packedH; + + let intersection = null; + + if (clipping) { + const rect = new Rectangle(destX, destY, destW, destH); + intersection = rect.getIntersection(visibleRect); + if (!intersection) { + return; + } + + srcX += (intersection.x - destX) / scaleW; + srcY += (intersection.y - destY) / scaleH; + + srcW *= intersection.w / destW; + srcH *= intersection.h / destH; + + destX = intersection.x; + destY = intersection.y; + + destW = intersection.w; + destH = intersection.h; + } + + parameters.context.drawImage( + link.atlas, + + // atlas src pos + srcX, + srcY, + + // atlas src size + srcW, + srcH, + + // dest pos and size + destX - EXTRUDE, + destY - EXTRUDE, + destW + 2 * EXTRUDE, + destH + 2 * EXTRUDE + ); + } + + /** + * Draws a subset of the sprite. Does NO culling + * @param {DrawParameters} parameters + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {Rectangle=} clipRect The rectangle in local space (0 ... 1) to draw of the image + */ + drawCachedWithClipRect(parameters, x, y, w = null, h = null, clipRect = FULL_CLIP_RECT) { + if (G_IS_DEV) { + assert(parameters instanceof DrawParameters, "Not a valid context"); + assert(!!w && w > 0, "Not a valid width:" + w); + assert(!!h && h > 0, "Not a valid height:" + h); + assert(clipRect, "No clip rect given!"); + } + + const scale = parameters.desiredAtlasScale; + const link = this.linksByResolution[scale]; + + if (!link) { + assert(false, `Link not known: ${scale} (having ${Object.keys(this.linksByResolution)})`); + } + + const scaleW = w / link.w; + const scaleH = h / link.h; + + let destX = x + link.packOffsetX * scaleW + clipRect.x * w; + let destY = y + link.packOffsetY * scaleH + clipRect.y * h; + let destW = link.packedW * scaleW * clipRect.w; + let destH = link.packedH * scaleH * clipRect.h; + + let srcX = link.packedX + clipRect.x * link.packedW; + let srcY = link.packedY + clipRect.y * link.packedH; + let srcW = link.packedW * clipRect.w; + let srcH = link.packedH * clipRect.h; + + parameters.context.drawImage( + link.atlas, + + // atlas src pos + srcX, + srcY, + + // atlas src siize + srcW, + srcH, + + // dest pos and size + destX - EXTRUDE, + destY - EXTRUDE, + destW + 2 * EXTRUDE, + destH + 2 * EXTRUDE + ); + } + + /** + * Renders into an html element + * @param {HTMLElement} element + * @param {number} w + * @param {number} h + */ + renderToHTMLElement(element, w = 1, h = 1) { + element.style.position = "relative"; + element.innerHTML = this.getAsHTML(w, h); + } + + /** + * Returns the html to render as icon + * @param {number} w + * @param {number} h + */ + getAsHTML(w, h) { + const link = this.linksByResolution["0.5"]; + + // Find out how much we have to scale it so that it fits + const scaleX = w / link.w; + const scaleY = h / link.h; + + // Find out how big the scaled atlas is + const atlasW = link.atlas.width * scaleX; + const atlasH = link.atlas.height * scaleY; + + // @ts-ignore + const srcSafe = link.atlas.src.replaceAll("\\", "/"); + + // Find out how big we render the sprite + const widthAbsolute = scaleX * link.packedW; + const heightAbsolute = scaleY * link.packedH; + + // Compute the position in the relative container + const leftRelative = (link.packOffsetX * scaleX) / w; + const topRelative = (link.packOffsetY * scaleY) / h; + const widthRelative = widthAbsolute / w; + const heightRelative = heightAbsolute / h; + + // Scale the atlas relative to the width and height of the element + const bgW = atlasW / widthAbsolute; + const bgH = atlasH / heightAbsolute; + + // Figure out what the position of the atlas is + const bgX = link.packedX * scaleX; + const bgY = link.packedY * scaleY; + + // Fuck you, whoever thought its a good idea to make background-position work like it does now + const bgXRelative = -bgX / (widthAbsolute - atlasW); + const bgYRelative = -bgY / (heightAbsolute - atlasH); + + return ` + + `; + } +} + +export class RegularSprite extends BaseSprite { + constructor(sprite, w, h) { + super(); + this.w = w; + this.h = h; + this.sprite = sprite; + } + + getRawTexture() { + return this.sprite; + } + + /** + * Draws the sprite, do *not* use this for sprites which are rendered! Only for drawing + * images into buffers + * @param {CanvasRenderingContext2D} context + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + */ + draw(context, x, y, w, h) { + assert(context, "No context given"); + assert(x !== undefined, "No x given"); + assert(y !== undefined, "No y given"); + assert(w !== undefined, "No width given"); + assert(h !== undefined, "No height given"); + context.drawImage(this.sprite, x, y, w, h); + } + + /** + * Draws the sprite, do *not* use this for sprites which are rendered! Only for drawing + * images into buffers + * @param {CanvasRenderingContext2D} context + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + */ + drawCentered(context, x, y, w, h) { + assert(context, "No context given"); + assert(x !== undefined, "No x given"); + assert(y !== undefined, "No y given"); + assert(w !== undefined, "No width given"); + assert(h !== undefined, "No height given"); + context.drawImage(this.sprite, x - w / 2, y - h / 2, w, h); + } +} diff --git a/src/js/core/stale_area_detector.js b/src/js/core/stale_area_detector.js new file mode 100644 index 00000000..5048ee37 --- /dev/null +++ b/src/js/core/stale_area_detector.js @@ -0,0 +1,90 @@ +import { Component } from "../game/component"; +import { Entity } from "../game/entity"; +import { globalConfig } from "./config"; +import { createLogger } from "./logging"; +import { Rectangle } from "./rectangle"; + +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(); + } + } + + /** + * Makes this detector recompute the area of an entity whenever + * it changes in any way + * @param {Array} components + * @param {number} tilesAround How many tiles arround to expand the area + */ + recomputeOnComponentsChanged(components, tilesAround) { + const componentIds = components.map(component => component.getId()); + + /** + * Internal checker method + * @param {Entity} entity + */ + const checker = entity => { + if (!this.root.gameInitialized) { + return; + } + + // Check for all components + for (let i = 0; i < componentIds.length; ++i) { + if (entity.components[componentIds[i]]) { + // Entity is relevant, compute affected area + const area = entity.components.StaticMapEntity.getTileSpaceBounds().expandedInAllDirections( + tilesAround + ); + this.invalidate(area); + return; + } + } + }; + + this.root.signals.entityAdded.add(checker); + this.root.signals.entityChanged.add(checker); + this.root.signals.entityComponentRemoved.add(checker); + this.root.signals.entityGotNewComponent.add(checker); + this.root.signals.entityDestroyed.add(checker); + } + + /** + * 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 cb00e465..98327378 100644 --- a/src/js/core/utils.js +++ b/src/js/core/utils.js @@ -1,969 +1,752 @@ -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=} 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); -} - -/** - * 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 - * @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 : ""); -} +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; +} + +/** + * Fills in a tag + * @param {string} translation + * @param {string} link + */ +export function fillInLinkIntoTranslation(translation, link) { + return translation + .replace("", "") + .replace("", ""); +} + +/** + * 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); +} + +/** + * Starts a file chooser + * @param {string} acceptedType + */ +export function startFileChoose(acceptedType = ".bin") { + var input = document.createElement("input"); + input.type = "file"; + input.accept = acceptedType; + + return new Promise(resolve => { + input.onchange = _ => resolve(input.files[0]); + input.click(); + }); +} + +const romanLiterals = [ + "0", // NULL + "I", + "II", + "III", + "IV", + "V", + "VI", + "VII", + "VIII", + "IX", + "X", + "XI", + "XII", + "XIII", + "XIV", + "XV", + "XVI", + "XVII", + "XVIII", + "XIX", + "XX", +]; + +/** + * + * @param {number} number + * @returns {string} + */ +export function getRomanNumber(number) { + number = Math.max(0, Math.round(number)); + if (number < romanLiterals.length) { + return romanLiterals[number]; + } + return String(number); +} 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..0075e6c1 100644 --- a/src/js/game/base_item.js +++ b/src/js/game/base_item.js @@ -1,61 +1,100 @@ -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, -}; - -/** - * Class for items on belts etc. Not an entity for performance reasons - */ -export class BaseItem extends BasicSerializableObject { - constructor() { - super(); - } - - static getId() { - return "base_item"; - } - - /** @returns {object} */ - static getSchema() { - return {}; - } - - /** @returns {enumItemType} */ - getItemType() { - abstract; - return ""; - } - - /** - * Draws the item at the given position - * @param {number} x - * @param {number} y - * @param {DrawParameters} parameters - * @param {number=} size - */ - draw(x, y, parameters, size) {} - - getBackgroundColorAsResource() { - abstract; - return ""; - } -} +import { globalConfig } from "../core/config"; +import { DrawParameters } from "../core/draw_parameters"; +import { BasicSerializableObject } from "../savegame/serialization"; + +/** @type {ItemType[]} **/ +export const itemTypes = ["shape", "color", "boolean"]; + +/** + * Class for items on belts etc. Not an entity for performance reasons + */ +export class BaseItem extends BasicSerializableObject { + constructor() { + super(); + } + + static getId() { + return "base_item"; + } + + /** @returns {object} */ + static getSchema() { + return {}; + } + + /** @returns {ItemType} **/ + getItemType() { + abstract; + return "shape"; + } + + /** + * Returns a string id of the item + * @returns {string} + */ + getAsCopyableKey() { + abstract; + return ""; + } + + /** + * 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; + } + + /** + * Draws the item to a canvas + * @param {CanvasRenderingContext2D} context + * @param {number} size + */ + drawFullSizeOnCanvas(context, size) { + abstract; + } + + /** + * Draws the item at the given position + * @param {number} x + * @param {number} y + * @param {DrawParameters} parameters + * @param {number=} diameter + */ + 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; + return ""; + } +} diff --git a/src/js/game/belt_path.js b/src/js/game/belt_path.js index 0b6da48c..eb55d613 100644 --- a/src/js/game/belt_path.js +++ b/src/js/game/belt_path.js @@ -1,1166 +1,1405 @@ -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 { clamp, epsilonCompare, round4Digits } 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(); + + /** + * How many items past the first item are compressed + */ + this.numCompressedItemsAfterFirstItem = 0; + } + + /** + * Called by the belt system when the surroundings changed + */ + onSurroundingsChanged() { + this.onPathChanged(); + } + + /** + * Finds the entity which accepts our items + * @param {boolean=} debug_Silent Whether debug output should be silent + * @return {{ entity: Entity, slot: number, direction?: enumDirection }} + */ + computeAcceptingEntityAndSlot(debug_Silent = false) { + DEBUG && !debug_Silent && logger.log("Recomputing acceptor target"); + + 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) { + DEBUG && !debug_Silent && logger.log(" Found target entity", targetEntity.uid); + const targetStaticComp = targetEntity.components.StaticMapEntity; + const targetBeltComp = targetEntity.components.Belt; + + // Check for belts (special case) + if (targetBeltComp) { + const beltAcceptingDirection = targetStaticComp.localDirectionToWorld(enumDirection.top); + DEBUG && + !debug_Silent && + logger.log( + " Entity is accepting items from", + ejectSlotWsDirection, + "vs", + beltAcceptingDirection, + "Rotation:", + targetStaticComp.rotation + ); + 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"); + } + + // Check acceptor + const acceptor = this.computeAcceptingEntityAndSlot(true); + if (!!acceptor !== !!this.acceptorTarget) { + return fail("Acceptor target mismatch, acceptor", !!acceptor, "vs stored", !!this.acceptorTarget); + } + + if (acceptor) { + if (this.acceptorTarget.entity !== acceptor.entity) { + return fail( + "Mismatching entity on acceptor target:", + acceptor.entity.uid, + "vs", + this.acceptorTarget.entity.uid + ); + } + + if (this.acceptorTarget.slot !== acceptor.slot) { + return fail( + "Mismatching entity on acceptor target:", + acceptor.slot, + "vs stored", + this.acceptorTarget.slot + ); + } + + if (this.acceptorTarget.direction !== acceptor.direction) { + return fail( + "Mismatching direction on acceptor target:", + acceptor.direction, + "vs stored", + this.acceptorTarget.direction + ); + } + } + + // Check first nonzero offset + let firstNonzero = 0; + for (let i = this.items.length - 2; i >= 0; --i) { + if (this.items[i][_nextDistance] < globalConfig.itemSpacingOnBelts + 1e-5) { + ++firstNonzero; + } else { + break; + } + } + + // Should warn, but this check isn't actually accurate + // if (firstNonzero !== this.numCompressedItemsAfterFirstItem) { + // console.warn( + // "First nonzero index is " + + // firstNonzero + + // " but stored is " + + // this.numCompressedItemsAfterFirstItem + // ); + // } + } + + /* 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; + + // Store the last item we processed, so we can skip clashed ones + let lastItemProcessed; + + for (lastItemProcessed = this.items.length - 1; lastItemProcessed >= 0; --lastItemProcessed) { + const nextDistanceAndItem = this.items[lastItemProcessed]; + + // Compute how much spacing we need at least + const minimumSpacing = + lastItemProcessed === 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(); + + this.numCompressedItemsAfterFirstItem = Math.max( + 0, + this.numCompressedItemsAfterFirstItem - 1 + ); + } + } + + if (isFirstItemProcessed) { + // Skip N null items after first items + lastItemProcessed -= this.numCompressedItemsAfterFirstItem; + } + + isFirstItemProcessed = false; + this.spacingToFirstItem += clampedProgress; + if (remainingVelocity < 1e-7) { + break; + } + } + + // Compute compressed item count + this.numCompressedItemsAfterFirstItem = Math.max( + 0, + this.numCompressedItemsAfterFirstItem, + this.items.length - 2 - lastItemProcessed + ); + + // 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(); + this.numCompressedItemsAfterFirstItem = Math.max( + 0, + this.numCompressedItemsAfterFirstItem - 1 + ); + } + } + + 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) { + if (!this.root.app.settings.getAllSettings().simplifiedBelts) { + 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 issues .. + 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]; + + if (this.items.length - 1 - this.numCompressedItemsAfterFirstItem === i) { + parameters.context.fillStyle = "red"; + parameters.context.fillRect(worldPos.x + 5, worldPos.y, 20, 3); + } + } + + 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); + } + + /** + * Checks if this belt path should render simplified + */ + checkIsPotatoMode() { + // POTATO Mode: Only show items when belt is hovered + if (!this.root.app.settings.getAllSettings().simplifiedBelts) { + return false; + } + + if (this.root.currentLayer !== "regular") { + // Not in regular layer + return true; + } + + const mousePos = this.root.app.mousePosition; + if (!mousePos) { + // Mouse not registered + return true; + } + + const tile = this.root.camera.screenToWorld(mousePos).toTileSpace(); + const contents = this.root.map.getLayerContentXY(tile.x, tile.y, "regular"); + if (!contents || !contents.components.Belt) { + // Nothing below + return true; + } + + if (contents.components.Belt.assignedPath !== this) { + // Not this path + return true; + } + return false; + } + + /** + * Draws the path + * @param {DrawParameters} parameters + */ + draw(parameters) { + if (!parameters.visibleRect.containsRect(this.worldBounds)) { + return; + } + + if (this.items.length === 0) { + // Early out + return; + } + + if (this.checkIsPotatoMode()) { + const firstItem = this.items[0]; + if (this.entityPath.length > 1 && firstItem) { + const medianBeltIndex = clamp( + Math.round(this.entityPath.length / 2 - 1), + 0, + this.entityPath.length - 1 + ); + const medianBelt = this.entityPath[medianBeltIndex]; + const beltComp = medianBelt.components.Belt; + const staticComp = medianBelt.components.StaticMapEntity; + const centerPosLocal = beltComp.transformBeltToLocalSpace( + this.entityPath.length % 2 === 0 ? beltComp.getEffectiveLengthTiles() : 0.5 + ); + const centerPos = staticComp.localTileToWorld(centerPosLocal).toWorldSpaceCenterOfTile(); + + parameters.context.globalAlpha = 0.5; + firstItem[_item].drawItemCenteredClipped(centerPos.x, centerPos.y, parameters); + parameters.context.globalAlpha = 1; + } + + 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) { + // It's 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..63989393 100644 --- a/src/js/game/blueprint.js +++ b/src/js/game/blueprint.js @@ -1,14 +1,9 @@ +import { globalConfig } from "../core/config"; import { DrawParameters } from "../core/draw_parameters"; -import { Loader } from "../core/loader"; -import { createLogger } from "../core/logging"; +import { findNiceIntegerValue } from "../core/utils"; import { Vector } from "../core/vector"; import { Entity } from "./entity"; -import { GameRoot, enumLayer } from "./root"; -import { findNiceIntegerValue } from "../core/utils"; -import { blueprintShape } from "./upgrades"; -import { globalConfig } from "../core/config"; - -const logger = createLogger("blueprint"); +import { GameRoot } from "./root"; export class Blueprint { /** @@ -20,11 +15,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; } @@ -44,7 +39,7 @@ export class Blueprint { const entity = root.entityMgr.findByUid(uids[i]); assert(entity, "Entity for blueprint not found:" + uids[i]); - const clone = entity.duplicateWithoutContents(); + const clone = entity.clone(); newEntities.push(clone); const pos = entity.components.StaticMapEntity.getTileSpaceBounds().getCenter(); @@ -81,10 +76,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 +87,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; } @@ -153,7 +138,7 @@ export class Blueprint { * @param {GameRoot} root */ canAfford(root) { - return root.hubGoals.getShapesStoredByKey(blueprintShape) >= this.getCost(); + return root.hubGoals.getShapesStoredByKey(root.gameMode.getBlueprintShapeKey()) >= this.getCost(); } /** @@ -170,7 +155,7 @@ export class Blueprint { continue; } - const clone = entity.duplicateWithoutContents(); + const clone = entity.clone(); clone.components.StaticMapEntity.origin.addInplace(tile); root.logic.freeEntityAreaBeforeBuild(clone); root.map.placeStaticEntity(clone); diff --git a/src/js/game/building_codes.js b/src/js/game/building_codes.js new file mode 100644 index 00000000..78240c31 --- /dev/null +++ b/src/js/game/building_codes.js @@ -0,0 +1,95 @@ +/* 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 +}; + +/** + * Mapping from 'metaBuildingId/variant/rotationVariant' to building code + * @type {Map} + */ +const variantsCache = new Map(); + +/** + * Registers a new variant + * @param {number} code + * @param {typeof MetaBuilding} meta + * @param {string} variant + * @param {number} rotationVariant + */ +export function registerBuildingVariant( + code, + meta, + variant = "default" /* @TODO: Circular dependency, actually its defaultBuildingVariant */, + rotationVariant = 0 +) { + assert(!gBuildingVariants[code], "Duplicate id: " + code); + gBuildingVariants[code] = { + 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]; +} + +/** + * Builds the cache for the codes + */ +export function buildBuildingCodeCache() { + for (const code in gBuildingVariants) { + const data = gBuildingVariants[code]; + const hash = data.metaInstance.getId() + "/" + data.variant + "/" + data.rotationVariant; + variantsCache.set(hash, +code); + } +} + +/** + * Finds the code for a given variant + * @param {MetaBuilding} metaBuilding + * @param {string} variant + * @param {number} rotationVariant + * @returns {number} + */ +export function getCodeFromBuildingData(metaBuilding, variant, rotationVariant) { + const hash = metaBuilding.getId() + "/" + variant + "/" + rotationVariant; + const result = variantsCache.get(hash); + if (G_IS_DEV) { + if (!result) { + console.warn("Known hashes:", Array.from(variantsCache.keys())); + assertAlways(false, "Building not found by data: " + hash); + } + } + return result; +} 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/analyzer.js b/src/js/game/buildings/analyzer.js new file mode 100644 index 00000000..8335f730 --- /dev/null +++ b/src/js/game/buildings/analyzer.js @@ -0,0 +1,79 @@ +import { generateMatrixRotations } from "../../core/utils"; +import { enumDirection, Vector } from "../../core/vector"; +import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { enumHubGoalRewards } from "../tutorial_goals"; + +const overlayMatrix = generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 0]); + +export class MetaAnalyzerBuilding extends MetaBuilding { + constructor() { + super("analyzer"); + } + + getSilhouetteColor() { + return "#3a52bc"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_virtual_processing); + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getDimensions() { + return new Vector(1, 1); + } + + getRenderPins() { + // We already have it included + return false; + } + + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) { + return overlayMatrix[rotation]; + } + + /** + * 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.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.right, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + ], + }) + ); + + entity.addComponent( + new LogicGateComponent({ + type: enumLogicGateType.analyzer, + }) + ); + } +} diff --git a/src/js/game/buildings/balancer.js b/src/js/game/buildings/balancer.js new file mode 100644 index 00000000..2f14e36c --- /dev/null +++ b/src/js/game/buildings/balancer.js @@ -0,0 +1,231 @@ +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, generateMatrixRotations } from "../../core/utils"; +import { BeltUnderlaysComponent } from "../components/belt_underlays"; + +/** @enum {string} */ +export const enumBalancerVariants = { + merger: "merger", + mergerInverse: "merger-inverse", + splitter: "splitter", + splitterInverse: "splitter-inverse", +}; + +const overlayMatrices = { + [defaultBuildingVariant]: null, + [enumBalancerVariants.merger]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 0, 1, 0]), + [enumBalancerVariants.mergerInverse]: generateMatrixRotations([0, 1, 0, 1, 1, 0, 0, 1, 0]), + [enumBalancerVariants.splitter]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 0, 1, 0]), + [enumBalancerVariants.splitterInverse]: generateMatrixRotations([0, 1, 0, 1, 1, 0, 0, 1, 0]), +}; + +export class MetaBalancerBuilding extends MetaBuilding { + constructor() { + super("balancer"); + } + + getDimensions(variant) { + switch (variant) { + case defaultBuildingVariant: + return new Vector(2, 1); + case enumBalancerVariants.merger: + case enumBalancerVariants.mergerInverse: + case enumBalancerVariants.splitter: + case enumBalancerVariants.splitterInverse: + return new Vector(1, 1); + default: + assertAlways(false, "Unknown balancer variant: " + variant); + } + } + + /** + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + * @returns {Array|null} + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + const matrix = overlayMatrices[variant]; + if (matrix) { + return matrix[rotation]; + } + return null; + } + + /** + * @param {GameRoot} root + * @param {string} variant + * @returns {Array<[string, string]>} + */ + getAdditionalStatistics(root, variant) { + let speedMultiplier = 2; + switch (variant) { + case enumBalancerVariants.merger: + case enumBalancerVariants.mergerInverse: + case enumBalancerVariants.splitter: + case enumBalancerVariants.splitterInverse: + speedMultiplier = 1; + } + + const speed = + (root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.balancer) / 2) * speedMultiplier; + return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; + } + + getSilhouetteColor() { + return "#555759"; + } + + /** + * @param {GameRoot} root + */ + getAvailableVariants(root) { + let available = [defaultBuildingVariant]; + + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_merger)) { + available.push(enumBalancerVariants.merger, enumBalancerVariants.mergerInverse); + } + + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_splitter)) { + available.push(enumBalancerVariants.splitter, enumBalancerVariants.splitterInverse); + } + + return available; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_balancer); + } + + /** + * 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.balancer, + }) + ); + + entity.addComponent( + new ItemEjectorComponent({ + slots: [], // set later + renderFloatingItems: false, + }) + ); + + 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 enumBalancerVariants.merger: + case enumBalancerVariants.mergerInverse: { + entity.components.ItemAcceptor.setSlots([ + { + pos: new Vector(0, 0), + directions: [enumDirection.bottom], + }, + { + pos: new Vector(0, 0), + directions: [ + variant === enumBalancerVariants.mergerInverse + ? 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 enumBalancerVariants.splitter: + case enumBalancerVariants.splitterInverse: { + 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 === enumBalancerVariants.splitterInverse + ? enumDirection.left + : enumDirection.right, + }, + ]); + + entity.components.BeltUnderlays.underlays = [ + { pos: new Vector(0, 0), direction: enumDirection.top }, + ]; + + break; + } + default: + assertAlways(false, "Unknown balancer variant: " + variant); + } + } +} diff --git a/src/js/game/buildings/belt.js b/src/js/game/buildings/belt.js index 1fb80b88..84646b19 100644 --- a/src/js/game/buildings/belt.js +++ b/src/js/game/buildings/belt.js @@ -1,52 +1,229 @@ -import { Loader } from "../../core/loader"; -import { enumDirection } from "../../core/vector"; -import { SOUNDS } from "../../platform/sound"; -import { arrayBeltVariantToRotation, MetaBeltBaseBuilding } from "./belt_base"; - -export class MetaBeltBuilding extends MetaBeltBaseBuilding { - constructor() { - super("belt"); - } - - getSilhouetteColor() { - return "#777"; - } - - getPlacementSound() { - return SOUNDS.placeBelt; - } - - getPreviewSprite(rotationVariant) { - switch (arrayBeltVariantToRotation[rotationVariant]) { - case enumDirection.top: { - return Loader.getSprite("sprites/buildings/belt_top.png"); - } - case enumDirection.left: { - return Loader.getSprite("sprites/buildings/belt_left.png"); - } - case enumDirection.right: { - return Loader.getSprite("sprites/buildings/belt_right.png"); - } - default: { - assertAlways(false, "Invalid belt rotation variant"); - } - } - } - - getBlueprintSprite(rotationVariant) { - switch (arrayBeltVariantToRotation[rotationVariant]) { - case enumDirection.top: { - return Loader.getSprite("sprites/blueprints/belt_top.png"); - } - case enumDirection.left: { - return Loader.getSprite("sprites/blueprints/belt_left.png"); - } - case enumDirection.right: { - return Loader.getSprite("sprites/blueprints/belt_right.png"); - } - default: { - assertAlways(false, "Invalid belt rotation variant"); - } - } - } -} +import { Loader } from "../../core/loader"; +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 { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { THEME } from "../theme"; + +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 MetaBeltBuilding extends MetaBuilding { + constructor() { + super("belt"); + } + + getSilhouetteColor() { + return THEME.map.chunkOverview.beltColor; + } + + getPlacementSound() { + return SOUNDS.placeBelt; + } + + getHasDirectionLockAvailable() { + return true; + } + getStayInPlacementMode() { + return true; + } + + getRotateAutomaticallyWhilePlacing() { + return true; + } + + getSprite() { + return null; + } + + getIsReplaceable() { + return true; + } + + /** + * @param {GameRoot} root + * @param {string} variant + * @returns {Array<[string, string]>} + */ + getAdditionalStatistics(root, variant) { + const beltSpeed = root.hubGoals.getBeltBaseSpeed(); + return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]]; + } + + getPreviewSprite(rotationVariant) { + switch (arrayBeltVariantToRotation[rotationVariant]) { + case enumDirection.top: { + return Loader.getSprite("sprites/buildings/belt_top.png"); + } + case enumDirection.left: { + return Loader.getSprite("sprites/buildings/belt_left.png"); + } + case enumDirection.right: { + return Loader.getSprite("sprites/buildings/belt_right.png"); + } + default: { + assertAlways(false, "Invalid belt rotation variant"); + } + } + } + + getBlueprintSprite(rotationVariant) { + switch (arrayBeltVariantToRotation[rotationVariant]) { + case enumDirection.top: { + return Loader.getSprite("sprites/blueprints/belt_top.png"); + } + case enumDirection.left: { + return Loader.getSprite("sprites/blueprints/belt_left.png"); + } + case enumDirection.right: { + return Loader.getSprite("sprites/blueprints/belt_right.png"); + } + default: { + assertAlways(false, "Invalid belt rotation variant"); + } + } + } + + /** + * + * @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 + */ + setupEntityComponents(entity) { + entity.addComponent( + new BeltComponent({ + direction: enumDirection.top, // updated later + }) + ); + } + + /** + * + * @param {Entity} entity + * @param {number} rotationVariant + */ + updateVariants(entity, rotationVariant) { + entity.components.Belt.direction = arrayBeltVariantToRotation[rotationVariant]; + } + + /** + * 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 {Layer} param0.layer + * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array }} + */ + computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { + const topDirection = enumAngleToDirection[rotation]; + const rightDirection = enumAngleToDirection[(rotation + 90) % 360]; + const bottomDirection = enumAngleToDirection[(rotation + 180) % 360]; + const leftDirection = enumAngleToDirection[(rotation + 270) % 360]; + + const { ejectors, acceptors } = root.logic.getEjectorsAndAcceptorsAtTile(tile); + + let hasBottomEjector = false; + let hasRightEjector = false; + let hasLeftEjector = false; + + let hasTopAcceptor = false; + let hasLeftAcceptor = false; + let hasRightAcceptor = false; + + // Check all ejectors + for (let i = 0; i < ejectors.length; ++i) { + const ejector = ejectors[i]; + + if (ejector.toDirection === topDirection) { + hasBottomEjector = true; + } else if (ejector.toDirection === leftDirection) { + hasRightEjector = true; + } else if (ejector.toDirection === rightDirection) { + hasLeftEjector = true; + } + } + + // Check all acceptors + for (let i = 0; i < acceptors.length; ++i) { + const acceptor = acceptors[i]; + if (acceptor.fromDirection === bottomDirection) { + hasTopAcceptor = true; + } else if (acceptor.fromDirection === rightDirection) { + hasLeftAcceptor = true; + } else if (acceptor.fromDirection === leftDirection) { + hasRightAcceptor = true; + } + } + + // Soo .. if there is any ejector below us we always prioritize + // this ejector + if (!hasBottomEjector) { + // When something ejects to us from the left and nothing from the right, + // do a curve from the left to the top + + if (hasRightEjector && !hasLeftEjector) { + return { + rotation: (rotation + 270) % 360, + rotationVariant: 2, + }; + } + + // When something ejects to us from the right and nothing from the left, + // do a curve from the right to the top + if (hasLeftEjector && !hasRightEjector) { + return { + rotation: (rotation + 90) % 360, + rotationVariant: 1, + }; + } + } + + // When there is a top acceptor, ignore sides + // NOTICE: This makes the belt prefer side turns *way* too much! + if (!hasTopAcceptor) { + // When there is an acceptor to the right but no acceptor to the left, + // do a turn to the right + if (hasRightAcceptor && !hasLeftAcceptor) { + return { + rotation, + rotationVariant: 2, + }; + } + + // When there is an acceptor to the left but no acceptor to the right, + // do a turn to the left + if (hasLeftAcceptor && !hasRightAcceptor) { + return { + rotation, + rotationVariant: 1, + }; + } + } + + return { + rotation, + rotationVariant: 0, + }; + } +} diff --git a/src/js/game/buildings/belt_base.js b/src/js/game/buildings/belt_base.js deleted file mode 100644 index b8e92150..00000000 --- a/src/js/game/buildings/belt_base.js +++ /dev/null @@ -1,195 +0,0 @@ -import { Loader } from "../../core/loader"; -import { formatItemsPerSecond } 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"; - -export const arrayBeltVariantToRotation = [enumDirection.top, enumDirection.left, enumDirection.right]; - -export class MetaBeltBaseBuilding extends MetaBuilding { - getHasDirectionLockAvailable() { - return true; - } - - /** - * @param {GameRoot} root - * @param {string} variant - * @returns {Array<[string, string]>} - */ - getAdditionalStatistics(root, variant) { - const beltSpeed = root.hubGoals.getBeltBaseSpeed(enumLayer.regular); - return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]]; - } - - getStayInPlacementMode() { - return true; - } - - getRotateAutomaticallyWhilePlacing() { - return true; - } - - getPlacementSound() { - return SOUNDS.placeBelt; - } - - /** - * Creates the entity at the given location - * @param {Entity} entity - */ - setupEntityComponents(entity) { - entity.addComponent( - new BeltComponent({ - 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, - }) - ); - } - - /** - * - * @param {Entity} entity - * @param {number} rotationVariant - */ - updateVariants(entity, rotationVariant) { - entity.components.Belt.direction = arrayBeltVariantToRotation[rotationVariant]; - entity.components.ItemEjector.slots[0].direction = arrayBeltVariantToRotation[rotationVariant]; - entity.components.StaticMapEntity.spriteKey = null; - } - - /** - * 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 topDirection = enumAngleToDirection[rotation]; - const rightDirection = enumAngleToDirection[(rotation + 90) % 360]; - const bottomDirection = enumAngleToDirection[(rotation + 180) % 360]; - const leftDirection = enumAngleToDirection[(rotation + 270) % 360]; - - const { ejectors, acceptors } = root.logic.getEjectorsAndAcceptorsAtTile(tile, layer); - - let hasBottomEjector = false; - let hasRightEjector = false; - let hasLeftEjector = false; - - let hasTopAcceptor = false; - let hasLeftAcceptor = false; - let hasRightAcceptor = false; - - // Check all ejectors - for (let i = 0; i < ejectors.length; ++i) { - const ejector = ejectors[i]; - - if (ejector.toDirection === topDirection) { - hasBottomEjector = true; - } else if (ejector.toDirection === leftDirection) { - hasRightEjector = true; - } else if (ejector.toDirection === rightDirection) { - hasLeftEjector = true; - } - } - - // Check all acceptors - for (let i = 0; i < acceptors.length; ++i) { - const acceptor = acceptors[i]; - if (acceptor.fromDirection === bottomDirection) { - hasTopAcceptor = true; - } else if (acceptor.fromDirection === rightDirection) { - hasLeftAcceptor = true; - } else if (acceptor.fromDirection === leftDirection) { - hasRightAcceptor = true; - } - } - - // Soo .. if there is any ejector below us we always prioritize - // this ejector - if (!hasBottomEjector) { - // When something ejects to us from the left and nothing from the right, - // do a curve from the left to the top - - if (hasRightEjector && !hasLeftEjector) { - return { - rotation: (rotation + 270) % 360, - rotationVariant: 2, - }; - } - - // When something ejects to us from the right and nothing from the left, - // do a curve from the right to the top - if (hasLeftEjector && !hasRightEjector) { - return { - rotation: (rotation + 90) % 360, - rotationVariant: 1, - }; - } - } - - // When there is a top acceptor, ignore sides - // NOTICE: This makes the belt prefer side turns *way* too much! - if (!hasTopAcceptor) { - // When there is an acceptor to the right but no acceptor to the left, - // do a turn to the right - if (hasRightAcceptor && !hasLeftAcceptor) { - return { - rotation, - rotationVariant: 2, - }; - } - - // When there is an acceptor to the left but no acceptor to the right, - // do a turn to the left - if (hasLeftAcceptor && !hasRightAcceptor) { - return { - rotation, - rotationVariant: 1, - }; - } - } - - return { - rotation, - rotationVariant: 0, - }; - } -} diff --git a/src/js/game/buildings/comparator.js b/src/js/game/buildings/comparator.js new file mode 100644 index 00000000..6738d514 --- /dev/null +++ b/src/js/game/buildings/comparator.js @@ -0,0 +1,72 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { enumHubGoalRewards } from "../tutorial_goals"; + +export class MetaComparatorBuilding extends MetaBuilding { + constructor() { + super("comparator"); + } + + getSilhouetteColor() { + return "#823cab"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_virtual_processing); + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getDimensions() { + return new Vector(1, 1); + } + + getRenderPins() { + // We already have it included + 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, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.left, + type: enumPinSlotType.logicalAcceptor, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.right, + type: enumPinSlotType.logicalAcceptor, + }, + ], + }) + ); + + entity.addComponent( + new LogicGateComponent({ + type: enumLogicGateType.compare, + }) + ); + } +} diff --git a/src/js/game/buildings/constant_signal.js b/src/js/game/buildings/constant_signal.js new file mode 100644 index 00000000..983594cb --- /dev/null +++ b/src/js/game/buildings/constant_signal.js @@ -0,0 +1,63 @@ +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"; +import { generateMatrixRotations } from "../../core/utils"; +import { enumHubGoalRewards } from "../tutorial_goals"; + +const overlayMatrix = generateMatrixRotations([0, 1, 0, 1, 1, 1, 1, 1, 1]); + +export class MetaConstantSignalBuilding extends MetaBuilding { + constructor() { + super("constant_signal"); + } + + getSilhouetteColor() { + return "#2b84fd"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_constant_signal); + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getDimensions() { + return new Vector(1, 1); + } + + getRenderPins() { + return false; + } + + getSpecialOverlayRenderMatrix(rotation) { + return overlayMatrix[rotation]; + } + + /** + * 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..422bea81 --- /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"; +import { enumHubGoalRewards } from "../tutorial_goals"; + +export class MetaDisplayBuilding extends MetaBuilding { + constructor() { + super("display"); + } + + getSilhouetteColor() { + return "#aaaaaa"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_display); + } + + 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/filter.js b/src/js/game/buildings/filter.js new file mode 100644 index 00000000..2d81ce83 --- /dev/null +++ b/src/js/game/buildings/filter.js @@ -0,0 +1,92 @@ +import { formatItemsPerSecond } from "../../core/utils"; +import { enumDirection, Vector } from "../../core/vector"; +import { T } from "../../translations"; +import { FilterComponent } from "../components/filter"; +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 { GameRoot } from "../root"; +import { enumHubGoalRewards } from "../tutorial_goals"; + +export class MetaFilterBuilding extends MetaBuilding { + constructor() { + super("filter"); + } + + getSilhouetteColor() { + return "#c45c2e"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_filter); + } + + getDimensions() { + return new Vector(2, 1); + } + + getShowWiresLayerPreview() { + return true; + } + + /** + * @param {GameRoot} root + * @param {string} variant + * @returns {Array<[string, string]>} + */ + getAdditionalStatistics(root, variant) { + const beltSpeed = root.hubGoals.getBeltBaseSpeed(); + return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]]; + } + + /** + * 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 FilterComponent()); + } +} 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/item_producer.js b/src/js/game/buildings/item_producer.js new file mode 100644 index 00000000..477ed603 --- /dev/null +++ b/src/js/game/buildings/item_producer.js @@ -0,0 +1,44 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { ItemEjectorComponent } from "../components/item_ejector"; +import { ItemProducerComponent } from "../components/item_producer"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; + +export class MetaItemProducerBuilding extends MetaBuilding { + constructor() { + super("item_producer"); + } + + getSilhouetteColor() { + return "#b37dcd"; + } + + getShowWiresLayerPreview() { + return true; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new ItemEjectorComponent({ + slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }], + }) + ); + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(0, 0), + type: enumPinSlotType.logicalAcceptor, + direction: enumDirection.bottom, + }, + ], + }) + ); + entity.addComponent(new ItemProducerComponent()); + } +} diff --git a/src/js/game/buildings/lever.js b/src/js/game/buildings/lever.js new file mode 100644 index 00000000..7ddaf65f --- /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"; +import { enumHubGoalRewards } from "../tutorial_goals"; + +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) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers); + } + + 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..b61d4373 --- /dev/null +++ b/src/js/game/buildings/logic_gate.js @@ -0,0 +1,151 @@ +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"; +import { generateMatrixRotations } from "../../core/utils"; +import { enumHubGoalRewards } from "../tutorial_goals"; + +/** @enum {string} */ +export const enumLogicGateVariants = { + not: "not", + xor: "xor", + or: "or", +}; + +/** @enum {string} */ +export const enumVariantToGate = { + [defaultBuildingVariant]: enumLogicGateType.and, + [enumLogicGateVariants.not]: enumLogicGateType.not, + [enumLogicGateVariants.xor]: enumLogicGateType.xor, + [enumLogicGateVariants.or]: enumLogicGateType.or, +}; + +const overlayMatrices = { + [defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]), + [enumLogicGateVariants.xor]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]), + [enumLogicGateVariants.or]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]), + [enumLogicGateVariants.not]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]), +}; + +const colors = { + [defaultBuildingVariant]: "#f48d41", + [enumLogicGateVariants.xor]: "#f4a241", + [enumLogicGateVariants.or]: "#f4d041", + [enumLogicGateVariants.not]: "#f44184", +}; + +export class MetaLogicGateBuilding extends MetaBuilding { + constructor() { + super("logic_gate"); + } + + getSilhouetteColor(variant) { + return colors[variant]; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_logic_gates); + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getDimensions() { + return new Vector(1, 1); + } + + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) { + return overlayMatrices[variant][rotation]; + } + + getAvailableVariants() { + return [ + defaultBuildingVariant, + enumLogicGateVariants.or, + enumLogicGateVariants.not, + enumLogicGateVariants.xor, + ]; + } + + 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.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..f0b837a1 100644 --- a/src/js/game/buildings/miner.js +++ b/src/js/game/buildings/miner.js @@ -1,66 +1,81 @@ -import { enumDirection, Vector } from "../../core/vector"; -import { ItemEjectorComponent } from "../components/item_ejector"; -import { MinerComponent } from "../components/miner"; -import { Entity } from "../entity"; -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"; - -/** @enum {string} */ -export const enumMinerVariants = { chainable: "chainable" }; - -export class MetaMinerBuilding extends MetaBuilding { - constructor() { - super("miner"); - } - - getSilhouetteColor() { - return "#b37dcd"; - } - - /** - * @param {GameRoot} root - * @param {string} variant - * @returns {Array<[string, string]>} - */ - getAdditionalStatistics(root, variant) { - const speed = root.hubGoals.getMinerBaseSpeed(); - return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; - } - - /** - * - * @param {GameRoot} root - */ - getAvailableVariants(root) { - if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_miner_chainable)) { - return [defaultBuildingVariant, enumMinerVariants.chainable]; - } - return super.getAvailableVariants(root); - } - - /** - * Creates the entity at the given location - * @param {Entity} entity - */ - setupEntityComponents(entity) { - entity.addComponent(new MinerComponent({})); - entity.addComponent( - new ItemEjectorComponent({ - slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }], - }) - ); - } - - /** - * - * @param {Entity} entity - * @param {number} rotationVariant - * @param {string} variant - */ - updateVariants(entity, rotationVariant, variant) { - entity.components.Miner.chainable = variant === enumMinerVariants.chainable; - } -} +import { enumDirection, Vector } from "../../core/vector"; +import { ItemEjectorComponent } from "../components/item_ejector"; +import { MinerComponent } from "../components/miner"; +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, generateMatrixRotations } from "../../core/utils"; + +/** @enum {string} */ +export const enumMinerVariants = { chainable: "chainable" }; + +const overlayMatrix = { + [defaultBuildingVariant]: generateMatrixRotations([1, 1, 1, 1, 0, 1, 1, 1, 1]), + [enumMinerVariants.chainable]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 1, 1, 1]), +}; + +export class MetaMinerBuilding extends MetaBuilding { + constructor() { + super("miner"); + } + + getSilhouetteColor() { + return "#b37dcd"; + } + + /** + * @param {GameRoot} root + * @param {string} variant + * @returns {Array<[string, string]>} + */ + getAdditionalStatistics(root, variant) { + const speed = root.hubGoals.getMinerBaseSpeed(); + return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; + } + + /** + * + * @param {GameRoot} root + */ + getAvailableVariants(root) { + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_miner_chainable)) { + return [enumMinerVariants.chainable]; + } + return super.getAvailableVariants(root); + } + + /** + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return overlayMatrix[variant][rotation]; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent(new MinerComponent({})); + entity.addComponent( + new ItemEjectorComponent({ + slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }], + }) + ); + } + + /** + * + * @param {Entity} entity + * @param {number} rotationVariant + * @param {string} variant + */ + updateVariants(entity, rotationVariant, variant) { + entity.components.Miner.chainable = variant === enumMinerVariants.chainable; + } +} 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..6e941403 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" }; @@ -67,7 +71,7 @@ export class MetaPainterBuilding extends MetaBuilding { if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_painter_double)) { variants.push(enumPainterVariants.double); } - if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_painter_quad)) { + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers)) { variants.push(enumPainterVariants.quad); } return variants; @@ -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..006d6582 --- /dev/null +++ b/src/js/game/buildings/reader.js @@ -0,0 +1,115 @@ +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"; +import { enumHubGoalRewards } from "../tutorial_goals"; +import { generateMatrixRotations } from "../../core/utils"; + +const overlayMatrix = generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]); + +export class MetaReaderBuilding extends MetaBuilding { + constructor() { + super("reader"); + } + + getSilhouetteColor() { + return "#25fff2"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_belt_reader); + } + + getDimensions() { + return new Vector(1, 1); + } + + getShowWiresLayerPreview() { + return true; + } + + /** + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + * @returns {Array|null} + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return overlayMatrix[rotation]; + } + + /** + * 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..7df94d16 100644 --- a/src/js/game/buildings/rotater.js +++ b/src/js/game/buildings/rotater.js @@ -1,107 +1,143 @@ -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 enumRotaterVariants = { ccw: "ccw" }; - -export class MetaRotaterBuilding extends MetaBuilding { - constructor() { - super("rotater"); - } - - getSilhouetteColor() { - return "#7dc6cd"; - } - - /** - * @param {GameRoot} root - * @param {string} variant - * @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)]]; - } - - /** - * - * @param {GameRoot} root - */ - getAvailableVariants(root) { - if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater_ccw)) { - return [defaultBuildingVariant, enumRotaterVariants.ccw]; - } - return super.getAvailableVariants(root); - } - - /** - * @param {GameRoot} root - */ - getIsUnlocked(root) { - return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater); - } - - /** - * Creates the entity at the given location - * @param {Entity} entity - */ - setupEntityComponents(entity) { - entity.addComponent( - new ItemProcessorComponent({ - inputsPerCharge: 1, - processorType: enumItemProcessorTypes.rotater, - }) - ); - - entity.addComponent( - new ItemEjectorComponent({ - slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }], - }) - ); - 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.ItemProcessor.type = enumItemProcessorTypes.rotater; - break; - } - case enumRotaterVariants.ccw: { - entity.components.ItemProcessor.type = enumItemProcessorTypes.rotaterCCW; - break; - } - default: - assertAlways(false, "Unknown rotater variant: " + variant); - } - } -} +import { formatItemsPerSecond, generateMatrixRotations } 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 enumRotaterVariants = { ccw: "ccw", rotate180: "rotate180" }; + +const overlayMatrices = { + [defaultBuildingVariant]: generateMatrixRotations([0, 1, 1, 1, 1, 0, 0, 1, 1]), + [enumRotaterVariants.ccw]: generateMatrixRotations([1, 1, 0, 0, 1, 1, 1, 1, 0]), + [enumRotaterVariants.rotate180]: generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 1]), +}; + +export class MetaRotaterBuilding extends MetaBuilding { + constructor() { + super("rotater"); + } + + getSilhouetteColor() { + return "#7dc6cd"; + } + + /** + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + * @returns {Array|null} + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + const matrix = overlayMatrices[variant]; + if (matrix) { + return matrix[rotation]; + } + return null; + } + + /** + * @param {GameRoot} root + * @param {string} variant + * @returns {Array<[string, string]>} + */ + getAdditionalStatistics(root, variant) { + 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.rotate180: { + const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.rotater180); + return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; + } + } + } + + /** + * + * @param {GameRoot} root + */ + getAvailableVariants(root) { + let variants = [defaultBuildingVariant]; + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater_ccw)) { + variants.push(enumRotaterVariants.ccw); + } + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater_180)) { + variants.push(enumRotaterVariants.rotate180); + } + return variants; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_rotater); + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new ItemProcessorComponent({ + inputsPerCharge: 1, + processorType: enumItemProcessorTypes.rotater, + }) + ); + + entity.addComponent( + new ItemEjectorComponent({ + slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }], + }) + ); + 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.ItemProcessor.type = enumItemProcessorTypes.rotater; + break; + } + case enumRotaterVariants.ccw: { + entity.components.ItemProcessor.type = enumItemProcessorTypes.rotaterCCW; + break; + } + case enumRotaterVariants.rotate180: { + entity.components.ItemProcessor.type = enumItemProcessorTypes.rotater180; + break; + } + default: + assertAlways(false, "Unknown rotater variant: " + variant); + } + } +} diff --git a/src/js/game/buildings/splitter.js b/src/js/game/buildings/splitter.js deleted file mode 100644 index 12f0e6e7..00000000 --- a/src/js/game/buildings/splitter.js +++ /dev/null @@ -1,156 +0,0 @@ -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); - } - } -} 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/energy_generator.js b/src/js/game/buildings/storage.js similarity index 59% rename from src/js/game/buildings/energy_generator.js rename to src/js/game/buildings/storage.js index 1d7ac18b..5574e137 100644 --- a/src/js/game/buildings/energy_generator.js +++ b/src/js/game/buildings/storage.js @@ -1,109 +1,101 @@ -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, - }, - ], - }) - ); - } -} +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 { StorageComponent } from "../components/storage"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { enumHubGoalRewards } from "../tutorial_goals"; + +const storageSize = 5000; + +export class MetaStorageBuilding extends MetaBuilding { + constructor() { + super("storage"); + } + + getSilhouetteColor() { + return "#bbdf6d"; + } + + /** + * @returns {Array<[string, string]>} + */ + getAdditionalStatistics(root, variant) { + return [[T.ingame.buildingPlacement.infoTexts.storage, formatBigNumber(storageSize)]]; + } + + getDimensions() { + return new Vector(2, 2); + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_storage); + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + // Required, since the item processor needs this. + entity.addComponent( + new ItemEjectorComponent({ + slots: [ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + }, + { + pos: new Vector(1, 0), + direction: enumDirection.top, + }, + ], + }) + ); + + entity.addComponent( + new ItemAcceptorComponent({ + slots: [ + { + pos: new Vector(0, 1), + directions: [enumDirection.bottom], + }, + { + pos: new Vector(1, 1), + directions: [enumDirection.bottom], + }, + ], + }) + ); + + entity.addComponent( + new StorageComponent({ + maximumStorage: storageSize, + }) + ); + + 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, + }, + ], + }) + ); + } +} diff --git a/src/js/game/buildings/transistor.js b/src/js/game/buildings/transistor.js new file mode 100644 index 00000000..ebcfeac3 --- /dev/null +++ b/src/js/game/buildings/transistor.js @@ -0,0 +1,101 @@ +import { generateMatrixRotations } from "../../core/utils"; +import { enumDirection, Vector } from "../../core/vector"; +import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate"; +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 enumTransistorVariants = { + mirrored: "mirrored", +}; + +const overlayMatrices = { + [defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 0, 0, 1, 0]), + [enumTransistorVariants.mirrored]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 0, 1, 0]), +}; + +export class MetaTransistorBuilding extends MetaBuilding { + constructor() { + super("transistor"); + } + + getSilhouetteColor() { + return "#bc3a61"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_logic_gates); + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getDimensions() { + return new Vector(1, 1); + } + + getAvailableVariants() { + return [defaultBuildingVariant, enumTransistorVariants.mirrored]; + } + + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) { + return overlayMatrices[variant][rotation]; + } + + getRenderPins() { + // We already have it included + return false; + } + + /** + * + * @param {Entity} entity + * @param {number} rotationVariant + */ + updateVariants(entity, rotationVariant, variant) { + entity.components.WiredPins.slots[1].direction = + variant === enumTransistorVariants.mirrored ? enumDirection.right : enumDirection.left; + } + + /** + * 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, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.left, + type: enumPinSlotType.logicalAcceptor, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + ], + }) + ); + + entity.addComponent( + new LogicGateComponent({ + type: enumLogicGateType.transistor, + }) + ); + } +} diff --git a/src/js/game/buildings/trash.js b/src/js/game/buildings/trash.js index 8ae36b8d..43108b9e 100644 --- a/src/js/game/buildings/trash.js +++ b/src/js/game/buildings/trash.js @@ -1,64 +1,33 @@ +import { generateMatrixRotations } from "../../core/utils"; 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 { enumHubGoalRewards } from "../tutorial_goals"; +import { MetaBuilding } from "../meta_building"; import { GameRoot } from "../root"; -import { StorageComponent } from "../components/storage"; -import { T } from "../../translations"; -import { formatBigNumber } from "../../core/utils"; +import { enumHubGoalRewards } from "../tutorial_goals"; -/** @enum {string} */ -export const enumTrashVariants = { storage: "storage" }; - -const trashSize = 5000; +const overlayMatrix = generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 1]); export class MetaTrashBuilding extends MetaBuilding { constructor() { super("trash"); } - isRotateable(variant) { - return variant !== defaultBuildingVariant; + getIsRotateable() { + return false; } getSilhouetteColor() { - return "#cd7d86"; + return "#ed1d5d"; } - /** - * @param {GameRoot} root - * @param {string} variant - * @returns {Array<[string, string]>} - */ - getAdditionalStatistics(root, variant) { - if (variant === enumTrashVariants.storage) { - return [[T.ingame.buildingPlacement.infoTexts.storage, formatBigNumber(trashSize)]]; - } - return []; + getDimensions() { + return new Vector(1, 1); } - getDimensions(variant) { - switch (variant) { - case defaultBuildingVariant: - return new Vector(1, 1); - case enumTrashVariants.storage: - return new Vector(2, 2); - default: - assertAlways(false, "Unknown trash variant: " + variant); - } - } - - /** - * @param {GameRoot} root - */ - getAvailableVariants(root) { - if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_storage)) { - return [defaultBuildingVariant, enumTrashVariants.storage]; - } - return super.getAvailableVariants(root); + getSpecialOverlayRenderMatrix(rotation) { + return overlayMatrix[rotation]; } /** @@ -73,13 +42,6 @@ export class MetaTrashBuilding extends MetaBuilding { * @param {Entity} entity */ setupEntityComponents(entity) { - // Required, since the item processor needs this. - entity.addComponent( - new ItemEjectorComponent({ - slots: [], - }) - ); - entity.addComponent( new ItemAcceptorComponent({ slots: [ @@ -95,78 +57,11 @@ export class MetaTrashBuilding extends MetaBuilding { ], }) ); - } - - /** - * - * @param {Entity} entity - * @param {number} rotationVariant - * @param {string} variant - */ - updateVariants(entity, rotationVariant, variant) { - switch (variant) { - case defaultBuildingVariant: { - if (!entity.components.ItemProcessor) { - entity.addComponent( - new ItemProcessorComponent({ - inputsPerCharge: 1, - processorType: enumItemProcessorTypes.trash, - }) - ); - } - if (entity.components.Storage) { - entity.removeComponent(StorageComponent); - } - - entity.components.ItemAcceptor.setSlots([ - { - pos: new Vector(0, 0), - directions: [ - enumDirection.top, - enumDirection.right, - enumDirection.bottom, - enumDirection.left, - ], - }, - ]); - entity.components.ItemEjector.setSlots([]); - entity.components.ItemProcessor.type = enumItemProcessorTypes.trash; - break; - } - case enumTrashVariants.storage: { - if (entity.components.ItemProcessor) { - entity.removeComponent(ItemProcessorComponent); - } - if (!entity.components.Storage) { - entity.addComponent(new StorageComponent({})); - } - - entity.components.Storage.maximumStorage = trashSize; - entity.components.ItemAcceptor.setSlots([ - { - pos: new Vector(0, 1), - directions: [enumDirection.bottom], - }, - { - pos: new Vector(1, 1), - directions: [enumDirection.bottom], - }, - ]); - - entity.components.ItemEjector.setSlots([ - { - pos: new Vector(0, 0), - direction: enumDirection.top, - }, - { - pos: new Vector(1, 0), - direction: enumDirection.top, - }, - ]); - break; - } - default: - assertAlways(false, "Unknown trash variant: " + variant); - } + entity.addComponent( + new ItemProcessorComponent({ + inputsPerCharge: 1, + processorType: enumItemProcessorTypes.trash, + }) + ); } } diff --git a/src/js/game/buildings/underground_belt.js b/src/js/game/buildings/underground_belt.js index 99004b99..2761443d 100644 --- a/src/js/game/buildings/underground_belt.js +++ b/src/js/game/buildings/underground_belt.js @@ -1,236 +1,267 @@ -import { Loader } from "../../core/loader"; -import { enumDirection, Vector, enumAngleToDirection, enumDirectionToVector } from "../../core/vector"; -import { ItemAcceptorComponent } from "../components/item_acceptor"; -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 { globalConfig } from "../../core/config"; -import { enumHubGoalRewards } from "../tutorial_goals"; -import { formatItemsPerSecond } from "../../core/utils"; -import { T } from "../../translations"; - -/** @enum {string} */ -export const arrayUndergroundRotationVariantToMode = [ - enumUndergroundBeltMode.sender, - enumUndergroundBeltMode.receiver, -]; - -/** @enum {string} */ -export const enumUndergroundBeltVariants = { tier2: "tier2" }; - -export const enumUndergroundBeltVariantToTier = { - [defaultBuildingVariant]: 0, - [enumUndergroundBeltVariants.tier2]: 1, -}; - -export class MetaUndergroundBeltBuilding extends MetaBuilding { - constructor() { - super("underground_belt"); - } - - getSilhouetteColor() { - return "#555"; - } - - getFlipOrientationAfterPlacement() { - return true; - } - - getStayInPlacementMode() { - return true; - } - - /** - * @param {GameRoot} root - * @param {string} variant - * @returns {Array<[string, string]>} - */ - getAdditionalStatistics(root, variant) { - const rangeTiles = - globalConfig.undergroundBeltMaxTilesByTier[enumUndergroundBeltVariantToTier[variant]]; - - const beltSpeed = root.hubGoals.getUndergroundBeltBaseSpeed(); - return [ - [ - T.ingame.buildingPlacement.infoTexts.range, - T.ingame.buildingPlacement.infoTexts.tiles.replace("", "" + rangeTiles), - ], - [T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)], - ]; - } - - /** - * @param {GameRoot} root - */ - getAvailableVariants(root) { - if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_underground_belt_tier_2)) { - return [defaultBuildingVariant, enumUndergroundBeltVariants.tier2]; - } - return super.getAvailableVariants(root); - } - - getPreviewSprite(rotationVariant, variant) { - let suffix = ""; - if (variant !== defaultBuildingVariant) { - suffix = "-" + variant; - } - - switch (arrayUndergroundRotationVariantToMode[rotationVariant]) { - case enumUndergroundBeltMode.sender: - return Loader.getSprite("sprites/buildings/underground_belt_entry" + suffix + ".png"); - case enumUndergroundBeltMode.receiver: - return Loader.getSprite("sprites/buildings/underground_belt_exit" + suffix + ".png"); - default: - assertAlways(false, "Invalid rotation variant"); - } - } - - getBlueprintSprite(rotationVariant, variant) { - let suffix = ""; - if (variant !== defaultBuildingVariant) { - suffix = "-" + variant; - } - - switch (arrayUndergroundRotationVariantToMode[rotationVariant]) { - case enumUndergroundBeltMode.sender: - return Loader.getSprite("sprites/blueprints/underground_belt_entry" + suffix + ".png"); - case enumUndergroundBeltMode.receiver: - return Loader.getSprite("sprites/blueprints/underground_belt_exit" + suffix + ".png"); - default: - assertAlways(false, "Invalid rotation variant"); - } - } - - /** - * @param {GameRoot} root - */ - getIsUnlocked(root) { - return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_tunnel); - } - - /** - * Creates the entity at the given location - * @param {Entity} entity - */ - setupEntityComponents(entity) { - // Required, since the item processor needs this. - entity.addComponent( - new ItemEjectorComponent({ - slots: [], - }) - ); - - entity.addComponent(new UndergroundBeltComponent({})); - entity.addComponent( - new ItemAcceptorComponent({ - slots: [], - }) - ); - } - - /** - * 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 searchDirection = enumAngleToDirection[rotation]; - const searchVector = enumDirectionToVector[searchDirection]; - const tier = enumUndergroundBeltVariantToTier[variant]; - - const targetRotation = (rotation + 180) % 360; - const targetSenderRotation = rotation; - - for ( - let searchOffset = 1; - searchOffset <= globalConfig.undergroundBeltMaxTilesByTier[tier]; - ++searchOffset - ) { - tile = tile.addScalars(searchVector.x, searchVector.y); - - /* WIRES: FIXME */ - const contents = root.map.getTileContent(tile, enumLayer.regular); - if (contents) { - const undergroundComp = contents.components.UndergroundBelt; - if (undergroundComp && undergroundComp.tier === tier) { - const staticComp = contents.components.StaticMapEntity; - if (staticComp.rotation === targetRotation) { - if (undergroundComp.mode !== enumUndergroundBeltMode.sender) { - // If we encounter an underground receiver on our way which is also faced in our direction, we don't accept that - break; - } - return { - rotation: targetRotation, - rotationVariant: 1, - connectedEntities: [contents], - }; - } else if (staticComp.rotation === targetSenderRotation) { - // Draw connections to receivers - if (undergroundComp.mode === enumUndergroundBeltMode.receiver) { - return { - rotation: rotation, - rotationVariant: 0, - connectedEntities: [contents], - }; - } else { - break; - } - } - } - } - } - - return { - rotation, - rotationVariant: 0, - }; - } - - /** - * - * @param {Entity} entity - * @param {number} rotationVariant - * @param {string} variant - */ - 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: { - entity.components.UndergroundBelt.mode = enumUndergroundBeltMode.sender; - entity.components.ItemEjector.setSlots([]); - entity.components.ItemAcceptor.setSlots([ - { - pos: new Vector(0, 0), - directions: [enumDirection.bottom], - }, - ]); - return; - } - case enumUndergroundBeltMode.receiver: { - entity.components.UndergroundBelt.mode = enumUndergroundBeltMode.receiver; - entity.components.ItemAcceptor.setSlots([]); - entity.components.ItemEjector.setSlots([ - { - pos: new Vector(0, 0), - direction: enumDirection.top, - }, - ]); - return; - } - default: - assertAlways(false, "Invalid rotation variant"); - } - } -} +import { Loader } from "../../core/loader"; +import { enumDirection, Vector, enumAngleToDirection, enumDirectionToVector } from "../../core/vector"; +import { ItemAcceptorComponent } from "../components/item_acceptor"; +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 } from "../root"; +import { globalConfig } from "../../core/config"; +import { enumHubGoalRewards } from "../tutorial_goals"; +import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils"; +import { T } from "../../translations"; + +/** @enum {string} */ +export const arrayUndergroundRotationVariantToMode = [ + enumUndergroundBeltMode.sender, + enumUndergroundBeltMode.receiver, +]; + +/** @enum {string} */ +export const enumUndergroundBeltVariants = { tier2: "tier2" }; + +export const enumUndergroundBeltVariantToTier = { + [defaultBuildingVariant]: 0, + [enumUndergroundBeltVariants.tier2]: 1, +}; + +const colorsByRotationVariant = ["#6d9dff", "#71ff9c"]; + +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(variant, rotationVariant) { + return colorsByRotationVariant[rotationVariant]; + } + + getFlipOrientationAfterPlacement() { + return true; + } + + getStayInPlacementMode() { + 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 + * @returns {Array<[string, string]>} + */ + getAdditionalStatistics(root, variant) { + const rangeTiles = + globalConfig.undergroundBeltMaxTilesByTier[enumUndergroundBeltVariantToTier[variant]]; + + const beltSpeed = root.hubGoals.getUndergroundBeltBaseSpeed(); + return [ + [ + T.ingame.buildingPlacement.infoTexts.range, + T.ingame.buildingPlacement.infoTexts.tiles.replace("", "" + rangeTiles), + ], + [T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)], + ]; + } + + /** + * @param {GameRoot} root + */ + getAvailableVariants(root) { + if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_underground_belt_tier_2)) { + return [defaultBuildingVariant, enumUndergroundBeltVariants.tier2]; + } + return super.getAvailableVariants(root); + } + + /** + * @param {number} rotationVariant + * @param {string} variant + */ + getPreviewSprite(rotationVariant, variant) { + let suffix = ""; + if (variant !== defaultBuildingVariant) { + suffix = "-" + variant; + } + + switch (arrayUndergroundRotationVariantToMode[rotationVariant]) { + case enumUndergroundBeltMode.sender: + return Loader.getSprite("sprites/buildings/underground_belt_entry" + suffix + ".png"); + case enumUndergroundBeltMode.receiver: + return Loader.getSprite("sprites/buildings/underground_belt_exit" + suffix + ".png"); + default: + assertAlways(false, "Invalid rotation variant"); + } + } + + /** + * @param {number} rotationVariant + * @param {string} variant + */ + getBlueprintSprite(rotationVariant, variant) { + let suffix = ""; + if (variant !== defaultBuildingVariant) { + suffix = "-" + variant; + } + + switch (arrayUndergroundRotationVariantToMode[rotationVariant]) { + case enumUndergroundBeltMode.sender: + return Loader.getSprite("sprites/blueprints/underground_belt_entry" + suffix + ".png"); + case enumUndergroundBeltMode.receiver: + return Loader.getSprite("sprites/blueprints/underground_belt_exit" + suffix + ".png"); + default: + assertAlways(false, "Invalid rotation variant"); + } + } + + /** + * @param {number} rotationVariant + * @param {string} variant + */ + getSprite(rotationVariant, variant) { + return this.getPreviewSprite(rotationVariant, variant); + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_tunnel); + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + // Required, since the item processor needs this. + entity.addComponent( + new ItemEjectorComponent({ + slots: [], + }) + ); + + entity.addComponent(new UndergroundBeltComponent({})); + entity.addComponent( + new ItemAcceptorComponent({ + slots: [], + }) + ); + } + + /** + * 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 {Layer} param0.layer + * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array }} + */ + computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { + const searchDirection = enumAngleToDirection[rotation]; + const searchVector = enumDirectionToVector[searchDirection]; + const tier = enumUndergroundBeltVariantToTier[variant]; + + const targetRotation = (rotation + 180) % 360; + const targetSenderRotation = rotation; + + for ( + let searchOffset = 1; + searchOffset <= globalConfig.undergroundBeltMaxTilesByTier[tier]; + ++searchOffset + ) { + tile = tile.addScalars(searchVector.x, searchVector.y); + + const contents = root.map.getTileContent(tile, "regular"); + if (contents) { + const undergroundComp = contents.components.UndergroundBelt; + if (undergroundComp && undergroundComp.tier === tier) { + const staticComp = contents.components.StaticMapEntity; + if (staticComp.rotation === targetRotation) { + if (undergroundComp.mode !== enumUndergroundBeltMode.sender) { + // If we encounter an underground receiver on our way which is also faced in our direction, we don't accept that + break; + } + return { + rotation: targetRotation, + rotationVariant: 1, + connectedEntities: [contents], + }; + } else if (staticComp.rotation === targetSenderRotation) { + // Draw connections to receivers + if (undergroundComp.mode === enumUndergroundBeltMode.receiver) { + return { + rotation: rotation, + rotationVariant: 0, + connectedEntities: [contents], + }; + } else { + break; + } + } + } + } + } + + return { + rotation, + rotationVariant: 0, + }; + } + + /** + * + * @param {Entity} entity + * @param {number} rotationVariant + * @param {string} variant + */ + updateVariants(entity, rotationVariant, variant) { + entity.components.UndergroundBelt.tier = enumUndergroundBeltVariantToTier[variant]; + + switch (arrayUndergroundRotationVariantToMode[rotationVariant]) { + case enumUndergroundBeltMode.sender: { + entity.components.UndergroundBelt.mode = enumUndergroundBeltMode.sender; + entity.components.ItemEjector.setSlots([]); + entity.components.ItemAcceptor.setSlots([ + { + pos: new Vector(0, 0), + directions: [enumDirection.bottom], + }, + ]); + return; + } + case enumUndergroundBeltMode.receiver: { + entity.components.UndergroundBelt.mode = enumUndergroundBeltMode.receiver; + entity.components.ItemAcceptor.setSlots([]); + entity.components.ItemEjector.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + }, + ]); + return; + } + default: + assertAlways(false, "Invalid rotation variant"); + } + } +} diff --git a/src/js/game/buildings/virtual_processor.js b/src/js/game/buildings/virtual_processor.js new file mode 100644 index 00000000..b4f91762 --- /dev/null +++ b/src/js/game/buildings/virtual_processor.js @@ -0,0 +1,163 @@ +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"; +import { enumHubGoalRewards } from "../tutorial_goals"; +import { MetaCutterBuilding } from "./cutter"; +import { MetaPainterBuilding } from "./painter"; +import { MetaRotaterBuilding } from "./rotater"; +import { MetaStackerBuilding } from "./stacker"; + +/** @enum {string} */ +export const enumVirtualProcessorVariants = { + rotater: "rotater", + unstacker: "unstacker", + stacker: "stacker", + painter: "painter", +}; + +/** @enum {string} */ +export const enumVariantToGate = { + [defaultBuildingVariant]: enumLogicGateType.cutter, + [enumVirtualProcessorVariants.rotater]: enumLogicGateType.rotater, + [enumVirtualProcessorVariants.unstacker]: enumLogicGateType.unstacker, + [enumVirtualProcessorVariants.stacker]: enumLogicGateType.stacker, + [enumVirtualProcessorVariants.painter]: enumLogicGateType.painter, +}; + +const colors = { + [defaultBuildingVariant]: new MetaCutterBuilding().getSilhouetteColor(), + [enumVirtualProcessorVariants.rotater]: new MetaRotaterBuilding().getSilhouetteColor(), + [enumVirtualProcessorVariants.unstacker]: new MetaStackerBuilding().getSilhouetteColor(), + [enumVirtualProcessorVariants.stacker]: new MetaStackerBuilding().getSilhouetteColor(), + [enumVirtualProcessorVariants.painter]: new MetaPainterBuilding().getSilhouetteColor(), +}; + +export class MetaVirtualProcessorBuilding extends MetaBuilding { + constructor() { + super("virtual_processor"); + } + + getSilhouetteColor(variant) { + return colors[variant]; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_virtual_processing); + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getDimensions() { + return new Vector(1, 1); + } + + getAvailableVariants() { + return [ + defaultBuildingVariant, + enumVirtualProcessorVariants.rotater, + enumVirtualProcessorVariants.stacker, + enumVirtualProcessorVariants.painter, + enumVirtualProcessorVariants.unstacker, + ]; + } + + 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.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.stacker: + case enumLogicGateType.painter: { + pinComp.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + 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..61b75073 --- /dev/null +++ b/src/js/game/buildings/wire.js @@ -0,0 +1,270 @@ +import { Loader } from "../../core/loader"; +import { generateMatrixRotations } from "../../core/utils"; +import { enumDirection, Vector } from "../../core/vector"; +import { SOUNDS } from "../../platform/sound"; +import { enumWireType, enumWireVariant, WireComponent } from "../components/wire"; +import { Entity } from "../entity"; +import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { enumHubGoalRewards } from "../tutorial_goals"; + +export const arrayWireRotationVariantToType = [ + enumWireType.forward, + enumWireType.turn, + enumWireType.split, + enumWireType.cross, +]; + +export const wireOverlayMatrices = { + [enumWireType.forward]: 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]), +}; + +/** @enum {string} */ +export const wireVariants = { + second: "second", +}; + +const enumWireVariantToVariant = { + [defaultBuildingVariant]: enumWireVariant.first, + [wireVariants.second]: enumWireVariant.second, +}; + +export class MetaWireBuilding extends MetaBuilding { + constructor() { + super("wire"); + } + + getHasDirectionLockAvailable() { + return true; + } + + getSilhouetteColor() { + return "#61ef6f"; + } + + getAvailableVariants() { + return [defaultBuildingVariant, wireVariants.second]; + } + + 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) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers); + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent(new WireComponent({})); + } + + /** + * + * @param {Entity} entity + * @param {number} rotationVariant + * @param {string} variant + */ + updateVariants(entity, rotationVariant, variant) { + entity.components.Wire.type = arrayWireRotationVariantToType[rotationVariant]; + entity.components.Wire.variant = enumWireVariantToVariant[variant]; + } + + /** + * + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return wireOverlayMatrices[entity.components.Wire.type][rotation]; + } + + /** + * + * @param {number} rotationVariant + * @param {string} variant + * @returns {import("../../core/draw_utils").AtlasSprite} + */ + getPreviewSprite(rotationVariant, variant) { + const wireVariant = enumWireVariantToVariant[variant]; + switch (arrayWireRotationVariantToType[rotationVariant]) { + case enumWireType.forward: { + return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_forward.png"); + } + case enumWireType.turn: { + return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_turn.png"); + } + case enumWireType.split: { + return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_split.png"); + } + case enumWireType.cross: { + return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_cross.png"); + } + default: { + assertAlways(false, "Invalid wire rotation variant"); + } + } + } + + getBlueprintSprite(rotationVariant, variant) { + return this.getPreviewSprite(rotationVariant, 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 wireVariant = enumWireVariantToVariant[variant]; + const connections = { + top: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.top }), + right: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.right }), + bottom: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.bottom }), + left: root.logic.computeWireEdgeStatus({ tile, wireVariant, 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.forward; + + // 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..2626dd12 --- /dev/null +++ b/src/js/game/buildings/wire_tunnel.js @@ -0,0 +1,58 @@ +import { generateMatrixRotations } from "../../core/utils"; +import { Vector } from "../../core/vector"; +import { WireTunnelComponent } from "../components/wire_tunnel"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { enumHubGoalRewards } from "../tutorial_goals"; + +const wireTunnelOverlayMatrix = generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]); + +export class MetaWireTunnelBuilding extends MetaBuilding { + constructor() { + super("wire_tunnel"); + } + + getSilhouetteColor() { + return "#777a86"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers); + } + + /** + * + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return wireTunnelOverlayMatrix[rotation]; + } + + getIsRotateable() { + return false; + } + + getDimensions() { + return new Vector(1, 1); + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent(new WireTunnelComponent()); + } +} diff --git a/src/js/game/camera.js b/src/js/game/camera.js index 1b302c4f..a823402e 100644 --- a/src/js/game/camera.js +++ b/src/js/game/camera.js @@ -123,7 +123,7 @@ export class Camera extends BasicSerializableObject { this.clampZoomLevel(); } - // Simple geters & setters + // Simple getters & setters addScreenShake(amount) { const currentShakeAmount = this.currentShake.length(); @@ -353,7 +353,7 @@ export class Camera extends BasicSerializableObject { .add(() => (this.desiredZoom = this.zoomLevel * 1.2)); mapper .getBinding(KEYMAPPINGS.navigation.mapZoomOut) - .add(() => (this.desiredZoom = this.zoomLevel * 0.8)); + .add(() => (this.desiredZoom = this.zoomLevel / 1.2)); mapper.getBinding(KEYMAPPINGS.navigation.centerMap).add(() => this.centerOnMap()); } @@ -530,16 +530,20 @@ export class Camera extends BasicSerializableObject { } const prevZoom = this.zoomLevel; - const delta = Math.sign(event.deltaY) * -0.15 * this.root.app.settings.getScrollWheelSensitivity(); - assert(Number.isFinite(delta), "Got invalid delta in mouse wheel event: " + event.deltaY); + const scale = 1 + 0.15 * this.root.app.settings.getScrollWheelSensitivity(); + assert(Number.isFinite(scale), "Got invalid scale in mouse wheel event: " + event.deltaY); assert(Number.isFinite(this.zoomLevel), "Got invalid zoom level *before* wheel: " + this.zoomLevel); - this.zoomLevel *= 1 + delta; + this.zoomLevel *= event.deltaY < 0 ? scale : 1 / scale; assert(Number.isFinite(this.zoomLevel), "Got invalid zoom level *after* wheel: " + this.zoomLevel); this.clampZoomLevel(); this.desiredZoom = null; - const mousePosition = this.root.app.mousePosition; + let mousePosition = this.root.app.mousePosition; + if (!this.root.app.settings.getAllSettings().zoomToCursor) { + mousePosition = new Vector(this.root.gameWidth / 2, this.root.gameHeight / 2); + } + if (mousePosition) { const worldPos = this.root.camera.screenToWorld(mousePosition); const worldDelta = worldPos.sub(this.center); @@ -804,6 +808,7 @@ export class Camera extends BasicSerializableObject { this.cameraUpdateTimeBucket -= physicsStepSizeMs; this.internalUpdatePanning(now, physicsStepSizeMs); + this.internalUpdateMousePanning(now, physicsStepSizeMs); this.internalUpdateZooming(now, physicsStepSizeMs); this.internalUpdateCentering(now, physicsStepSizeMs); this.internalUpdateShake(now, physicsStepSizeMs); @@ -890,6 +895,69 @@ export class Camera extends BasicSerializableObject { } } + /** + * Internal screen panning handler + * @param {number} now + * @param {number} dt + */ + internalUpdateMousePanning(now, dt) { + if (!this.root.app.focused) { + return; + } + + if (!this.root.app.settings.getAllSettings().enableMousePan) { + // Not enabled + return; + } + + const mousePos = this.root.app.mousePosition; + if (!mousePos) { + return; + } + + if (this.root.hud.shouldPauseGame() || this.root.hud.hasBlockingOverlayOpen()) { + return; + } + + if (this.desiredCenter || this.desiredZoom || this.currentlyMoving || this.currentlyPinching) { + // Performing another method of movement right now + return; + } + + if ( + mousePos.x < 0 || + mousePos.y < 0 || + mousePos.x > this.root.gameWidth || + mousePos.y > this.root.gameHeight + ) { + // Out of screen + return; + } + + const panAreaPixels = 2; + + const panVelocity = new Vector(); + if (mousePos.x < panAreaPixels) { + panVelocity.x -= 1; + } + if (mousePos.x > this.root.gameWidth - panAreaPixels) { + panVelocity.x += 1; + } + + if (mousePos.y < panAreaPixels) { + panVelocity.y -= 1; + } + if (mousePos.y > this.root.gameHeight - panAreaPixels) { + panVelocity.y += 1; + } + + this.center = this.center.add( + panVelocity.multiplyScalar( + ((0.5 * dt) / this.zoomLevel) * this.root.app.settings.getMovementSpeed() + ) + ); + } + /** * Updates the non user interaction zooming * @param {number} now Time now in seconds @@ -910,6 +978,7 @@ export class Camera extends BasicSerializableObject { this.zoomLevel = this.zoomLevel * fade + this.desiredZoom * (1 - fade); assert(Number.isFinite(this.zoomLevel), "Zoom level is NaN after fade: " + this.zoomLevel); } else { + this.zoomLevel = this.desiredZoom; this.desiredZoom = null; } } 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..46b1b545 100644 --- a/src/js/game/component.js +++ b/src/js/game/component.js @@ -18,12 +18,10 @@ export class Component extends BasicSerializableObject { } /** - * Should duplicate the component but without its contents - * @returns {object} + * Copy the current state to another component + * @param {Component} otherComponent */ - duplicateWithoutContents() { - abstract; - } + copyAdditionalStateTo(otherComponent) {} /* dev:start */ @@ -44,3 +42,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..f094e60d 100644 --- a/src/js/game/component_registry.js +++ b/src/js/game/component_registry.js @@ -5,14 +5,20 @@ 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"; +import { FilterComponent } from "./components/filter"; +import { ItemProducerComponent } from "./components/item_producer"; export function initComponentRegistry() { gComponentRegistry.register(StaticMapEntityComponent); @@ -21,14 +27,20 @@ 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); + gComponentRegistry.register(FilterComponent); + gComponentRegistry.register(ItemProducerComponent); // IMPORTANT ^^^^^ UPDATE ENTITY COMPONENT STORAGE AFTERWARDS diff --git a/src/js/game/components/belt.js b/src/js/game/components/belt.js index e9a0cd80..138c4775 100644 --- a/src/js/game/components/belt.js +++ b/src/js/game/components/belt.js @@ -2,27 +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 }); - } - /** * * @param {object} param0 @@ -33,9 +50,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 +59,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..d451bab5 --- /dev/null +++ b/src/js/game/components/belt_reader.js @@ -0,0 +1,44 @@ +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"; + } + + 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..63b265d0 --- /dev/null +++ b/src/js/game/components/belt_underlays.js @@ -0,0 +1,41 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { Component } from "../component"; + +/** + * Store which type an underlay is, this is cached so we can easily + * render it. + * + * Full: Render underlay at top and bottom of tile + * Bottom Only: Only render underlay at the bottom half + * Top Only: + * @enum {string} + */ +export const enumClippedBeltUnderlayType = { + full: "full", + bottomOnly: "bottomOnly", + topOnly: "topOnly", + none: "none", +}; + +/** + * @typedef {{ + * pos: Vector, + * direction: enumDirection, + * cachedType?: enumClippedBeltUnderlayType + * }} BeltUnderlayTile + */ + +export class BeltUnderlaysComponent extends Component { + static getId() { + return "BeltUnderlays"; + } + + /** + * @param {object} param0 + * @param {Array=} 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..286108be --- /dev/null +++ b/src/js/game/components/constant_signal.js @@ -0,0 +1,35 @@ +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), + }; + } + + /** + * Copy the current state to another component + * @param {ConstantSignalComponent} otherComponent + */ + copyAdditionalStateTo(otherComponent) { + otherComponent.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..5a5b1b3b --- /dev/null +++ b/src/js/game/components/display.js @@ -0,0 +1,7 @@ +import { Component } from "../component"; + +export class DisplayComponent extends Component { + static getId() { + return "Display"; + } +} 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/filter.js b/src/js/game/components/filter.js new file mode 100644 index 00000000..cffee969 --- /dev/null +++ b/src/js/game/components/filter.js @@ -0,0 +1,55 @@ +import { types } from "../../savegame/serialization"; +import { BaseItem } from "../base_item"; +import { Component } from "../component"; +import { typeItemSingleton } from "../item_resolver"; + +/** + * @typedef {{ + * item: BaseItem, + * progress: number + * }} PendingFilterItem + */ + +export class FilterComponent extends Component { + static getId() { + return "Filter"; + } + + duplicateWithoutContents() { + return new FilterComponent(); + } + + static getSchema() { + return { + pendingItemsToLeaveThrough: types.array( + types.structured({ + item: typeItemSingleton, + progress: types.ufloat, + }) + ), + + pendingItemsToReject: types.array( + types.structured({ + item: typeItemSingleton, + progress: types.ufloat, + }) + ), + }; + } + + constructor() { + super(); + + /** + * Items in queue to leave through + * @type {Array} + */ + this.pendingItemsToLeaveThrough = []; + + /** + * Items in queue to reject + * @type {Array} + */ + this.pendingItemsToReject = []; + } +} 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..7dbd9677 100644 --- a/src/js/game/components/item_acceptor.js +++ b/src/js/game/components/item_acceptor.js @@ -1,219 +1,134 @@ -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"; + } + + /** + * + * @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..47253b4b 100644 --- a/src/js/game/components/item_ejector.js +++ b/src/js/game/components/item_ejector.js @@ -1,181 +1,143 @@ -import { Vector, enumDirection, enumDirectionToVector } from "../../core/vector"; -import { BaseItem } from "../base_item"; -import { Component } from "../component"; -import { types } from "../../savegame/serialization"; -import { gItemRegistry } from "../../core/global_registries"; -import { Entity } from "../entity"; -import { enumLayer } from "../root"; - -/** - * @typedef {{ - * pos: Vector, - * direction: enumDirection, - * item: BaseItem, - * layer: enumLayer, - * progress: number?, - * cachedDestSlot?: import("./item_acceptor").ItemAcceptorLocatedSlot, - * cachedTargetEntity?: Entity - * }} ItemEjectorSlot - */ - -export class ItemEjectorComponent extends Component { - static getId() { - return "ItemEjector"; - } - - static getSchema() { - // The cachedDestSlot, cachedTargetEntity, and cachedConnectedSlots 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)), - progress: types.float, - - // 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(), - 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 - */ - constructor({ slots = [], instantEject = false }) { - super(); - - // How long items take to eject - this.instantEject = instantEject; - - this.setSlots(slots); - - /** @type {ItemEjectorSlot[]} */ - this.cachedConnectedSlots = null; - - /** - * Whether this ejector slot is enabled - */ - this.enabled = true; - } - - /** - * @param {Array<{pos: Vector, direction: enumDirection, layer?: enumLayer}>} slots The slots to eject on - */ - setSlots(slots) { - /** @type {Array} */ - this.slots = []; - for (let i = 0; i < slots.length; ++i) { - const slot = slots[i]; - this.slots.push({ - pos: slot.pos, - direction: slot.direction, - item: null, - progress: 0, - layer: slot.layer || enumLayer.regular, - cachedDestSlot: null, - cachedTargetEntity: null, - }); - } - } - - /** - * Returns where this slot ejects to - * @param {number} index - * @returns {Vector} - */ - getSlotTargetLocalTile(index) { - const slot = this.slots[index]; - const directionVector = enumDirectionToVector[slot.direction]; - return slot.pos.add(directionVector); - } - - /** - * Returns whether any slot ejects to the given local tile - * @param {Vector} tile - * @param {enumLayer} layer - */ - anySlotEjectsToLocalTile(tile, layer) { - for (let i = 0; i < this.slots.length; ++i) { - if (this.getSlotTargetLocalTile(i).equals(tile) && this.slots[i].layer === layer) { - return true; - } - } - return false; - } - - /** - * Returns if we can eject on a given slot - * @param {number} slotIndex - * @returns {boolean} - */ - canEjectOnSlot(slotIndex) { - assert(slotIndex >= 0 && slotIndex < this.slots.length, "Invalid ejector slot: " + slotIndex); - return !this.slots[slotIndex].item; - } - - /** - * Returns the first free slot on this ejector or null if there is none - * @param {enumLayer} layer - * @returns {number?} - */ - getFirstFreeSlot(layer) { - for (let i = 0; i < this.slots.length; ++i) { - if (this.canEjectOnSlot(i) && this.slots[i].layer === layer) { - return i; - } - } - return null; - } - - /** - * Tries to eject a given item - * @param {number} slotIndex - * @param {BaseItem} item - * @returns {boolean} - */ - tryEject(slotIndex, item) { - if (!this.canEjectOnSlot(slotIndex)) { - return false; - } - this.slots[slotIndex].item = item; - this.slots[slotIndex].progress = this.instantEject ? 1 : 0; - return true; - } - - /** - * Clears the given slot and returns the item it had - * @param {number} slotIndex - * @returns {BaseItem|null} - */ - takeSlotItem(slotIndex) { - const slot = this.slots[slotIndex]; - const item = slot.item; - slot.item = null; - slot.progress = 0.0; - return item; - } -} +import { enumDirection, enumDirectionToVector, Vector } from "../../core/vector"; +import { types } from "../../savegame/serialization"; +import { BaseItem } from "../base_item"; +import { BeltPath } from "../belt_path"; +import { Component } from "../component"; +import { Entity } from "../entity"; +import { typeItemSingleton } from "../item_resolver"; + +/** + * @typedef {{ + * pos: Vector, + * direction: enumDirection, + * item: BaseItem, + * progress: number?, + * cachedDestSlot?: import("./item_acceptor").ItemAcceptorLocatedSlot, + * cachedBeltPath?: BeltPath, + * cachedTargetEntity?: Entity + * }} ItemEjectorSlot + */ + +export class ItemEjectorComponent extends Component { + static getId() { + return "ItemEjector"; + } + + static getSchema() { + // The cachedDestSlot, cachedTargetEntity fields are not serialized. + return { + slots: types.fixedSizeArray( + types.structured({ + item: types.nullable(typeItemSingleton), + progress: types.float, + }) + ), + }; + } + + /** + * + * @param {object} param0 + * @param {Array<{pos: Vector, direction: enumDirection }>=} param0.slots The slots to eject on + * @param {boolean=} param0.renderFloatingItems Whether to render items even if they are not connected + */ + constructor({ slots = [], renderFloatingItems = true }) { + super(); + + this.setSlots(slots); + this.renderFloatingItems = renderFloatingItems; + } + + /** + * @param {Array<{pos: Vector, direction: enumDirection }>} slots The slots to eject on + */ + setSlots(slots) { + /** @type {Array} */ + this.slots = []; + for (let i = 0; i < slots.length; ++i) { + const slot = slots[i]; + this.slots.push({ + pos: slot.pos, + direction: slot.direction, + item: null, + progress: 0, + cachedDestSlot: null, + cachedTargetEntity: null, + }); + } + } + + /** + * Returns where this slot ejects to + * @param {ItemEjectorSlot} slot + * @returns {Vector} + */ + getSlotTargetLocalTile(slot) { + const directionVector = enumDirectionToVector[slot.direction]; + return slot.pos.add(directionVector); + } + + /** + * Returns whether any slot ejects to the given local tile + * @param {Vector} tile + */ + anySlotEjectsToLocalTile(tile) { + for (let i = 0; i < this.slots.length; ++i) { + if (this.getSlotTargetLocalTile(this.slots[i]).equals(tile)) { + return true; + } + } + return false; + } + + /** + * Returns if we can eject on a given slot + * @param {number} slotIndex + * @returns {boolean} + */ + canEjectOnSlot(slotIndex) { + assert(slotIndex >= 0 && slotIndex < this.slots.length, "Invalid ejector slot: " + slotIndex); + return !this.slots[slotIndex].item; + } + + /** + * Returns the first free slot on this ejector or null if there is none + * @returns {number?} + */ + getFirstFreeSlot() { + for (let i = 0; i < this.slots.length; ++i) { + if (this.canEjectOnSlot(i)) { + return i; + } + } + return null; + } + + /** + * Tries to eject a given item + * @param {number} slotIndex + * @param {BaseItem} item + * @returns {boolean} + */ + tryEject(slotIndex, item) { + if (!this.canEjectOnSlot(slotIndex)) { + return false; + } + this.slots[slotIndex].item = item; + this.slots[slotIndex].progress = 0; + return true; + } + + /** + * Clears the given slot and returns the item it had + * @param {number} slotIndex + * @returns {BaseItem|null} + */ + takeSlotItem(slotIndex) { + const slot = this.slots[slotIndex]; + const item = slot.item; + slot.item = null; + slot.progress = 0.0; + return item; + } +} diff --git a/src/js/game/components/item_processor.js b/src/js/game/components/item_processor.js index 72422faf..fd466662 100644 --- a/src/js/game/components/item_processor.js +++ b/src/js/game/components/item_processor.js @@ -1,26 +1,42 @@ -import { gItemRegistry } from "../../core/global_registries"; import { types } from "../../savegame/serialization"; import { BaseItem } from "../base_item"; import { Component } from "../component"; /** @enum {string} */ export const enumItemProcessorTypes = { - splitter: "splitter", - splitterWires: "splitterWires", + balancer: "balancer", cutter: "cutter", cutterQuad: "cutterQuad", rotater: "rotater", rotaterCCW: "rotaterCCW", + rotater180: "rotater180", 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", +}; + +/** @typedef {{ + * item: BaseItem, + * requiredSlot?: number, + * preferredSlot?: number + * }} EjectorItemToEject */ + +/** @typedef {{ + * remainingTime: number, + * items: Array, + * }} EjectorCharge */ + export class ItemProcessorComponent extends Component { static getId() { return "ItemProcessor"; @@ -29,51 +45,35 @@ 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, - inputsPerCharge: this.inputsPerCharge, - }); - } - /** * * @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.balancer, + processingRequirement = null, + inputsPerCharge = 1, + }) { super(); // Which slot to emit next, this is only a preference and if it can't emit - // it will take the other one. Some machines ignore this (e.g. the splitter) to make + // it will take the other one. Some machines ignore this (e.g. the balancer) to make // sure the outputs always match this.nextOutputSlot = 0; // 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 +87,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/item_producer.js b/src/js/game/components/item_producer.js new file mode 100644 index 00000000..ef3571e2 --- /dev/null +++ b/src/js/game/components/item_producer.js @@ -0,0 +1,7 @@ +import { Component } from "../component"; + +export class ItemProducerComponent extends Component { + static getId() { + return "ItemProducer"; + } +} diff --git a/src/js/game/components/lever.js b/src/js/game/components/lever.js new file mode 100644 index 00000000..106cbbdd --- /dev/null +++ b/src/js/game/components/lever.js @@ -0,0 +1,31 @@ +import { Component } from "../component"; +import { types } from "../../savegame/serialization"; + +export class LeverComponent extends Component { + static getId() { + return "Lever"; + } + + static getSchema() { + return { + toggled: types.bool, + }; + } + + /** + * Copy the current state to another component + * @param {LeverComponent} otherComponent + */ + copyAdditionalStateTo(otherComponent) { + otherComponent.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..62cd3365 --- /dev/null +++ b/src/js/game/components/logic_gate.js @@ -0,0 +1,34 @@ +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", + compare: "compare", + stacker: "stacker", + painter: "painter", +}; + +export class LogicGateComponent extends Component { + static getId() { + return "LogicGate"; + } + + /** + * + * @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..ab87760f 100644 --- a/src/js/game/components/miner.js +++ b/src/js/game/components/miner.js @@ -1,60 +1,60 @@ -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), + }; + } + + 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..7e2f5314 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,72 @@ 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, }; } - duplicateWithoutContents() { + /** + * 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; + } + + /** + * Returns the buildings variant + * @returns {string} + */ + getVariant() { + return getBuildingDataFromCode(this.code).variant; + } + + /** + * Copy the current state to another component + * @param {Component} otherComponent + */ + copyAdditionalStateTo(otherComponent) { 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 +91,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 +107,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 +117,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 +174,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 +198,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 +246,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 +265,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 +276,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..be243a44 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,17 +12,11 @@ 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), }; } - duplicateWithoutContents() { - return new StorageComponent({ maximumStorage: this.maximumStorage }); - } - /** * @param {object} param0 * @param {number=} param0.maximumStorage How much this storage can hold @@ -67,11 +61,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 +74,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..a3e883ec 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,19 +25,10 @@ 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)), }; } - duplicateWithoutContents() { - return new UndergroundBeltComponent({ - mode: this.mode, - tier: this.tier, - }); - } - /** * * @param {object} param0 @@ -58,7 +48,7 @@ export class UndergroundBeltComponent extends Component { * Used on both receiver and sender. * Reciever: Used to store the next item to transfer, and to block input while doing this * Sender: Used to store which items are currently "travelling" - * @type {Array<[BaseItem, number]>} Format is [Item, remaining seconds until transfer/ejection] + * @type {Array<[BaseItem, number]>} Format is [Item, ingame time to eject the item] */ this.pendingItems = []; @@ -95,16 +85,16 @@ export class UndergroundBeltComponent extends Component { * @param {BaseItem} item * @param {number} travelDistance How many tiles this item has to travel * @param {number} beltSpeed How fast this item travels + * @param {number} now Current ingame time */ - tryAcceptTunneledItem(item, travelDistance, beltSpeed) { + tryAcceptTunneledItem(item, travelDistance, beltSpeed, now) { if (this.mode !== enumUndergroundBeltMode.receiver) { // Only receivers can accept tunneled items return false; } // 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,14 +104,9 @@ 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]; - - this.pendingItems.push([item, travelDuration]); - - // Sort so we can only look at the first ones - this.pendingItems.sort((a, b) => a[1] - b[1]); + const travelDuration = (travelDistance + 1.5) / beltSpeed / globalConfig.itemSpacingOnBelts; + this.pendingItems.push([item, now + travelDuration]); return true; } } 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..d0e354e2 --- /dev/null +++ b/src/js/game/components/wire.js @@ -0,0 +1,42 @@ +import { Component } from "../component"; + +/** @enum {string} */ +export const enumWireType = { + forward: "forward", + turn: "turn", + split: "split", + cross: "cross", +}; + +/** @enum {string} */ +export const enumWireVariant = { + first: "first", + second: "second", +}; + +export class WireComponent extends Component { + static getId() { + return "Wire"; + } + + /** + * @param {object} param0 + * @param {enumWireType=} param0.type + * @param {enumWireVariant=} param0.variant + */ + constructor({ type = enumWireType.forward, variant = enumWireVariant.first }) { + super(); + this.type = type; + + /** + * The variant of the wire, different variants do not connect + * @type {enumWireVariant} + */ + this.variant = variant; + + /** + * @type {import("../systems/wire").WireNetwork} + */ + this.linkedNetwork = null; + } +} diff --git a/src/js/game/components/wire_tunnel.js b/src/js/game/components/wire_tunnel.js new file mode 100644 index 00000000..1c170484 --- /dev/null +++ b/src/js/game/components/wire_tunnel.js @@ -0,0 +1,17 @@ +import { Component } from "../component"; + +export class WireTunnelComponent extends Component { + static getId() { + return "WireTunnel"; + } + + constructor() { + super(); + + /** + * 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..81a6ec62 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 { @@ -29,10 +31,9 @@ export class WiredPinsComponent extends Component { static getSchema() { return { - slots: types.array( + slots: types.fixedSizeArray( types.structured({ - pos: types.vector, - type: types.enum(enumPinSlotType), + value: types.nullable(typeItemSingleton), }) ), }; @@ -48,20 +49,6 @@ export class WiredPinsComponent extends Component { this.setSlots(slots); } - duplicateWithoutContents() { - const slots = []; - for (let i = 0; i < this.slots.length; ++i) { - const slot = this.slots[i]; - slots.push({ - pos: slot.pos.copy(), - type: slot.type, - direction: slot.direction, - }); - } - - return new WiredPinsComponent({ slots }); - } - /** * Sets the slots of this building * @param {Array} slots @@ -76,6 +63,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..2df8989f 100644 --- a/src/js/game/core.js +++ b/src/js/game/core.js @@ -1,480 +1,555 @@ -/* 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, + getBufferStats, + 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 { RegularGameMode } from "./modes/regular"; +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 game mode + root.gameMode = new RegularGameMode(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); + } + + 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.5 && !lowQuality) { + desiredAtlasScale = ORIGINAL_SPRITE_SCALE; + } else if (effectiveZoomLevel > 0.35 && !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); + + // On low performance, skip the fade + if (this.root.entityMgr.entities.length > 5000 || this.root.dynamicTickrate.averageFps < 50) { + this.overlayAlpha = desiredOverlayAlpha; + } + + 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( + "Maintained Buffers: " + + stats.rootKeys + + " root keys / " + + stats.subKeys + + " buffers / VRAM: " + + round2Digits(stats.vramBytes / (1024 * 1024)) + + " MB", + 20, + 620 + ); + const internalStats = getBufferStats(); + context.fillText( + "Total Buffers: " + + internalStats.bufferCount + + " buffers / " + + internalStats.backlogSize + + " backlog / " + + internalStats.backlogKeys + + " keys in backlog / VRAM " + + round2Digits(internalStats.vramUsage / (1024 * 1024)) + + " MB / Backlog " + + round2Digits(internalStats.backlogVramUsage / (1024 * 1024)) + + " MB / Created " + + internalStats.numCreated + + " / Reused " + + internalStats.numReused, + 20, + 640 + ); + } + + 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..d7dd715e 100644 --- a/src/js/game/entity.js +++ b/src/js/game/entity.js @@ -1,234 +1,233 @@ -/* typehints:start */ -import { DrawParameters } from "../core/draw_parameters"; -import { Component } from "./component"; -/* typehints:end */ - -import { GameRoot, enumLayer } from "./root"; -import { globalConfig } from "../core/config"; -import { enumDirectionToVector, enumDirectionToAngle } from "../core/vector"; -import { BasicSerializableObject, types } from "../savegame/serialization"; -import { EntityComponentStorage } from "./entity_components"; -import { Loader } from "../core/loader"; -import { drawRotatedSprite } from "../core/draw_utils"; -import { gComponentRegistry } from "../core/global_registries"; - -export class Entity extends BasicSerializableObject { - /** - * @param {GameRoot} root - */ - constructor(root) { - super(); - - /** - * Handle to the global game root - */ - this.root = root; - - /** - * The components of the entity - */ - this.components = new EntityComponentStorage(); - - /** - * Whether this entity was registered on the @see EntityManager so far - */ - this.registered = false; - - /** - * On which layer this entity is - */ - this.layer = enumLayer.regular; - - /** - * Internal entity unique id, set by the @see EntityManager - */ - this.uid = 0; - - /* typehints:start */ - - /** - * Stores if this entity is destroyed, set by the @see EntityManager - * @type {boolean} */ - this.destroyed; - - /** - * Stores if this entity is queued to get destroyed in the next tick - * of the @see EntityManager - * @type {boolean} */ - this.queuedForDestroy; - - /** - * Stores the reason why this entity was destroyed - * @type {string} */ - this.destroyReason; - - /* typehints:end */ - } - - static getId() { - return "Entity"; - } - - /** - * @see BasicSerializableObject.getSchema - * @returns {import("../savegame/serialization").Schema} - */ - static getSchema() { - return { - uid: types.uint, - components: types.keyValueMap(types.objData(gComponentRegistry)), - layer: types.enum(enumLayer), - }; - } - - /** - * Returns a clone of this entity without contents - */ - duplicateWithoutContents() { - const clone = new Entity(this.root); - for (const key in this.components) { - clone.components[key] = this.components[key].duplicateWithoutContents(); - } - clone.layer = this.layer; - return clone; - } - - /** - * Internal destroy callback - */ - internalDestroyCallback() { - assert(!this.destroyed, "Can not destroy entity twice"); - this.destroyed = true; - } - - /** - * Adds a new component, only possible until the entity is registered on the entity manager, - * after that use @see EntityManager.addDynamicComponent - * @param {Component} componentInstance - * @param {boolean} force Used by the entity manager. Internal parameter, do not change - */ - addComponent(componentInstance, force = false) { - if (!force && this.registered) { - this.root.entityMgr.attachDynamicComponent(this, componentInstance); - return; - } - assert(force || !this.registered, "Entity already registered, use EntityManager.addDynamicComponent"); - const id = /** @type {typeof Component} */ (componentInstance.constructor).getId(); - assert(!this.components[id], "Component already present"); - this.components[id] = componentInstance; - } - - /** - * Removes a given component, only possible until the entity is registered on the entity manager, - * after that use @see EntityManager.removeDynamicComponent - * @param {typeof Component} componentClass - * @param {boolean} force - */ - removeComponent(componentClass, force = false) { - if (!force && this.registered) { - this.root.entityMgr.removeDynamicComponent(this, componentClass); - return; - } - assert( - force || !this.registered, - "Entity already registered, use EntityManager.removeDynamicComponent" - ); - const id = componentClass.getId(); - assert(this.components[id], "Component does not exist on entity"); - delete this.components[id]; - } - - /** - * Draws the entity, to override use @see Entity.drawImpl - * @param {DrawParameters} parameters - */ - drawDebugOverlays(parameters) { - const context = parameters.context; - const staticComp = this.components.StaticMapEntity; - - if (G_IS_DEV && staticComp && globalConfig.debug.showEntityBounds) { - if (staticComp) { - const transformed = staticComp.getTileSpaceBounds(); - context.strokeStyle = "rgba(255, 0, 0, 0.5)"; - context.lineWidth = 2; - // const boundsSize = 20; - context.beginPath(); - context.rect( - transformed.x * globalConfig.tileSize, - transformed.y * globalConfig.tileSize, - transformed.w * globalConfig.tileSize, - transformed.h * globalConfig.tileSize - ); - context.stroke(); - } - } - if (G_IS_DEV && staticComp && globalConfig.debug.showAcceptorEjectors) { - const ejectorComp = this.components.ItemEjector; - - if (ejectorComp) { - 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]; - const angle = Math.radians(enumDirectionToAngle[direction]); - - context.globalAlpha = slot.item ? 1 : 0.2; - drawRotatedSprite({ - parameters, - sprite: ejectorSprite, - x: (slotTile.x + 0.5 + directionVector.x * 0.37) * globalConfig.tileSize, - y: (slotTile.y + 0.5 + directionVector.y * 0.37) * globalConfig.tileSize, - angle, - size: globalConfig.tileSize * 0.25, - }); - } - } - const acceptorComp = this.components.ItemAcceptor; - - if (acceptorComp) { - const acceptorSprite = Loader.getSprite("sprites/debug/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]); - const directionVector = enumDirectionToVector[direction]; - const angle = Math.radians(enumDirectionToAngle[direction] + 180); - context.globalAlpha = 0.4; - drawRotatedSprite({ - parameters, - sprite: acceptorSprite, - x: (slotTile.x + 0.5 + directionVector.x * 0.37) * globalConfig.tileSize, - y: (slotTile.y + 0.5 + directionVector.y * 0.37) * globalConfig.tileSize, - angle, - size: globalConfig.tileSize * 0.25, - }); - } - } - } - - context.globalAlpha = 1; - } - // this.drawImpl(parameters); - } - - ///// Helper interfaces - - ///// Interface to override by subclasses - - /** - * override, should draw the entity - * @param {DrawParameters} parameters - */ - drawImpl(parameters) { - abstract; - } -} +/* typehints:start */ +import { DrawParameters } from "../core/draw_parameters"; +import { Component } from "./component"; +/* typehints:end */ + +import { GameRoot } from "./root"; +import { globalConfig } from "../core/config"; +import { enumDirectionToVector, enumDirectionToAngle } from "../core/vector"; +import { BasicSerializableObject, types } from "../savegame/serialization"; +import { EntityComponentStorage } from "./entity_components"; +import { Loader } from "../core/loader"; +import { drawRotatedSprite } from "../core/draw_utils"; +import { gComponentRegistry } from "../core/global_registries"; +import { getBuildingDataFromCode } from "./building_codes"; + +export class Entity extends BasicSerializableObject { + /** + * @param {GameRoot} root + */ + constructor(root) { + super(); + + /** + * Handle to the global game root + */ + this.root = root; + + /** + * The components of the entity + */ + this.components = new EntityComponentStorage(); + + /** + * Whether this entity was registered on the @see EntityManager so far + */ + this.registered = false; + + /** + * On which layer this entity is + * @type {Layer} + */ + this.layer = "regular"; + + /** + * Internal entity unique id, set by the @see EntityManager + */ + this.uid = 0; + + /* typehints:start */ + + /** + * Stores if this entity is destroyed, set by the @see EntityManager + * @type {boolean} */ + this.destroyed; + + /** + * Stores if this entity is queued to get destroyed in the next tick + * of the @see EntityManager + * @type {boolean} */ + this.queuedForDestroy; + + /** + * Stores the reason why this entity was destroyed + * @type {string} */ + this.destroyReason; + + /* typehints:end */ + } + + static getId() { + return "Entity"; + } + + /** + * @see BasicSerializableObject.getSchema + * @returns {import("../savegame/serialization").Schema} + */ + static getSchema() { + return { + uid: types.uint, + components: types.keyValueMap(types.objData(gComponentRegistry), false), + }; + } + + /** + * Returns a clone of this entity + */ + clone() { + const staticComp = this.components.StaticMapEntity; + const buildingData = getBuildingDataFromCode(staticComp.code); + + const clone = buildingData.metaInstance.createEntity({ + root: this.root, + origin: staticComp.origin, + originalRotation: staticComp.originalRotation, + rotation: staticComp.rotation, + rotationVariant: buildingData.rotationVariant, + variant: buildingData.variant, + }); + + for (const key in this.components) { + /** @type {Component} */ (this.components[key]).copyAdditionalStateTo(clone.components[key]); + } + + return clone; + } + + /** + * Adds a new component, only possible until the entity is registered on the entity manager, + * after that use @see EntityManager.addDynamicComponent + * @param {Component} componentInstance + * @param {boolean} force Used by the entity manager. Internal parameter, do not change + */ + addComponent(componentInstance, force = false) { + if (!force && this.registered) { + this.root.entityMgr.attachDynamicComponent(this, componentInstance); + return; + } + assert(force || !this.registered, "Entity already registered, use EntityManager.addDynamicComponent"); + const id = /** @type {typeof Component} */ (componentInstance.constructor).getId(); + assert(!this.components[id], "Component already present"); + this.components[id] = componentInstance; + } + + /** + * Removes a given component, only possible until the entity is registered on the entity manager, + * after that use @see EntityManager.removeDynamicComponent + * @param {typeof Component} componentClass + * @param {boolean} force + */ + removeComponent(componentClass, force = false) { + if (!force && this.registered) { + this.root.entityMgr.removeDynamicComponent(this, componentClass); + return; + } + assert( + force || !this.registered, + "Entity already registered, use EntityManager.removeDynamicComponent" + ); + const id = componentClass.getId(); + assert(this.components[id], "Component does not exist on entity"); + delete this.components[id]; + } + + /** + * Draws the entity, to override use @see Entity.drawImpl + * @param {DrawParameters} parameters + */ + drawDebugOverlays(parameters) { + const context = parameters.context; + const staticComp = this.components.StaticMapEntity; + + if (G_IS_DEV && staticComp && globalConfig.debug.showEntityBounds) { + if (staticComp) { + const transformed = staticComp.getTileSpaceBounds(); + context.strokeStyle = "rgba(255, 0, 0, 0.5)"; + context.lineWidth = 2; + // const boundsSize = 20; + context.beginPath(); + context.rect( + transformed.x * globalConfig.tileSize, + transformed.y * globalConfig.tileSize, + transformed.w * globalConfig.tileSize, + transformed.h * globalConfig.tileSize + ); + context.stroke(); + } + } + + if (G_IS_DEV && staticComp && globalConfig.debug.showAcceptorEjectors) { + const ejectorComp = this.components.ItemEjector; + + if (ejectorComp) { + const ejectorSprite = Loader.getSprite("sprites/debug/ejector_slot.png"); + for (let i = 0; i < ejectorComp.slots.length; ++i) { + const slot = ejectorComp.slots[i]; + const slotTile = staticComp.localTileToWorld(slot.pos); + const direction = staticComp.localDirectionToWorld(slot.direction); + const directionVector = enumDirectionToVector[direction]; + const angle = Math.radians(enumDirectionToAngle[direction]); + + context.globalAlpha = slot.item ? 1 : 0.2; + drawRotatedSprite({ + parameters, + sprite: ejectorSprite, + x: (slotTile.x + 0.5 + directionVector.x * 0.37) * globalConfig.tileSize, + y: (slotTile.y + 0.5 + directionVector.y * 0.37) * globalConfig.tileSize, + angle, + size: globalConfig.tileSize * 0.25, + }); + } + } + const acceptorComp = this.components.ItemAcceptor; + + if (acceptorComp) { + const acceptorSprite = Loader.getSprite("sprites/misc/acceptor_slot.png"); + for (let i = 0; i < acceptorComp.slots.length; ++i) { + const slot = acceptorComp.slots[i]; + const slotTile = staticComp.localTileToWorld(slot.pos); + for (let k = 0; k < slot.directions.length; ++k) { + const direction = staticComp.localDirectionToWorld(slot.directions[k]); + const directionVector = enumDirectionToVector[direction]; + const angle = Math.radians(enumDirectionToAngle[direction] + 180); + context.globalAlpha = 0.4; + drawRotatedSprite({ + parameters, + sprite: acceptorSprite, + x: (slotTile.x + 0.5 + directionVector.x * 0.37) * globalConfig.tileSize, + y: (slotTile.y + 0.5 + directionVector.y * 0.37) * globalConfig.tileSize, + angle, + size: globalConfig.tileSize * 0.25, + }); + } + } + } + + context.globalAlpha = 1; + } + // this.drawImpl(parameters); + } + + ///// Helper interfaces + + ///// Interface to override by subclasses + + /** + * override, should draw the entity + * @param {DrawParameters} parameters + */ + drawImpl(parameters) { + abstract; + } +} diff --git a/src/js/game/entity_components.js b/src/js/game/entity_components.js index 24430dd2..7dee590a 100644 --- a/src/js/game/entity_components.js +++ b/src/js/game/entity_components.js @@ -1,70 +1,94 @@ -/* 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"; +import { FilterComponent } from "./components/filter"; +import { ItemProducerComponent } from "./components/item_producer"; +/* 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; + + /** @type {FilterComponent} */ + this.Filter; + + /** @type {ItemProducerComponent} */ + this.ItemProducer; + + /* typehints:end */ + } +} diff --git a/src/js/game/entity_manager.js b/src/js/game/entity_manager.js index 11bc709c..b4101fc8 100644 --- a/src/js/game/entity_manager.js +++ b/src/js/game/entity_manager.js @@ -1,252 +1,241 @@ -import { arrayDeleteValue, newEmptyMap, fastArrayDeleteValue } from "../core/utils"; -import { Component } from "./component"; -import { GameRoot } from "./root"; -import { Entity } from "./entity"; -import { BasicSerializableObject, types } from "../savegame/serialization"; -import { createLogger } from "../core/logging"; - -const logger = createLogger("entity_manager"); - -// Manages all entities - -// NOTICE: We use arrayDeleteValue instead of fastArrayDeleteValue since that does not preserve the order -// This is slower but we need it for the street path generation - -export class EntityManager extends BasicSerializableObject { - constructor(root) { - super(); - - /** @type {GameRoot} */ - this.root = root; - - /** @type {Array} */ - this.entities = []; - - // We store a seperate list with entities to destroy, since we don't destroy - // them instantly - /** @type {Array} */ - this.destroyList = []; - - // Store a map from componentid to entities - This is used by the game system - // for faster processing - /** @type {Object.>} */ - this.componentToEntity = newEmptyMap(); - - // Store the next uid to use - this.nextUid = 10000; - } - - static getId() { - return "EntityManager"; - } - - static getSchema() { - return { - nextUid: types.uint, - }; - } - - getStatsText() { - return this.entities.length + " entities [" + this.destroyList.length + " to kill]"; - } - - // Main update - update() { - this.processDestroyList(); - } - - /** - * Registers a new entity - * @param {Entity} entity - * @param {number=} uid Optional predefined uid - */ - registerEntity(entity, uid = null) { - assert(this.entities.indexOf(entity) < 0, `RegisterEntity() called twice for entity ${entity}`); - assert(!entity.destroyed, `Attempting to register destroyed entity ${entity}`); - - if (G_IS_DEV && uid !== null) { - assert(!this.findByUid(uid, false), "Entity uid already taken: " + uid); - } - - if (uid !== null) { - assert(uid >= 0 && uid < Number.MAX_SAFE_INTEGER, "Invalid uid passed: " + uid); - } - - this.entities.push(entity); - - // Register into the componentToEntity map - for (const componentId in entity.components) { - if (entity.components[componentId]) { - if (this.componentToEntity[componentId]) { - this.componentToEntity[componentId].push(entity); - } else { - this.componentToEntity[componentId] = [entity]; - } - } - } - - // Give each entity a unique id - entity.uid = uid ? uid : this.generateUid(); - entity.registered = true; - - this.root.signals.entityAdded.dispatch(entity); - } - - /** - * Sorts all entitiy lists after a resync - */ - sortEntityLists() { - this.entities.sort((a, b) => a.uid - b.uid); - this.destroyList.sort((a, b) => a.uid - b.uid); - - for (const key in this.componentToEntity) { - this.componentToEntity[key].sort((a, b) => a.uid - b.uid); - } - } - - /** - * Generates a new uid - * @returns {number} - */ - generateUid() { - return this.nextUid++; - } - - /** - * Call to attach a new component after the creation of the entity - * @param {Entity} entity - * @param {Component} component - */ - attachDynamicComponent(entity, component) { - entity.addComponent(component, true); - const componentId = /** @type {typeof Component} */ (component.constructor).getId(); - if (this.componentToEntity[componentId]) { - this.componentToEntity[componentId].push(entity); - } else { - this.componentToEntity[componentId] = [entity]; - } - this.root.signals.entityGotNewComponent.dispatch(entity); - } - - /** - * Call to remove a component after the creation of the entity - * @param {Entity} entity - * @param {typeof Component} component - */ - removeDynamicComponent(entity, component) { - entity.removeComponent(component, true); - const componentId = /** @type {typeof Component} */ (component.constructor).getId(); - - fastArrayDeleteValue(this.componentToEntity[componentId], entity); - this.root.signals.entityComponentRemoved.dispatch(entity); - } - - /** - * Finds an entity buy its uid, kinda slow since it loops over all entities - * @param {number} uid - * @param {boolean=} errorWhenNotFound - * @returns {Entity} - */ - findByUid(uid, errorWhenNotFound = true) { - const arr = this.entities; - for (let i = 0, len = arr.length; i < len; ++i) { - const entity = arr[i]; - if (entity.uid === uid) { - if (entity.queuedForDestroy || entity.destroyed) { - if (errorWhenNotFound) { - logger.warn("Entity with UID", uid, "not found (destroyed)"); - } - return null; - } - return entity; - } - } - if (errorWhenNotFound) { - logger.warn("Entity with UID", uid, "not found"); - } - return null; - } - - /** - * Returns all entities having the given component - * @param {typeof Component} componentHandle - * @returns {Array} entities - */ - getAllWithComponent(componentHandle) { - return this.componentToEntity[componentHandle.getId()] || []; - } - - /** - * Return all of a given class. This is SLOW! - * @param {object} entityClass - * @returns {Array} entities - */ - getAllOfClass(entityClass) { - // FIXME: Slow - const result = []; - for (let i = 0; i < this.entities.length; ++i) { - const entity = this.entities[i]; - if (entity instanceof entityClass) { - result.push(entity); - } - } - return result; - } - - /** - * Unregisters all components of an entity from the component to entity mapping - * @param {Entity} entity - */ - unregisterEntityComponents(entity) { - for (const componentId in entity.components) { - if (entity.components[componentId]) { - arrayDeleteValue(this.componentToEntity[componentId], entity); - } - } - } - - // Processes the entities to destroy and actually destroys them - /* eslint-disable max-statements */ - processDestroyList() { - for (let i = 0; i < this.destroyList.length; ++i) { - const entity = this.destroyList[i]; - - // Remove from entities list - arrayDeleteValue(this.entities, entity); - - // Remove from componentToEntity list - this.unregisterEntityComponents(entity); - - entity.registered = false; - entity.internalDestroyCallback(); - - this.root.signals.entityDestroyed.dispatch(entity); - } - - this.destroyList = []; - } - - /** - * Queues an entity for destruction - * @param {Entity} entity - */ - destroyEntity(entity) { - if (entity.destroyed) { - logger.error("Tried to destroy already destroyed entity:", entity.uid); - return; - } - - if (entity.queuedForDestroy) { - logger.error("Trying to destroy entity which is already queued for destroy!", entity.uid); - return; - } - - if (this.destroyList.indexOf(entity) < 0) { - this.destroyList.push(entity); - entity.queuedForDestroy = true; - this.root.signals.entityQueuedForDestroy.dispatch(entity); - } else { - assert(false, "Trying to destroy entity twice"); - } - } -} +import { arrayDeleteValue, newEmptyMap, fastArrayDeleteValue } from "../core/utils"; +import { Component } from "./component"; +import { GameRoot } from "./root"; +import { Entity } from "./entity"; +import { BasicSerializableObject, types } from "../savegame/serialization"; +import { createLogger } from "../core/logging"; +import { globalConfig } from "../core/config"; + +const logger = createLogger("entity_manager"); + +// Manages all entities + +// NOTICE: We use arrayDeleteValue instead of fastArrayDeleteValue since that does not preserve the order +// This is slower but we need it for the street path generation + +export class EntityManager extends BasicSerializableObject { + constructor(root) { + super(); + + /** @type {GameRoot} */ + this.root = root; + + /** @type {Array} */ + this.entities = []; + + // We store a separate list with entities to destroy, since we don't destroy + // them instantly + /** @type {Array} */ + this.destroyList = []; + + // Store a map from componentid to entities - This is used by the game system + // for faster processing + /** @type {Object.>} */ + this.componentToEntity = newEmptyMap(); + + // Store the next uid to use + this.nextUid = 10000; + } + + static getId() { + return "EntityManager"; + } + + static getSchema() { + return { + nextUid: types.uint, + }; + } + + getStatsText() { + return this.entities.length + " entities [" + this.destroyList.length + " to kill]"; + } + + // Main update + update() { + this.processDestroyList(); + } + + /** + * Registers a new entity + * @param {Entity} entity + * @param {number=} uid Optional predefined uid + */ + registerEntity(entity, uid = null) { + if (G_IS_DEV && !globalConfig.debug.disableSlowAsserts) { + assert(this.entities.indexOf(entity) < 0, `RegisterEntity() called twice for entity ${entity}`); + } + assert(!entity.destroyed, `Attempting to register destroyed entity ${entity}`); + + if (G_IS_DEV && !globalConfig.debug.disableSlowAsserts && uid !== null) { + assert(!this.findByUid(uid, false), "Entity uid already taken: " + uid); + assert(uid >= 0 && uid < Number.MAX_SAFE_INTEGER, "Invalid uid passed: " + uid); + } + + this.entities.push(entity); + + // Register into the componentToEntity map + for (const componentId in entity.components) { + if (entity.components[componentId]) { + if (this.componentToEntity[componentId]) { + this.componentToEntity[componentId].push(entity); + } else { + this.componentToEntity[componentId] = [entity]; + } + } + } + + // Give each entity a unique id + entity.uid = uid ? uid : this.generateUid(); + entity.registered = true; + + this.root.signals.entityAdded.dispatch(entity); + } + + /** + * Generates a new uid + * @returns {number} + */ + generateUid() { + return this.nextUid++; + } + + /** + * Call to attach a new component after the creation of the entity + * @param {Entity} entity + * @param {Component} component + */ + attachDynamicComponent(entity, component) { + entity.addComponent(component, true); + const componentId = /** @type {typeof Component} */ (component.constructor).getId(); + if (this.componentToEntity[componentId]) { + this.componentToEntity[componentId].push(entity); + } else { + this.componentToEntity[componentId] = [entity]; + } + this.root.signals.entityGotNewComponent.dispatch(entity); + } + + /** + * Call to remove a component after the creation of the entity + * @param {Entity} entity + * @param {typeof Component} component + */ + removeDynamicComponent(entity, component) { + entity.removeComponent(component, true); + const componentId = /** @type {typeof Component} */ (component.constructor).getId(); + + fastArrayDeleteValue(this.componentToEntity[componentId], entity); + this.root.signals.entityComponentRemoved.dispatch(entity); + } + + /** + * Finds an entity buy its uid, kinda slow since it loops over all entities + * @param {number} uid + * @param {boolean=} errorWhenNotFound + * @returns {Entity} + */ + findByUid(uid, errorWhenNotFound = true) { + const arr = this.entities; + for (let i = 0, len = arr.length; i < len; ++i) { + const entity = arr[i]; + if (entity.uid === uid) { + if (entity.queuedForDestroy || entity.destroyed) { + if (errorWhenNotFound) { + logger.warn("Entity with UID", uid, "not found (destroyed)"); + } + return null; + } + return entity; + } + } + if (errorWhenNotFound) { + logger.warn("Entity with UID", uid, "not found"); + } + return null; + } + + /** + * Returns a map which gives a mapping from UID to Entity. + * This map is not updated. + * + * @returns {Map} + */ + getFrozenUidSearchMap() { + const result = new Map(); + const array = this.entities; + for (let i = 0, len = array.length; i < len; ++i) { + const entity = array[i]; + if (!entity.queuedForDestroy && !entity.destroyed) { + result.set(entity.uid, entity); + } + } + return result; + } + + /** + * Returns all entities having the given component + * @param {typeof Component} componentHandle + * @returns {Array} entities + */ + getAllWithComponent(componentHandle) { + return this.componentToEntity[componentHandle.getId()] || []; + } + + /** + * Unregisters all components of an entity from the component to entity mapping + * @param {Entity} entity + */ + unregisterEntityComponents(entity) { + for (const componentId in entity.components) { + if (entity.components[componentId]) { + arrayDeleteValue(this.componentToEntity[componentId], entity); + } + } + } + + // Processes the entities to destroy and actually destroys them + /* eslint-disable max-statements */ + processDestroyList() { + for (let i = 0; i < this.destroyList.length; ++i) { + const entity = this.destroyList[i]; + + // Remove from entities list + arrayDeleteValue(this.entities, entity); + + // Remove from componentToEntity list + this.unregisterEntityComponents(entity); + + entity.registered = false; + entity.destroyed = true; + + this.root.signals.entityDestroyed.dispatch(entity); + } + + this.destroyList = []; + } + + /** + * Queues an entity for destruction + * @param {Entity} entity + */ + destroyEntity(entity) { + if (entity.destroyed) { + logger.error("Tried to destroy already destroyed entity:", entity.uid); + return; + } + + if (entity.queuedForDestroy) { + logger.error("Trying to destroy entity which is already queued for destroy!", entity.uid); + return; + } + + if (this.destroyList.indexOf(entity) < 0) { + this.destroyList.push(entity); + entity.queuedForDestroy = true; + this.root.signals.entityQueuedForDestroy.dispatch(entity); + } else { + assert(false, "Trying to destroy entity twice"); + } + } +} diff --git a/src/js/game/game_loading_overlay.js b/src/js/game/game_loading_overlay.js index f1e9d6ce..d6bb79f0 100644 --- a/src/js/game/game_loading_overlay.js +++ b/src/js/game/game_loading_overlay.js @@ -1,6 +1,8 @@ /* typehints:start */ import { Application } from "../application"; /* typehints:end */ + +import { randomChoice } from "../core/utils"; import { T } from "../translations"; export class GameLoadingOverlay { @@ -43,6 +45,7 @@ export class GameLoadingOverlay { this.element.classList.add("gameLoadingOverlay"); this.parent.appendChild(this.element); this.internalAddSpinnerAndText(this.element); + this.internalAddHint(this.element); } /** @@ -52,7 +55,17 @@ export class GameLoadingOverlay { internalAddSpinnerAndText(element) { const inner = document.createElement("span"); inner.classList.add("prefab_LoadingTextWithAnim"); - inner.innerText = T.global.loading; element.appendChild(inner); } + + /** + * Adds a random hint + * @param {HTMLElement} element + */ + internalAddHint(element) { + const hint = document.createElement("span"); + hint.innerHTML = randomChoice(T.tips); + hint.classList.add("prefab_GameHint"); + element.appendChild(hint); + } } diff --git a/src/js/game/game_mode.js b/src/js/game/game_mode.js new file mode 100644 index 00000000..15403eb5 --- /dev/null +++ b/src/js/game/game_mode.js @@ -0,0 +1,71 @@ +/* typehints:start */ +import { enumHubGoalRewards } from "./tutorial_goals"; +/* typehints:end */ + +import { GameRoot } from "./root"; + +/** @typedef {{ + * shape: string, + * amount: number + * }} UpgradeRequirement */ + +/** @typedef {{ + * required: Array + * improvement?: number, + * excludePrevious?: boolean + * }} TierRequirement */ + +/** @typedef {Array} UpgradeTiers */ + +/** @typedef {{ + * shape: string, + * required: number, + * reward: enumHubGoalRewards, + * throughputOnly?: boolean + * }} LevelDefinition */ + +export class GameMode { + /** + * + * @param {GameRoot} root + */ + constructor(root) { + this.root = root; + } + + /** + * Should return all available upgrades + * @returns {Object} + */ + getUpgrades() { + abstract; + return null; + } + + /** + * Returns the blueprint shape key + * @returns {string} + */ + getBlueprintShapeKey() { + abstract; + return null; + } + + /** + * Returns the goals for all levels including their reward + * @returns {Array} + */ + getLevelDefinitions() { + abstract; + return null; + } + + /** + * Should return whether free play is available or if the game stops + * after the predefined levels + * @returns {boolean} + */ + getIsFreeplayAvailable() { + return true; + } +} diff --git a/src/js/game/game_system_manager.js b/src/js/game/game_system_manager.js index ed9d1155..74ba798f 100644 --- a/src/js/game/game_system_manager.js +++ b/src/js/game/game_system_manager.js @@ -1,137 +1,187 @@ -/* 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"; +import { FilterSystem } from "./systems/filter"; +import { ItemProducerSystem } from "./systems/item_producer"; + +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, + + /** @type {FilterSystem} */ + filter: null, + + /** @type {ItemProducerSystem} */ + itemProducer: 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("filter", FilterSystem); + + add("itemProducer", ItemProducerSystem); + + 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..a6efeffd 100644 --- a/src/js/game/game_system_with_filter.js +++ b/src/js/game/game_system_with_filter.js @@ -1,214 +1,137 @@ -/* typehints:start */ -import { Component } from "./component"; -import { Entity } from "./entity"; -/* typehints:end */ - -import { GameRoot, enumLayer } 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 - * all entities which have *all* of the passed components - * @param {GameRoot} root - * @param {Array} requiredComponents - */ - constructor(root, requiredComponents) { - super(root); - this.requiredComponents = requiredComponents; - this.requiredComponentIds = requiredComponents.map(component => component.getId()); - - /** - * All entities which match the current components - * @type {Array} - */ - this.allEntities = []; - - this.root.signals.entityAdded.add(this.internalPushEntityIfMatching, this); - this.root.signals.entityGotNewComponent.add(this.internalReconsiderEntityToAdd, this); - this.root.signals.entityComponentRemoved.add(this.internalCheckEntityAfterComponentRemoval, this); - this.root.signals.entityQueuedForDestroy.add(this.internalPopEntityIfMatching, this); - - this.root.signals.postLoadHook.add(this.internalPostLoadHook, this); - 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 - */ - internalPushEntityIfMatching(entity) { - for (let i = 0; i < this.requiredComponentIds.length; ++i) { - if (!entity.components[this.requiredComponentIds[i]]) { - return; - } - } - - assert(this.allEntities.indexOf(entity) < 0, "entity already in list: " + entity); - this.internalRegisterEntity(entity); - } - - /** - * - * @param {Entity} entity - */ - internalCheckEntityAfterComponentRemoval(entity) { - if (this.allEntities.indexOf(entity) < 0) { - // Entity wasn't interesting anyways - return; - } - - for (let i = 0; i < this.requiredComponentIds.length; ++i) { - if (!entity.components[this.requiredComponentIds[i]]) { - // Entity is not interesting anymore - arrayDeleteValue(this.allEntities, entity); - } - } - } - - /** - * - * @param {Entity} entity - */ - internalReconsiderEntityToAdd(entity) { - for (let i = 0; i < this.requiredComponentIds.length; ++i) { - if (!entity.components[this.requiredComponentIds[i]]) { - return; - } - } - if (this.allEntities.indexOf(entity) >= 0) { - return; - } - this.internalRegisterEntity(entity); - } - - refreshCaches() { - this.allEntities.sort((a, b) => a.uid - b.uid); - - // Remove all entities which are queued for destroy - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - if (entity.queuedForDestroy || entity.destroyed) { - this.allEntities.splice(i, 1); - } - } - } - - /** - * Recomputes all target entities after the game has loaded - */ - internalPostLoadHook() { - this.refreshCaches(); - } - - /** - * - * @param {Entity} entity - */ - internalRegisterEntity(entity) { - this.allEntities.push(entity); - - if (this.root.gameInitialized && !this.root.bulkOperationRunning) { - // Sort entities by uid so behaviour is predictable - this.allEntities.sort((a, b) => a.uid - b.uid); - } - } - - /** - * - * @param {Entity} entity - */ - internalPopEntityIfMatching(entity) { - if (this.root.bulkOperationRunning) { - // We do this in refreshCaches afterwards - return; - } - const index = this.allEntities.indexOf(entity); - if (index >= 0) { - arrayDelete(this.allEntities, index); - } - } -} +/* typehints:start */ +import { Component } from "./component"; +import { Entity } from "./entity"; +/* typehints:end */ + +import { GameRoot } from "./root"; +import { GameSystem } from "./game_system"; +import { arrayDelete, arrayDeleteValue } from "../core/utils"; +import { globalConfig } from "../core/config"; + +export class GameSystemWithFilter extends GameSystem { + /** + * Constructs a new game system with the given component filter. It will process + * all entities which have *all* of the passed components + * @param {GameRoot} root + * @param {Array} requiredComponents + */ + constructor(root, requiredComponents) { + super(root); + this.requiredComponents = requiredComponents; + this.requiredComponentIds = requiredComponents.map(component => component.getId()); + + /** + * All entities which match the current components + * @type {Array} + */ + this.allEntities = []; + + this.root.signals.entityAdded.add(this.internalPushEntityIfMatching, this); + this.root.signals.entityGotNewComponent.add(this.internalReconsiderEntityToAdd, this); + this.root.signals.entityComponentRemoved.add(this.internalCheckEntityAfterComponentRemoval, this); + this.root.signals.entityQueuedForDestroy.add(this.internalPopEntityIfMatching, this); + + this.root.signals.postLoadHook.add(this.internalPostLoadHook, this); + this.root.signals.bulkOperationFinished.add(this.refreshCaches, this); + } + + /** + * @param {Entity} entity + */ + internalPushEntityIfMatching(entity) { + for (let i = 0; i < this.requiredComponentIds.length; ++i) { + if (!entity.components[this.requiredComponentIds[i]]) { + return; + } + } + + // This is slow! + if (G_IS_DEV && !globalConfig.debug.disableSlowAsserts) { + assert(this.allEntities.indexOf(entity) < 0, "entity already in list: " + entity); + } + + this.internalRegisterEntity(entity); + } + + /** + * + * @param {Entity} entity + */ + internalCheckEntityAfterComponentRemoval(entity) { + if (this.allEntities.indexOf(entity) < 0) { + // Entity wasn't interesting anyways + return; + } + + for (let i = 0; i < this.requiredComponentIds.length; ++i) { + if (!entity.components[this.requiredComponentIds[i]]) { + // Entity is not interesting anymore + arrayDeleteValue(this.allEntities, entity); + } + } + } + + /** + * + * @param {Entity} entity + */ + internalReconsiderEntityToAdd(entity) { + for (let i = 0; i < this.requiredComponentIds.length; ++i) { + if (!entity.components[this.requiredComponentIds[i]]) { + return; + } + } + if (this.allEntities.indexOf(entity) >= 0) { + return; + } + this.internalRegisterEntity(entity); + } + + refreshCaches() { + // Remove all entities which are queued for destroy + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + if (entity.queuedForDestroy || entity.destroyed) { + this.allEntities.splice(i, 1); + i -= 1; + } + } + + this.allEntities.sort((a, b) => a.uid - b.uid); + } + + /** + * Recomputes all target entities after the game has loaded + */ + internalPostLoadHook() { + this.refreshCaches(); + } + + /** + * + * @param {Entity} entity + */ + internalRegisterEntity(entity) { + this.allEntities.push(entity); + + if (this.root.gameInitialized && !this.root.bulkOperationRunning) { + // Sort entities by uid so behaviour is predictable + this.allEntities.sort((a, b) => a.uid - b.uid); + } + } + + /** + * + * @param {Entity} entity + */ + internalPopEntityIfMatching(entity) { + if (this.root.bulkOperationRunning) { + // We do this in refreshCaches afterwards + return; + } + const index = this.allEntities.indexOf(entity); + if (index >= 0) { + arrayDelete(this.allEntities, index); + } + } +} diff --git a/src/js/game/hints.js b/src/js/game/hints.js new file mode 100644 index 00000000..c2e7e4e5 --- /dev/null +++ b/src/js/game/hints.js @@ -0,0 +1,22 @@ +import { randomChoice } from "../core/utils"; +import { T } from "../translations"; + +const hintsShown = []; + +/** + * Finds a new hint to show about the game which the user hasn't seen within this session + */ +export function getRandomHint() { + let maxTries = 100 * T.tips.length; + + while (maxTries-- > 0) { + const hint = randomChoice(T.tips); + if (!hintsShown.includes(hint)) { + hintsShown.push(hint); + return hint; + } + } + + // All tips shown so far + return randomChoice(T.tips); +} diff --git a/src/js/game/hub_goals.js b/src/js/game/hub_goals.js index 612bc124..c9d9494f 100644 --- a/src/js/game/hub_goals.js +++ b/src/js/game/hub_goals.js @@ -1,454 +1,545 @@ -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 { RandomNumberGenerator } from "../core/rng"; +import { clamp } from "../core/utils"; +import { BasicSerializableObject, types } from "../savegame/serialization"; +import { enumColors } from "./colors"; +import { enumItemProcessorTypes } from "./components/item_processor"; +import { enumAnalyticsDataSource } from "./production_analytics"; +import { GameRoot } from "./root"; +import { enumSubShape, ShapeDefinition } from "./shape_definition"; +import { enumHubGoalRewards } from "./tutorial_goals"; + +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), + }; + } + + /** + * + * @param {*} data + * @param {GameRoot} root + */ + deserialize(data, root) { + const errorCode = super.deserialize(data); + if (errorCode) { + return errorCode; + } + + const levels = root.gameMode.getLevelDefinitions(); + + // If freeplay is not available, clamp the level + if (!root.gameMode.getIsFreeplayAvailable()) { + this.level = Math.min(this.level, levels.length); + } + + // Compute gained rewards + for (let i = 0; i < this.level - 1; ++i) { + if (i < levels.length) { + const reward = levels[i].reward; + this.gainedRewards[reward] = (this.gainedRewards[reward] || 0) + 1; + } + } + + // Compute upgrade improvements + const upgrades = this.root.gameMode.getUpgrades(); + for (const upgradeId in upgrades) { + const tiers = upgrades[upgradeId]; + const level = this.upgradeLevels[upgradeId] || 0; + let totalImprovement = 1; + for (let i = 0; i < level; ++i) { + totalImprovement += tiers[i].improvement; + } + this.upgradeImprovements[upgradeId] = totalImprovement; + } + + // Compute current goal + this.computeNextGoal(); + } + + /** + * @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 = {}; + + // Reset levels first + const upgrades = this.root.gameMode.getUpgrades(); + for (const key in upgrades) { + this.upgradeLevels[key] = 0; + this.upgradeImprovements[key] = 1; + } + + this.computeNextGoal(); + + // 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) { + if (!this.isEndOfDemoReached()) { + this.onGoalCompleted(); + } + } + } + }); + } + } + + /** + * Returns whether the end of the demo is reached + * @returns {boolean} + */ + isEndOfDemoReached() { + return ( + !this.root.gameMode.getIsFreeplayAvailable() && + this.level >= this.root.gameMode.getLevelDefinitions().length + ); + } + + /** + * 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() { + if (this.currentGoal.throughputOnly) { + return ( + this.root.productionAnalytics.getCurrentShapeRate( + enumAnalyticsDataSource.delivered, + this.currentGoal.definition + ) / globalConfig.analyticsSliceDurationSeconds + ); + } + + 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 + if ( + this.getCurrentGoalDelivered() >= this.currentGoal.required || + (G_IS_DEV && globalConfig.debug.rewardsInstant) + ) { + if (!this.isEndOfDemoReached()) { + this.onGoalCompleted(); + } + } + } + + /** + * Creates the next goal + */ + computeNextGoal() { + const storyIndex = this.level - 1; + const levels = this.root.gameMode.getLevelDefinitions(); + if (storyIndex < levels.length) { + const { shape, required, reward, throughputOnly } = levels[storyIndex]; + this.currentGoal = { + /** @type {ShapeDefinition} */ + definition: this.root.shapeDefinitionMgr.getShapeFromShortKey(shape), + required, + reward, + throughputOnly, + }; + return; + } + + const required = Math.min(200, 4 + (this.level - 27) * 0.25); + this.currentGoal = { + definition: this.computeFreeplayShape(this.level), + required, + reward: enumHubGoalRewards.no_reward_freeplay, + throughputOnly: true, + }; + } + + /** + * 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.computeNextGoal(); + + this.root.signals.storyGoalCompleted.dispatch(this.level - 1, reward); + } + + /** + * Returns whether we are playing in free-play + */ + isFreePlay() { + return this.level >= this.root.gameMode.getLevelDefinitions().length; + } + + /** + * Returns whether a given upgrade can be unlocked + * @param {string} upgradeId + */ + canUnlockUpgrade(upgradeId) { + const tiers = this.root.gameMode.getUpgrades()[upgradeId]; + const currentLevel = this.getUpgradeLevel(upgradeId); + + if (currentLevel >= tiers.length) { + // Max level + return false; + } + + if (G_IS_DEV && globalConfig.debug.upgradesNoCost) { + return true; + } + + const tierData = 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 this.root.gameMode.getUpgrades()) { + 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 upgradeTiers = this.root.gameMode.getUpgrades()[upgradeId]; + const currentLevel = this.getUpgradeLevel(upgradeId); + + const tierData = upgradeTiers[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; + } + + /** + * Picks random colors which are close to each other + * @param {RandomNumberGenerator} rng + */ + generateRandomColorSet(rng, allowUncolored = false) { + const colorWheel = [ + enumColors.red, + enumColors.yellow, + enumColors.green, + enumColors.cyan, + enumColors.blue, + enumColors.purple, + enumColors.red, + enumColors.yellow, + ]; + + const universalColors = [enumColors.white]; + if (allowUncolored) { + universalColors.push(enumColors.uncolored); + } + const index = rng.nextIntRange(0, colorWheel.length - 2); + const pickedColors = colorWheel.slice(index, index + 3); + pickedColors.push(rng.choice(universalColors)); + return pickedColors; + } + + /** + * Creates a (seeded) random shape + * @param {number} level + * @returns {ShapeDefinition} + */ + computeFreeplayShape(level) { + const layerCount = clamp(this.level / 25, 2, 4); + + /** @type {Array} */ + let layers = []; + + const rng = new RandomNumberGenerator(this.root.map.seed + "/" + level); + + const colors = this.generateRandomColorSet(rng, level > 35); + + let pickedSymmetry = null; // pairs of quadrants that must be the same + let availableShapes = [enumSubShape.rect, enumSubShape.circle, enumSubShape.star]; + if (rng.next() < 0.5) { + pickedSymmetry = [ + // radial symmetry + [0, 2], + [1, 3], + ]; + availableShapes.push(enumSubShape.windmill); // windmill looks good only in radial symmetry + } else { + const symmetries = [ + [ + // horizontal axis + [0, 3], + [1, 2], + ], + [ + // vertical axis + [0, 1], + [2, 3], + ], + [ + // diagonal axis + [0, 2], + [1], + [3], + ], + [ + // other diagonal axis + [1, 3], + [0], + [2], + ], + ]; + pickedSymmetry = rng.choice(symmetries); + } + + const randomColor = () => rng.choice(colors); + const randomShape = () => rng.choice(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 j = 0; j < pickedSymmetry.length; ++j) { + const group = pickedSymmetry[j]; + const shape = randomShape(); + const color = randomColor(); + for (let k = 0; k < group.length; ++k) { + const quad = group[k]; + layer[quad] = { + subShape: shape, + color, + }; + } + } + + // 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 (level > 75 && rng.next() > 0.95 && !anyIsMissingTwo) { + layer[rng.nextIntRange(0, 4)] = 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.trash: + case enumItemProcessorTypes.hub: + return 1e30; + case enumItemProcessorTypes.balancer: + return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt * 2; + 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.rotater180: + 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..5f1bd226 100644 --- a/src/js/game/hud/hud.js +++ b/src/js/game/hud/hud.js @@ -1,274 +1,289 @@ -/* 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 } 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"; +import { HUDBetaOverlay } from "./parts/beta_overlay"; +import { HUDStandaloneAdvantages } from "./parts/standalone_advantages"; +import { HUDCatMemes } from "./parts/cat_memes"; +import { HUDTutorialVideoOffer } from "./parts/tutorial_video_offer"; + +export class GameHUD { + /** + * @param {GameRoot} root + */ + constructor(root) { + this.root = root; + } + + /** + * Initializes the hud parts + */ + initialize() { + 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()), + unlockNotificationFinished: /** @type {TypedSignal<[]>} */ (new Signal()), + }; + + 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), + 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), + tutorialVideoOffer: new HUDTutorialVideoOffer(this.root), + + // Typing hints + /* typehints:start */ + /** @type {HUDChangesDebugger} */ + changesDebugger: null, + /* typehints:end */ + }; + + 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 (this.root.app.restrictionMgr.getIsStandaloneMarketingActive()) { + this.parts.watermark = new HUDWatermark(this.root); + this.parts.standaloneAdvantages = new HUDStandaloneAdvantages(this.root); + this.parts.catMemes = new HUDCatMemes(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); + } + + if (!G_IS_RELEASE && !G_IS_DEV) { + this.parts.betaOverlay = new HUDBetaOverlay(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() { + 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/base_toolbar.js b/src/js/game/hud/parts/base_toolbar.js index f5ec24c6..a0e2a49f 100644 --- a/src/js/game/hud/parts/base_toolbar.js +++ b/src/js/game/hud/parts/base_toolbar.js @@ -1,177 +1,228 @@ -import { gMetaBuildingRegistry } from "../../../core/global_registries"; -import { Signal, STOP_PROPAGATION } from "../../../core/signal"; -import { makeDiv } from "../../../core/utils"; -import { KEYMAPPINGS } from "../../key_action_mapper"; -import { MetaBuilding } from "../../meta_building"; -import { GameRoot } from "../../root"; -import { BaseHUDPart } from "../base_hud_part"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; - -export class HUDBaseToolbar extends BaseHUDPart { - /** - * @param {GameRoot} root - * @param {object} param0 - * @param {Array} param0.supportedBuildings - * @param {function} param0.visibilityCondition - * @param {string} param0.htmlElementId - */ - constructor(root, { supportedBuildings, visibilityCondition, htmlElementId }) { - super(root); - - this.supportedBuildings = supportedBuildings; - this.visibilityCondition = visibilityCondition; - this.htmlElementId = htmlElementId; - - /** @type {Object.} */ - this.buildingHandles = {}; - } - - /** - * Should create all require elements - * @param {HTMLElement} parent - */ - createElements(parent) { - this.element = makeDiv(parent, this.htmlElementId, ["ingame_buildingsToolbar"], ""); - } - - initialize() { - const actionMapper = this.root.keyMapper; - - const items = makeDiv(this.element, null, ["buildings"]); - - for (let i = 0; i < this.supportedBuildings.length; ++i) { - const metaBuilding = gMetaBuildingRegistry.findByClass(this.supportedBuildings[i]); - const binding = actionMapper.getBinding(KEYMAPPINGS.buildings[metaBuilding.getId()]); - - const itemContainer = makeDiv(items, null, ["building"]); - itemContainer.setAttribute("data-icon", "building_icons/" + metaBuilding.getId() + ".png"); - - binding.add(() => this.selectBuildingForPlacement(metaBuilding)); - - this.trackClicks(itemContainer, () => this.selectBuildingForPlacement(metaBuilding), { - clickSound: null, - }); - - this.buildingHandles[metaBuilding.id] = { - metaBuilding, - element: itemContainer, - unlocked: false, - selected: false, - index: i, - }; - } - - this.root.hud.signals.selectedPlacementBuildingChanged.add( - this.onSelectedPlacementBuildingChanged, - this - ); - - this.domAttach = new DynamicDomAttach(this.root, this.element, { - timeToKeepSeconds: 0.12, - attachClass: "visible", - }); - this.lastSelectedIndex = 0; - actionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildings).add(this.cycleBuildings, this); - } - - /** - * Updates the toolbar - */ - update() { - const visible = this.visibilityCondition(); - this.domAttach.update(visible); - - if (visible) { - for (const buildingId in this.buildingHandles) { - const handle = this.buildingHandles[buildingId]; - const newStatus = handle.metaBuilding.getIsUnlocked(this.root); - if (handle.unlocked !== newStatus) { - handle.unlocked = newStatus; - handle.element.classList.toggle("unlocked", newStatus); - } - } - } - } - - /** - * Cycles through all buildings - */ - cycleBuildings() { - const visible = this.visibilityCondition(); - if (!visible) { - return; - } - - let newBuildingFound = false; - let newIndex = this.lastSelectedIndex; - for (let i = 0; i < this.supportedBuildings.length; ++i, ++newIndex) { - newIndex %= this.supportedBuildings.length; - const metaBuilding = gMetaBuildingRegistry.findByClass(this.supportedBuildings[newIndex]); - const handle = this.buildingHandles[metaBuilding.id]; - if (!handle.selected && handle.unlocked) { - newBuildingFound = true; - break; - } - } - if (!newBuildingFound) { - return; - } - const metaBuildingClass = this.supportedBuildings[newIndex]; - const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass); - this.selectBuildingForPlacement(metaBuilding); - } - - /** - * Called when the selected building got changed - * @param {MetaBuilding} metaBuilding - */ - onSelectedPlacementBuildingChanged(metaBuilding) { - for (const buildingId in this.buildingHandles) { - const handle = this.buildingHandles[buildingId]; - const newStatus = handle.metaBuilding === metaBuilding; - if (handle.selected !== newStatus) { - handle.selected = newStatus; - handle.element.classList.toggle("selected", newStatus); - } - if (handle.selected) { - this.lastSelectedIndex = handle.index; - } - } - - this.element.classList.toggle("buildingSelected", !!metaBuilding); - } - - /** - * @param {MetaBuilding} metaBuilding - */ - selectBuildingForPlacement(metaBuilding) { - if (!this.visibilityCondition()) { - // Not active - return; - } - - if (!metaBuilding.getIsUnlocked(this.root)) { - this.root.soundProxy.playUiError(); - return STOP_PROPAGATION; - } - - // Allow clicking an item again to deselect it - for (const buildingId in this.buildingHandles) { - const handle = this.buildingHandles[buildingId]; - if (handle.selected && handle.metaBuilding === metaBuilding) { - metaBuilding = null; - break; - } - } - - this.root.soundProxy.playUiClick(); - this.root.hud.signals.buildingSelectedForPlacement.dispatch(metaBuilding); - this.onSelectedPlacementBuildingChanged(metaBuilding); - } -} +import { gMetaBuildingRegistry } from "../../../core/global_registries"; +import { Signal, STOP_PROPAGATION } from "../../../core/signal"; +import { makeDiv } from "../../../core/utils"; +import { KEYMAPPINGS } from "../../key_action_mapper"; +import { MetaBuilding } from "../../meta_building"; +import { GameRoot } from "../../root"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; + +export class HUDBaseToolbar extends BaseHUDPart { + /** + * @param {GameRoot} root + * @param {object} param0 + * @param {Array} param0.primaryBuildings + * @param {Array=} param0.secondaryBuildings + * @param {function} param0.visibilityCondition + * @param {string} param0.htmlElementId + * @param {Layer=} param0.layer + */ + constructor( + root, + { primaryBuildings, secondaryBuildings = [], visibilityCondition, htmlElementId, layer = "regular" } + ) { + super(root); + + this.primaryBuildings = primaryBuildings; + this.secondaryBuildings = secondaryBuildings; + this.visibilityCondition = visibilityCondition; + this.htmlElementId = htmlElementId; + this.layer = layer; + + /** @type {Object.} */ + this.buildingHandles = {}; + } + + /** + * Should create all require elements + * @param {HTMLElement} parent + */ + createElements(parent) { + this.element = makeDiv(parent, this.htmlElementId, ["ingame_buildingsToolbar"], ""); + } + + /** + * Returns all buildings + * @returns {Array} + */ + get allBuildings() { + return [...this.primaryBuildings, ...this.secondaryBuildings]; + } + + initialize() { + const actionMapper = this.root.keyMapper; + let rowSecondary; + if (this.secondaryBuildings.length > 0) { + rowSecondary = makeDiv(this.element, null, ["buildings", "secondary"]); + + this.secondaryDomAttach = new DynamicDomAttach(this.root, rowSecondary, { + attachClass: "visible", + }); + } + + const rowPrimary = makeDiv(this.element, null, ["buildings", "primary"]); + + const allBuildings = this.allBuildings; + + for (let i = 0; i < allBuildings.length; ++i) { + const metaBuilding = gMetaBuildingRegistry.findByClass(allBuildings[i]); + + let rawBinding = KEYMAPPINGS.buildings[metaBuilding.getId() + "_" + this.layer]; + if (!rawBinding) { + rawBinding = KEYMAPPINGS.buildings[metaBuilding.getId()]; + } + + const binding = actionMapper.getBinding(rawBinding); + + const itemContainer = makeDiv( + this.primaryBuildings.includes(allBuildings[i]) ? rowPrimary : rowSecondary, + null, + ["building"] + ); + itemContainer.setAttribute("data-icon", "building_icons/" + metaBuilding.getId() + ".png"); + itemContainer.setAttribute("data-id", metaBuilding.getId()); + + binding.add(() => this.selectBuildingForPlacement(metaBuilding)); + + this.trackClicks(itemContainer, () => this.selectBuildingForPlacement(metaBuilding), { + clickSound: null, + }); + + this.buildingHandles[metaBuilding.id] = { + metaBuilding, + element: itemContainer, + unlocked: false, + selected: false, + index: i, + }; + } + + this.root.hud.signals.selectedPlacementBuildingChanged.add( + this.onSelectedPlacementBuildingChanged, + this + ); + + this.domAttach = new DynamicDomAttach(this.root, this.element, { + timeToKeepSeconds: 0.12, + attachClass: "visible", + }); + this.lastSelectedIndex = 0; + actionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildings).add(this.cycleBuildings, this); + } + + /** + * Updates the toolbar + */ + update() { + const visible = this.visibilityCondition(); + this.domAttach.update(visible); + + if (visible) { + let recomputeSecondaryToolbarVisibility = false; + for (const buildingId in this.buildingHandles) { + const handle = this.buildingHandles[buildingId]; + const newStatus = handle.metaBuilding.getIsUnlocked(this.root); + if (handle.unlocked !== newStatus) { + handle.unlocked = newStatus; + handle.element.classList.toggle("unlocked", newStatus); + recomputeSecondaryToolbarVisibility = true; + } + } + + if (recomputeSecondaryToolbarVisibility && this.secondaryDomAttach) { + let anyUnlocked = false; + for (let i = 0; i < this.secondaryBuildings.length; ++i) { + const metaClass = gMetaBuildingRegistry.findByClass(this.secondaryBuildings[i]); + if (metaClass.getIsUnlocked(this.root)) { + anyUnlocked = true; + break; + } + } + + this.secondaryDomAttach.update(anyUnlocked); + } + } + } + + /** + * Cycles through all buildings + */ + cycleBuildings() { + const visible = this.visibilityCondition(); + if (!visible) { + return; + } + + let newBuildingFound = false; + let newIndex = this.lastSelectedIndex; + for (let i = 0; i < this.primaryBuildings.length; ++i, ++newIndex) { + newIndex %= this.primaryBuildings.length; + const metaBuilding = gMetaBuildingRegistry.findByClass(this.primaryBuildings[newIndex]); + const handle = this.buildingHandles[metaBuilding.id]; + if (!handle.selected && handle.unlocked) { + newBuildingFound = true; + break; + } + } + if (!newBuildingFound) { + return; + } + const metaBuildingClass = this.primaryBuildings[newIndex]; + const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass); + this.selectBuildingForPlacement(metaBuilding); + } + + /** + * Called when the selected building got changed + * @param {MetaBuilding} metaBuilding + */ + onSelectedPlacementBuildingChanged(metaBuilding) { + for (const buildingId in this.buildingHandles) { + const handle = this.buildingHandles[buildingId]; + const newStatus = handle.metaBuilding === metaBuilding; + if (handle.selected !== newStatus) { + handle.selected = newStatus; + handle.element.classList.toggle("selected", newStatus); + } + if (handle.selected) { + this.lastSelectedIndex = handle.index; + } + } + + this.element.classList.toggle("buildingSelected", !!metaBuilding); + } + + /** + * @param {MetaBuilding} metaBuilding + */ + selectBuildingForPlacement(metaBuilding) { + if (!this.visibilityCondition()) { + // Not active + return; + } + + if (!metaBuilding.getIsUnlocked(this.root)) { + this.root.soundProxy.playUiError(); + return STOP_PROPAGATION; + } + + // Allow clicking an item again to deselect it + for (const buildingId in this.buildingHandles) { + const handle = this.buildingHandles[buildingId]; + if (handle.selected && handle.metaBuilding === metaBuilding) { + metaBuilding = null; + break; + } + } + + this.root.soundProxy.playUiClick(); + this.root.hud.signals.buildingSelectedForPlacement.dispatch(metaBuilding); + this.onSelectedPlacementBuildingChanged(metaBuilding); + } +} diff --git a/src/js/game/hud/parts/beta_overlay.js b/src/js/game/hud/parts/beta_overlay.js index 517a15b7..3a515d29 100644 --- a/src/js/game/hud/parts/beta_overlay.js +++ b/src/js/game/hud/parts/beta_overlay.js @@ -3,7 +3,12 @@ import { makeDiv } from "../../../core/utils"; export class HUDBetaOverlay extends BaseHUDPart { createElements(parent) { - this.element = makeDiv(parent, "ingame_HUD_BetaOverlay", [], "CLOSED BETA"); + this.element = makeDiv( + parent, + "ingame_HUD_BetaOverlay", + [], + "

UNSTABLE BETA VERSION

Unfinalized & potential buggy content!" + ); } initialize() {} diff --git a/src/js/game/hud/parts/blueprint_placer.js b/src/js/game/hud/parts/blueprint_placer.js index 38341395..e1040c3b 100644 --- a/src/js/game/hud/parts/blueprint_placer.js +++ b/src/js/game/hud/parts/blueprint_placer.js @@ -1,203 +1,203 @@ -import { DrawParameters } from "../../../core/draw_parameters"; -import { STOP_PROPAGATION } from "../../../core/signal"; -import { TrackedState } from "../../../core/tracked_state"; -import { makeDiv } from "../../../core/utils"; -import { Vector } from "../../../core/vector"; -import { T } from "../../../translations"; -import { enumMouseButton } from "../../camera"; -import { KEYMAPPINGS } from "../../key_action_mapper"; -import { blueprintShape } from "../../upgrades"; -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) { - const blueprintCostShape = this.root.shapeDefinitionMgr.getShapeFromShortKey(blueprintShape); - const blueprintCostShapeCanvas = blueprintCostShape.generateAsCanvas(80); - - this.costDisplayParent = makeDiv(parent, "ingame_HUD_BlueprintPlacer", [], ``); - - makeDiv(this.costDisplayParent, null, ["label"], T.ingame.blueprintPlacer.cost); - const costContainer = makeDiv(this.costDisplayParent, null, ["costContainer"], ""); - this.costDisplayText = makeDiv(costContainer, null, ["costText"], ""); - costContainer.appendChild(blueprintCostShapeCanvas); - } - - initialize() { - this.root.hud.signals.buildingsSelectedForCopy.add(this.createBlueprintFromBuildings, this); - - /** @type {TypedTrackedState} */ - this.currentBlueprint = new TrackedState(this.onBlueprintChanged, this); - /** @type {Blueprint?} */ - this.lastBlueprintUsed = null; - - const keyActionMapper = this.root.keyMapper; - keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this); - keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.abortPlacement, this); - keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this); - keyActionMapper.getBinding(KEYMAPPINGS.massSelect.pasteLastBlueprint).add(this.pasteBlueprint, this); - - this.root.camera.downPreHandler.add(this.onMouseDown, this); - this.root.camera.movePreHandler.add(this.onMouseMove, this); - - this.root.hud.signals.selectedPlacementBuildingChanged.add(this.abortPlacement, this); - this.root.signals.editModeChanged.add(this.onEditModeChanged, this); - - this.domAttach = new DynamicDomAttach(this.root, this.costDisplayParent); - this.trackedCanAfford = new TrackedState(this.onCanAffordChanged, this); - } - - abortPlacement() { - if (this.currentBlueprint.get()) { - this.currentBlueprint.set(null); - - return STOP_PROPAGATION; - } - } - - /** - * Called when the layer was changed - * @param {enumLayer} layer - */ - onEditModeChanged(layer) { - // Check if the layer of the blueprint differs and thus we have to deselect it - const blueprint = this.currentBlueprint.get(); - if (blueprint) { - if (blueprint.layer !== layer) { - this.currentBlueprint.set(null); - } - } - } - - /** - * Called when the blueprint is now affordable or not - * @param {boolean} canAfford - */ - onCanAffordChanged(canAfford) { - this.costDisplayParent.classList.toggle("canAfford", canAfford); - } - - update() { - const currentBlueprint = this.currentBlueprint.get(); - this.domAttach.update(currentBlueprint && currentBlueprint.getCost() > 0); - this.trackedCanAfford.set(currentBlueprint && currentBlueprint.canAfford(this.root)); - } - - /** - * Called when the blueprint was changed - * @param {Blueprint} blueprint - */ - onBlueprintChanged(blueprint) { - if (blueprint) { - this.lastBlueprintUsed = blueprint; - this.costDisplayText.innerText = "" + blueprint.getCost(); - } - } - - /** - * mouse down pre handler - * @param {Vector} pos - * @param {enumMouseButton} button - */ - onMouseDown(pos, button) { - if (button === enumMouseButton.right) { - if (this.currentBlueprint.get()) { - this.abortPlacement(); - return STOP_PROPAGATION; - } - } - - const blueprint = this.currentBlueprint.get(); - if (!blueprint) { - return; - } - - if (!blueprint.canAfford(this.root)) { - this.root.soundProxy.playUiError(); - return; - } - - const worldPos = this.root.camera.screenToWorld(pos); - const tile = worldPos.toTileSpace(); - if (blueprint.tryPlace(this.root, tile)) { - const cost = blueprint.getCost(); - this.root.hubGoals.takeShapeByKey(blueprintShape, cost); - this.root.soundProxy.playUi(SOUNDS.placeBuilding); - } - } - - /** - * Mose move handler - */ - onMouseMove() { - // Prevent movement while blueprint is selected - if (this.currentBlueprint.get()) { - return STOP_PROPAGATION; - } - } - - /** - * Called when an array of bulidings was selected - * @param {Array} uids - */ - createBlueprintFromBuildings(uids) { - if (uids.length === 0) { - return; - } - this.currentBlueprint.set(Blueprint.fromUids(this.root, uids)); - } - - /** - * Attempts to rotate the current blueprint - */ - rotateBlueprint() { - if (this.currentBlueprint.get()) { - if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).pressed) { - this.currentBlueprint.get().rotateCcw(); - } else { - this.currentBlueprint.get().rotateCw(); - } - } - } - - /** - * Attempts to paste the last blueprint - */ - pasteBlueprint() { - if (this.lastBlueprintUsed !== null) { - if (this.lastBlueprintUsed.layer !== this.root.currentLayer) { - // Not compatible - this.root.soundProxy.playUiError(); - return; - } - - this.root.hud.signals.pasteBlueprintRequested.dispatch(); - this.currentBlueprint.set(this.lastBlueprintUsed); - } else { - this.root.soundProxy.playUiError(); - } - } - - /** - * - * @param {DrawParameters} parameters - */ - draw(parameters) { - const blueprint = this.currentBlueprint.get(); - if (!blueprint) { - return; - } - const mousePosition = this.root.app.mousePosition; - if (!mousePosition) { - // Not on screen - return; - } - - const worldPos = this.root.camera.screenToWorld(mousePosition); - const tile = worldPos.toTileSpace(); - blueprint.draw(parameters, tile); - } -} +import { DrawParameters } from "../../../core/draw_parameters"; +import { STOP_PROPAGATION } from "../../../core/signal"; +import { TrackedState } from "../../../core/tracked_state"; +import { makeDiv } from "../../../core/utils"; +import { Vector } from "../../../core/vector"; +import { SOUNDS } from "../../../platform/sound"; +import { T } from "../../../translations"; +import { Blueprint } from "../../blueprint"; +import { enumMouseButton } from "../../camera"; +import { KEYMAPPINGS } from "../../key_action_mapper"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; + +export class HUDBlueprintPlacer extends BaseHUDPart { + createElements(parent) { + const blueprintCostShape = this.root.shapeDefinitionMgr.getShapeFromShortKey( + this.root.gameMode.getBlueprintShapeKey() + ); + const blueprintCostShapeCanvas = blueprintCostShape.generateAsCanvas(80); + + this.costDisplayParent = makeDiv(parent, "ingame_HUD_BlueprintPlacer", [], ``); + + makeDiv(this.costDisplayParent, null, ["label"], T.ingame.blueprintPlacer.cost); + const costContainer = makeDiv(this.costDisplayParent, null, ["costContainer"], ""); + this.costDisplayText = makeDiv(costContainer, null, ["costText"], ""); + costContainer.appendChild(blueprintCostShapeCanvas); + } + + initialize() { + this.root.hud.signals.buildingsSelectedForCopy.add(this.createBlueprintFromBuildings, this); + + /** @type {TypedTrackedState} */ + this.currentBlueprint = new TrackedState(this.onBlueprintChanged, this); + /** @type {Blueprint?} */ + this.lastBlueprintUsed = null; + + const keyActionMapper = this.root.keyMapper; + keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this); + keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.abortPlacement, this); + keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this); + keyActionMapper.getBinding(KEYMAPPINGS.massSelect.pasteLastBlueprint).add(this.pasteBlueprint, this); + + this.root.camera.downPreHandler.add(this.onMouseDown, this); + this.root.camera.movePreHandler.add(this.onMouseMove, this); + + this.root.hud.signals.selectedPlacementBuildingChanged.add(this.abortPlacement, this); + this.root.signals.editModeChanged.add(this.onEditModeChanged, this); + + this.domAttach = new DynamicDomAttach(this.root, this.costDisplayParent); + this.trackedCanAfford = new TrackedState(this.onCanAffordChanged, this); + } + + abortPlacement() { + if (this.currentBlueprint.get()) { + this.currentBlueprint.set(null); + + return STOP_PROPAGATION; + } + } + + /** + * Called when the layer was changed + * @param {Layer} layer + */ + onEditModeChanged(layer) { + // Check if the layer of the blueprint differs and thus we have to deselect it + const blueprint = this.currentBlueprint.get(); + if (blueprint) { + if (blueprint.layer !== layer) { + this.currentBlueprint.set(null); + } + } + } + + /** + * Called when the blueprint is now affordable or not + * @param {boolean} canAfford + */ + onCanAffordChanged(canAfford) { + this.costDisplayParent.classList.toggle("canAfford", canAfford); + } + + update() { + const currentBlueprint = this.currentBlueprint.get(); + this.domAttach.update(currentBlueprint && currentBlueprint.getCost() > 0); + this.trackedCanAfford.set(currentBlueprint && currentBlueprint.canAfford(this.root)); + } + + /** + * Called when the blueprint was changed + * @param {Blueprint} blueprint + */ + onBlueprintChanged(blueprint) { + if (blueprint) { + this.lastBlueprintUsed = blueprint; + this.costDisplayText.innerText = "" + blueprint.getCost(); + } + } + + /** + * mouse down pre handler + * @param {Vector} pos + * @param {enumMouseButton} button + */ + onMouseDown(pos, button) { + if (button === enumMouseButton.right) { + if (this.currentBlueprint.get()) { + this.abortPlacement(); + return STOP_PROPAGATION; + } + } + + const blueprint = this.currentBlueprint.get(); + if (!blueprint) { + return; + } + + if (!blueprint.canAfford(this.root)) { + this.root.soundProxy.playUiError(); + return; + } + + const worldPos = this.root.camera.screenToWorld(pos); + const tile = worldPos.toTileSpace(); + if (blueprint.tryPlace(this.root, tile)) { + const cost = blueprint.getCost(); + this.root.hubGoals.takeShapeByKey(this.root.gameMode.getBlueprintShapeKey(), cost); + this.root.soundProxy.playUi(SOUNDS.placeBuilding); + } + } + + /** + * Mose move handler + */ + onMouseMove() { + // Prevent movement while blueprint is selected + if (this.currentBlueprint.get()) { + return STOP_PROPAGATION; + } + } + + /** + * Called when an array of bulidings was selected + * @param {Array} uids + */ + createBlueprintFromBuildings(uids) { + if (uids.length === 0) { + return; + } + this.currentBlueprint.set(Blueprint.fromUids(this.root, uids)); + } + + /** + * Attempts to rotate the current blueprint + */ + rotateBlueprint() { + if (this.currentBlueprint.get()) { + if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).pressed) { + this.currentBlueprint.get().rotateCcw(); + } else { + this.currentBlueprint.get().rotateCw(); + } + } + } + + /** + * Attempts to paste the last blueprint + */ + pasteBlueprint() { + if (this.lastBlueprintUsed !== null) { + if (this.lastBlueprintUsed.layer !== this.root.currentLayer) { + // Not compatible + this.root.soundProxy.playUiError(); + return; + } + + this.root.hud.signals.pasteBlueprintRequested.dispatch(); + this.currentBlueprint.set(this.lastBlueprintUsed); + } else { + this.root.soundProxy.playUiError(); + } + } + + /** + * + * @param {DrawParameters} parameters + */ + draw(parameters) { + const blueprint = this.currentBlueprint.get(); + if (!blueprint) { + return; + } + const mousePosition = this.root.app.mousePosition; + if (!mousePosition) { + // Not on screen + return; + } + + const worldPos = this.root.camera.screenToWorld(mousePosition); + const tile = worldPos.toTileSpace(); + blueprint.draw(parameters, tile); + } +} diff --git a/src/js/game/hud/parts/building_placer.js b/src/js/game/hud/parts/building_placer.js index d3a3c7ac..7dccb7a4 100644 --- a/src/js/game/hud/parts/building_placer.js +++ b/src/js/game/hud/parts/building_placer.js @@ -1,580 +1,618 @@ -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 layer = this.root.currentLayer; + + let rawBinding = KEYMAPPINGS.buildings[metaBuilding.getId() + "_" + layer]; + if (!rawBinding) { + rawBinding = KEYMAPPINGS.buildings[metaBuilding.getId()]; + } + + const binding = this.root.keyMapper.getBinding(rawBinding); + + 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 ae496790..a7aa9fd1 100644 --- a/src/js/game/hud/parts/building_placer_logic.js +++ b/src/js/game/hud/parts/building_placer_logic.js @@ -12,7 +12,8 @@ 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"; +import { getBuildingDataFromCode, getCodeFromBuildingData } from "../../building_codes"; +import { MetaHubBuilding } from "../../buildings/hub"; /** * Contains all logic for the building placer - this doesn't include the rendering @@ -120,6 +121,7 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { 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.storyGoalCompleted.add(() => this.currentMetaBuilding.set(null)); this.root.signals.upgradePurchased.add(() => this.signals.variantChanged.dispatch()); this.root.signals.editModeChanged.add(this.onEditModeChanged, this); @@ -131,12 +133,12 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { /** * Called when the edit mode got changed - * @param {enumLayer} editMode + * @param {Layer} layer */ - onEditModeChanged(editMode) { + onEditModeChanged(layer) { const metaBuilding = this.currentMetaBuilding.get(); if (metaBuilding) { - if (metaBuilding.getLayer() !== editMode) { + if (metaBuilding.getLayer() !== layer) { // This layer doesn't fit the edit mode anymore this.currentMetaBuilding.set(null); } @@ -252,6 +254,12 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { * @see BaseHUDPart.update */ update() { + // Abort placement if a dialog was shown in the meantime + if (this.root.hud.hasBlockingOverlayOpen()) { + this.abortPlacement(); + return; + } + // Always update since the camera might have moved const mousePos = this.root.app.mousePosition; if (mousePos) { @@ -288,7 +296,7 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { const mousePosition = this.root.app.mousePosition; if (!mousePosition) { // Not on screen - return; + return false; } const worldPos = this.root.camera.screenToWorld(mousePosition); @@ -297,8 +305,10 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { if (contents) { if (this.root.logic.tryDeleteBuilding(contents)) { this.root.soundProxy.playUi(SOUNDS.destroyBuilding); + return true; } } + return false; } /** @@ -324,10 +334,14 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { 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) { + if ( + tileBelow && + this.root.app.settings.getAllSettings().pickMinerOnPatch && + this.root.currentLayer === "regular" + ) { this.currentMetaBuilding.set(gMetaBuildingRegistry.findByClass(MetaMinerBuilding)); - // Select chained miner if available, since thats always desired once unlocked + // Select chained miner if available, since that's always desired once unlocked if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_miner_chainable)) { this.currentVariant.set(enumMinerVariants.chainable); } @@ -338,101 +352,33 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { } // Try to extract the building - const extracted = this.hack_reconstructMetaBuildingAndVariantFromBuilding(contents); + 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 ( - !extracted || - (extracted.metaBuilding === this.currentMetaBuilding.get() && - extracted.variant === this.currentVariant.get()) + this.currentMetaBuilding.get() && + extracted.metaInstance.getId() === this.currentMetaBuilding.get().getId() && + extracted.variant === this.currentVariant.get() ) { this.currentMetaBuilding.set(null); return; } - this.currentMetaBuilding.set(extracted.metaBuilding); + this.currentMetaBuilding.set(extracted.metaInstance); 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 }} + * Switches the side for the direction lock manually */ - 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; } @@ -516,11 +462,11 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { 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 - ); + let index = availableVariants.indexOf(this.currentVariant.get()); + if (index < 0) { + index = 0; + console.warn("Invalid variant selected:", this.currentVariant.get()); + } const newIndex = (index + 1) % availableVariants.length; const newVariant = availableVariants[newIndex]; this.setVariant(newVariant); @@ -654,7 +600,17 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { this.abortDragging(); this.root.hud.signals.selectedPlacementBuildingChanged.dispatch(metaBuilding); if (metaBuilding) { - const variant = this.preferredVariants[metaBuilding.getId()] || defaultBuildingVariant; + const availableVariants = metaBuilding.getAvailableVariants(this.root); + const preferredVariant = this.preferredVariants[metaBuilding.getId()]; + + // Choose last stored variant if possible, otherwise the default one + let variant; + if (!preferredVariant || !availableVariants.includes(preferredVariant)) { + variant = availableVariants[0]; + } else { + variant = preferredVariant; + } + this.currentVariant.set(variant); this.fakeEntity = new Entity(null); @@ -665,7 +621,7 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { origin: new Vector(0, 0), rotation: 0, tileSize: metaBuilding.getDimensions(this.currentVariant.get()).copy(), - blueprintSpriteKey: "", + code: getCodeFromBuildingData(metaBuilding, variant, 0), }) ); metaBuilding.updateVariants(this.fakeEntity, 0, this.currentVariant.get()); @@ -708,13 +664,14 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { // Deletion if ( button === enumMouseButton.right && - (!metaBuilding || this.root.app.settings.getSetting("canDeleteWhileBuilding")) + (!metaBuilding || !this.root.app.settings.getAllSettings().clearCursorOnDeleteWhilePlacing) ) { this.currentlyDragging = true; this.currentlyDeleting = true; this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace(); - this.deleteBelowCursor(); - return STOP_PROPAGATION; + if (this.deleteBelowCursor()) { + return STOP_PROPAGATION; + } } // Cancel placement diff --git a/src/js/game/hud/parts/buildings_toolbar.js b/src/js/game/hud/parts/buildings_toolbar.js index c46a5c98..05ffc795 100644 --- a/src/js/game/hud/parts/buildings_toolbar.js +++ b/src/js/game/hud/parts/buildings_toolbar.js @@ -1,41 +1,48 @@ -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 { MetaBeltBuilding } from "../../buildings/belt"; +import { MetaCutterBuilding } from "../../buildings/cutter"; +import { MetaDisplayBuilding } from "../../buildings/display"; +import { MetaFilterBuilding } from "../../buildings/filter"; +import { MetaLeverBuilding } from "../../buildings/lever"; +import { MetaMinerBuilding } from "../../buildings/miner"; +import { MetaMixerBuilding } from "../../buildings/mixer"; +import { MetaPainterBuilding } from "../../buildings/painter"; +import { MetaReaderBuilding } from "../../buildings/reader"; +import { MetaRotaterBuilding } from "../../buildings/rotater"; +import { MetaBalancerBuilding } from "../../buildings/balancer"; +import { MetaStackerBuilding } from "../../buildings/stacker"; +import { MetaTrashBuilding } from "../../buildings/trash"; +import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt"; +import { HUDBaseToolbar } from "./base_toolbar"; +import { MetaStorageBuilding } from "../../buildings/storage"; +import { MetaItemProducerBuilding } from "../../buildings/item_producer"; +import { queryParamOptions } from "../../../core/query_parameters"; + +export class HUDBuildingsToolbar extends HUDBaseToolbar { + constructor(root) { + super(root, { + primaryBuildings: [ + MetaBeltBuilding, + MetaBalancerBuilding, + MetaUndergroundBeltBuilding, + MetaMinerBuilding, + MetaCutterBuilding, + MetaRotaterBuilding, + MetaStackerBuilding, + MetaMixerBuilding, + MetaPainterBuilding, + MetaTrashBuilding, + ...(queryParamOptions.sandboxMode || G_IS_DEV ? [MetaItemProducerBuilding] : []), + ], + secondaryBuildings: [ + MetaStorageBuilding, + MetaReaderBuilding, + MetaLeverBuilding, + MetaFilterBuilding, + MetaDisplayBuilding, + ], + visibilityCondition: () => + !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "regular", + htmlElementId: "ingame_HUD_BuildingsToolbar", + }); + } +} diff --git a/src/js/game/hud/parts/cat_memes.js b/src/js/game/hud/parts/cat_memes.js new file mode 100644 index 00000000..f3af2be4 --- /dev/null +++ b/src/js/game/hud/parts/cat_memes.js @@ -0,0 +1,21 @@ +import { makeDiv } from "../../../core/utils"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; + +const memeShowIntervalSeconds = 70 * 60; +const memeShowDuration = 5; + +export class HUDCatMemes extends BaseHUDPart { + createElements(parent) { + this.element = makeDiv(parent, "ingame_HUD_CatMemes"); + } + + initialize() { + this.domAttach = new DynamicDomAttach(this.root, this.element); + } + + update() { + const now = this.root.time.realtimeNow(); + this.domAttach.update(now % memeShowIntervalSeconds > memeShowIntervalSeconds - memeShowDuration); + } +} 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..640ad4d6 100644 --- a/src/js/game/hud/parts/entity_debugger.js +++ b/src/js/game/hud/parts/entity_debugger.js @@ -1,7 +1,13 @@ -import { BaseHUDPart } from "../base_hud_part"; +/* dev:start */ import { makeDiv, removeAllChildren } from "../../../core/utils"; -import { globalConfig } from "../../../core/config"; +import { Vector } from "../../../core/vector"; +import { Entity } from "../../entity"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; +/** + * Allows to inspect entities by pressing F8 while hovering them + */ export class HUDEntityDebugger extends BaseHUDPart { createElements(parent) { this.element = makeDiv( @@ -9,63 +15,147 @@ export class HUDEntityDebugger extends BaseHUDPart { "ingame_HUD_EntityDebugger", [], ` - Tile below cursor:
- Chunk below cursor:
-
+ + Use F8 to toggle this overlay + +
+
+
` ); - - this.mousePosElem = this.element.querySelector(".mousePos"); - this.chunkPosElem = this.element.querySelector(".chunkPos"); - this.entityInfoElem = this.element.querySelector(".entityInfo"); + this.componentsElem = this.element.querySelector(".entityComponents"); } initialize() { - this.root.camera.downPreHandler.add(this.onMouseDown, this); + this.root.gameState.inputReciever.keydown.add(key => { + if (key.keyCode === 119) { + // F8 + this.pickEntity(); + } + }); + + /** + * The currently selected entity + * @type {Entity} + */ + this.selectedEntity = null; + + this.lastUpdate = 0; + + this.domAttach = new DynamicDomAttach(this.root, this.element); } - update() { + pickEntity() { const mousePos = this.root.app.mousePosition; if (!mousePos) { return; } const worldPos = this.root.camera.screenToWorld(mousePos); const worldTile = worldPos.toTileSpace(); - - const chunk = worldTile.divideScalar(globalConfig.mapChunkSize).floor(); - this.mousePosElem.innerText = worldTile.x + " / " + worldTile.y; - this.chunkPosElem.innerText = chunk.x + " / " + chunk.y; - const entity = this.root.map.getTileContent(worldTile, this.root.currentLayer); + + this.selectedEntity = entity; if (entity) { - removeAllChildren(this.entityInfoElem); - let html = "Entity"; - - const flag = (name, val) => - `${name} ${val}`; - - html += "
"; - html += flag("registered", entity.registered); - html += flag("uid", entity.uid); - html += flag("destroyed", entity.destroyed); - html += "
"; - - html += "
"; - - for (const componentId in entity.components) { - const data = entity.components[componentId]; - html += "
"; - html += "" + componentId + ""; - html += ""; - - html += "
"; - } - - html += "
"; - - this.entityInfoElem.innerHTML = html; + this.rerenderFull(entity); } } - onMouseDown() {} + /** + * + * @param {string} name + * @param {any} val + * @param {number} indent + * @param {Array} recursion + */ + propertyToHTML(name, val, indent = 0, recursion = []) { + if (indent > 20) { + return; + } + + if (val !== null && typeof val === "object") { + // Array is displayed like object, with indexes + recursion.push(val); + + // Get type class name (like Array, Object, Vector...) + let typeName = `(${val.constructor ? val.constructor.name : "unknown"})`; + + if (Array.isArray(val)) { + typeName = `(Array[${val.length}])`; + } + + if (val instanceof Vector) { + typeName = `(Vector[${val.x}, ${val.y}])`; + } + + const colorStyle = `color: hsl(${30 * indent}, 100%, 80%)`; + + let html = `
+ ${name} ${typeName} +
`; + + for (const property in val) { + const isRoot = val[property] == this.root; + const isRecursive = recursion.includes(val[property]); + + let hiddenValue = isRoot ? "" : null; + if (isRecursive) { + // Avoid recursion by not "expanding" object more than once + hiddenValue = ""; + } + + html += this.propertyToHTML( + property, + hiddenValue ? hiddenValue : val[property], + indent + 1, + [...recursion] // still expand same value in other "branches" + ); + } + + html += "
"; + + return html; + } + + const displayValue = (val + "") + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">"); + return ` ${displayValue}`; + } + + /** + * Rerenders the whole container + * @param {Entity} entity + */ + rerenderFull(entity) { + removeAllChildren(this.componentsElem); + let html = ""; + + const property = (strings, val) => ` ${val}`; + + html += property`registered ${!!entity.registered}`; + html += property`uid ${entity.uid}`; + html += property`destroyed ${!!entity.destroyed}`; + + for (const componentId in entity.components) { + const data = entity.components[componentId]; + html += "
"; + html += "" + componentId + "
"; + + for (const property in data) { + // Put entity into recursion list, so it won't get "expanded" + html += this.propertyToHTML(property, data[property], 0, [entity]); + } + + html += "
"; + } + + this.componentsElem.innerHTML = html; + } + + update() { + this.domAttach.update(!!this.selectedEntity); + } } + +/* dev:end */ diff --git a/src/js/game/hud/parts/game_menu.js b/src/js/game/hud/parts/game_menu.js index 64285624..2a172ab2 100644 --- a/src/js/game/hud/parts/game_menu.js +++ b/src/js/game/hud/parts/game_menu.js @@ -1,189 +1,174 @@ -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"; +import { TrackedState } from "../../../core/tracked_state"; + +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 = []; + + buttons.forEach(({ id, label, handler, keybinding, badge, notification, visible }) => { + const button = document.createElement("button"); + button.classList.add(id); + this.element.appendChild(button); + this.trackClicks(button, handler); + + if (keybinding) { + const binding = this.root.keyMapper.getBinding(keybinding); + binding.add(handler); + } + + 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, + }); + } + }); + + this.saveButton = makeDiv(this.element, null, ["button", "save", "animEven"]); + this.settingsButton = makeDiv(this.element, null, ["button", "settings"]); + + this.trackClicks(this.saveButton, this.startSave); + this.trackClicks(this.settingsButton, this.openSettings); + } + + initialize() { + this.root.signals.gameSaved.add(this.onGameSaved, this); + + this.trackedIsSaving = new TrackedState(this.onIsSavingChanged, this); + } + + update() { + let playSound = false; + let notifications = new Set(); + + // Check whether we are saving + this.trackedIsSaving.set(!!this.root.gameState.currentSavePromise); + + // 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); + }); + } + + onIsSavingChanged(isSaving) { + this.saveButton.classList.toggle("saving", isSaving); + } + + 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..e48a77fb 100644 --- a/src/js/game/hud/parts/interactive_tutorial.js +++ b/src/js/game/hud/parts/interactive_tutorial.js @@ -1,81 +1,185 @@ -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"; +import { enumItemProcessorTypes, ItemProcessorComponent } from "../../components/item_processor"; +import { ShapeItem } from "../../items/shape_item"; +import { WireComponent } from "../../components/wire"; +import { LeverComponent } from "../../components/lever"; + +// @todo: Make dictionary +const tutorialsByLevel = [ + // Level 1 + [ + // 1.1. place an extractor + { + id: "1_1_extractor", + condition: /** @param {GameRoot} root */ root => + root.entityMgr.getAllWithComponent(MinerComponent).length === 0, + }, + // 1.2. connect to hub + { + id: "1_2_conveyor", + condition: /** @param {GameRoot} root */ root => root.hubGoals.getCurrentGoalDelivered() === 0, + }, + // 1.3 wait for completion + { + id: "1_3_expand", + condition: () => true, + }, + ], + // Level 2 + [ + // 2.1 place a cutter + { + id: "2_1_place_cutter", + condition: /** @param {GameRoot} root */ root => + root.entityMgr + .getAllWithComponent(ItemProcessorComponent) + .filter(e => e.components.ItemProcessor.type === enumItemProcessorTypes.cutter).length === + 0, + }, + // 2.2 place trash + { + id: "2_2_place_trash", + condition: /** @param {GameRoot} root */ root => + root.entityMgr + .getAllWithComponent(ItemProcessorComponent) + .filter(e => e.components.ItemProcessor.type === enumItemProcessorTypes.trash).length === + 0, + }, + // 2.3 place more cutters + { + id: "2_3_more_cutters", + condition: /** @param {GameRoot} root */ root => + root.entityMgr + .getAllWithComponent(ItemProcessorComponent) + .filter(e => e.components.ItemProcessor.type === enumItemProcessorTypes.cutter).length < + 3, + }, + ], + + // Level 3 + [ + // 3.1. rectangles + { + id: "3_1_rectangles", + condition: /** @param {GameRoot} root */ root => + // 4 miners placed above rectangles and 10 delivered + root.hubGoals.getCurrentGoalDelivered() < 10 || + root.entityMgr.getAllWithComponent(MinerComponent).filter(entity => { + const tile = entity.components.StaticMapEntity.origin; + const below = root.map.getLowerLayerContentXY(tile.x, tile.y); + if (below && below.getItemType() === "shape") { + const shape = /** @type {ShapeItem} */ (below).definition.getHash(); + return shape === "RuRuRuRu"; + } + return false; + }).length < 4, + }, + ], + + [], // Level 4 + [], // Level 5 + [], // Level 6 + [], // Level 7 + [], // Level 8 + [], // Level 9 + [], // Level 10 + [], // Level 11 + [], // Level 12 + [], // Level 13 + [], // Level 14 + [], // Level 15 + [], // Level 16 + [], // Level 17 + [], // Level 18 + [], // Level 19 + [], // Level 20 + + // Level 21 + [ + // 21.1 place quad painter + { + id: "21_1_place_quad_painter", + condition: /** @param {GameRoot} root */ root => + root.entityMgr + .getAllWithComponent(ItemProcessorComponent) + .filter(e => e.components.ItemProcessor.type === enumItemProcessorTypes.painterQuad) + .length === 0, + }, + + // 21.2 switch to wires layer + { + id: "21_2_switch_to_wires", + condition: /** @param {GameRoot} root */ root => + root.entityMgr.getAllWithComponent(WireComponent).length < 5, + }, + + // 21.3 place button + { + id: "21_3_place_button", + condition: /** @param {GameRoot} root */ root => + root.entityMgr.getAllWithComponent(LeverComponent).length === 0, + }, + + // 21.4 activate button + { + id: "21_4_press_button", + condition: /** @param {GameRoot} root */ root => + root.entityMgr.getAllWithComponent(LeverComponent).some(e => !e.components.Lever.toggled), + }, + ], +]; + +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..65919d3c 100644 --- a/src/js/game/hud/parts/keybinding_overlay.js +++ b/src/js/game/hud/parts/keybinding_overlay.js @@ -1,323 +1,332 @@ -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 { enumHubGoalRewards } from "../../tutorial_goals"; +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, + }, + + { + // 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, + }, + + { + // Pipette + label: T.ingame.keybindingsOverlay.pipette, + keys: [k.placement.pipette], + condition: () => !this.mapOverviewActive && !this.blueprintPlacementActive, + }, + + { + // 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: () => + this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers), + }, + ]; + + 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 156318d8..92db15bd 100644 --- a/src/js/game/hud/parts/mass_selector.js +++ b/src/js/game/hud/parts/mass_selector.js @@ -21,8 +21,6 @@ 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(); @@ -50,6 +48,9 @@ export class HUDMassSelector extends BaseHUDPart { * @param {Entity} entity */ onEntityDestroyed(entity) { + if (this.root.bulkOperationRunning) { + return; + } this.selectedUids.delete(entity.uid); } @@ -92,14 +93,30 @@ export class HUDMassSelector extends BaseHUDPart { 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); + + // Build mapping from uid to entity + /** + * @type {Map} + */ + const mapUidToEntity = this.root.entityMgr.getFrozenUidSearchMap(); + + this.root.logic.performBulkOperation(() => { + for (let i = 0; i < entityUids.length; ++i) { + const uid = entityUids[i]; + const entity = mapUidToEntity.get(uid); + if (!entity) { + logger.error("Entity not found by uid:", uid); + continue; + } + + if (!this.root.logic.tryDeleteBuilding(entity)) { + logger.error("Error in mass delete, could not remove building"); + } } - } + }); + + // Clear uids later + this.selectedUids = new Set(); } startCopy() { @@ -278,10 +295,19 @@ export class HUDMassSelector extends BaseHUDPart { 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( 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..a0c6919d --- /dev/null +++ b/src/js/game/hud/parts/miner_highlight.js @@ -0,0 +1,176 @@ +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; + } + + const lowerContents = this.root.map.getLowerLayerContentXY(hoveredTile.x, hoveredTile.y); + if (!lowerContents) { + // Not connected + 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 tooltipLocation = 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( + tooltipLocation.x + 5 * scale, + tooltipLocation.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), + tooltipLocation.x + 10 * scale, + tooltipLocation.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)), + tooltipLocation.x + 10 * scale, + tooltipLocation.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) + ), + tooltipLocation.x + 10 * scale, + tooltipLocation.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/modal_dialogs.js b/src/js/game/hud/parts/modal_dialogs.js index 95428691..263b23dd 100644 --- a/src/js/game/hud/parts/modal_dialogs.js +++ b/src/js/game/hud/parts/modal_dialogs.js @@ -1,211 +1,215 @@ -/* typehints:start */ -import { Application } from "../../../application"; -/* typehints:end */ - -import { SOUNDS } from "../../../platform/sound"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; -import { BaseHUDPart } from "../base_hud_part"; -import { Dialog, DialogLoading, DialogOptionChooser } from "../../../core/modal_dialog_elements"; -import { makeDiv } from "../../../core/utils"; -import { T } from "../../../translations"; -import { THIRDPARTY_URLS } from "../../../core/config"; - -export class HUDModalDialogs extends BaseHUDPart { - constructor(root, app) { - // Important: Root is not always available here! Its also used in the main menu - super(root); - - /** @type {Application} */ - this.app = root ? root.app : app; - - this.dialogParent = null; - this.dialogStack = []; - } - - // For use inside of the game, implementation of base hud part - initialize() { - this.dialogParent = document.getElementById("ingame_HUD_ModalDialogs"); - this.domWatcher = new DynamicDomAttach(this.root, this.dialogParent); - } - - shouldPauseRendering() { - return this.dialogStack.length > 0; - } - - shouldPauseGame() { - return this.shouldPauseRendering(); - } - - createElements(parent) { - return makeDiv(parent, "ingame_HUD_ModalDialogs"); - } - - // For use outside of the game - initializeToElement(element) { - assert(element, "No element for dialogs given"); - this.dialogParent = element; - } - - // Methods - - /** - * @param {string} title - * @param {string} text - * @param {Array} buttons - */ - showInfo(title, text, buttons = ["ok:good"]) { - const dialog = new Dialog({ - app: this.app, - title: title, - contentHTML: text, - buttons: buttons, - type: "info", - }); - this.internalShowDialog(dialog); - - if (this.app) { - this.app.sound.playUiSound(SOUNDS.dialogOk); - } - - return dialog.buttonSignals; - } - - /** - * @param {string} title - * @param {string} text - * @param {Array} buttons - */ - showWarning(title, text, buttons = ["ok:good"]) { - const dialog = new Dialog({ - app: this.app, - title: title, - contentHTML: text, - buttons: buttons, - type: "warning", - }); - this.internalShowDialog(dialog); - - if (this.app) { - this.app.sound.playUiSound(SOUNDS.dialogError); - } - - return dialog.buttonSignals; - } - - /** - * @param {string} feature - * @param {string} textPrefab - */ - showFeatureRestrictionInfo(feature, textPrefab = T.dialogs.featureRestriction.desc) { - const dialog = new Dialog({ - app: this.app, - title: T.dialogs.featureRestriction.title, - contentHTML: textPrefab.replace("", feature), - buttons: ["cancel:bad", "getStandalone:good"], - type: "warning", - }); - this.internalShowDialog(dialog); - - if (this.app) { - this.app.sound.playUiSound(SOUNDS.dialogOk); - } - - this.app.analytics.trackUiClick("demo_dialog_show"); - - dialog.buttonSignals.cancel.add(() => { - this.app.analytics.trackUiClick("demo_dialog_cancel"); - }); - - dialog.buttonSignals.getStandalone.add(() => { - this.app.analytics.trackUiClick("demo_dialog_click"); - window.open(THIRDPARTY_URLS.standaloneStorePage); - }); - - return dialog.buttonSignals; - } - - showOptionChooser(title, options) { - const dialog = new DialogOptionChooser({ - app: this.app, - title, - options, - }); - this.internalShowDialog(dialog); - return dialog.buttonSignals; - } - - // Returns method to be called when laoding finishd - showLoadingDialog() { - const dialog = new DialogLoading(this.app); - this.internalShowDialog(dialog); - return this.closeDialog.bind(this, dialog); - } - - internalShowDialog(dialog) { - const elem = dialog.createElement(); - dialog.setIndex(this.dialogStack.length); - - // Hide last dialog in queue - if (this.dialogStack.length > 0) { - this.dialogStack[this.dialogStack.length - 1].hide(); - } - - this.dialogStack.push(dialog); - - // Append dialog - dialog.show(); - dialog.closeRequested.add(this.closeDialog.bind(this, dialog)); - - // Append to HTML - this.dialogParent.appendChild(elem); - - document.body.classList.toggle("modalDialogActive", this.dialogStack.length > 0); - - // IMPORTANT: Attach element directly, otherwise double submit is possible - this.update(); - } - - update() { - if (this.domWatcher) { - this.domWatcher.update(this.dialogStack.length > 0); - } - } - - closeDialog(dialog) { - dialog.destroy(); - - let index = -1; - for (let i = 0; i < this.dialogStack.length; ++i) { - if (this.dialogStack[i] === dialog) { - index = i; - break; - } - } - assert(index >= 0, "Dialog not in dialog stack"); - this.dialogStack.splice(index, 1); - - if (this.dialogStack.length > 0) { - // Show the dialog which was previously open - this.dialogStack[this.dialogStack.length - 1].show(); - } - - document.body.classList.toggle("modalDialogActive", this.dialogStack.length > 0); - } - - close() { - for (let i = 0; i < this.dialogStack.length; ++i) { - const dialog = this.dialogStack[i]; - dialog.destroy(); - } - this.dialogStack = []; - } - - cleanup() { - super.cleanup(); - for (let i = 0; i < this.dialogStack.length; ++i) { - this.dialogStack[i].destroy(); - } - this.dialogStack = []; - this.dialogParent = null; - } -} +/* typehints:start */ +import { Application } from "../../../application"; +/* typehints:end */ + +import { SOUNDS } from "../../../platform/sound"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; +import { BaseHUDPart } from "../base_hud_part"; +import { Dialog, DialogLoading, DialogOptionChooser } from "../../../core/modal_dialog_elements"; +import { makeDiv } from "../../../core/utils"; +import { T } from "../../../translations"; +import { THIRDPARTY_URLS } from "../../../core/config"; + +export class HUDModalDialogs extends BaseHUDPart { + constructor(root, app) { + // Important: Root is not always available here! Its also used in the main menu + super(root); + + /** @type {Application} */ + this.app = root ? root.app : app; + + this.dialogParent = null; + this.dialogStack = []; + } + + // For use inside of the game, implementation of base hud part + initialize() { + this.dialogParent = document.getElementById("ingame_HUD_ModalDialogs"); + this.domWatcher = new DynamicDomAttach(this.root, this.dialogParent); + } + + shouldPauseRendering() { + return this.dialogStack.length > 0; + } + + shouldPauseGame() { + return this.shouldPauseRendering(); + } + + createElements(parent) { + return makeDiv(parent, "ingame_HUD_ModalDialogs"); + } + + // For use outside of the game + initializeToElement(element) { + assert(element, "No element for dialogs given"); + this.dialogParent = element; + } + + isBlockingOverlay() { + return this.dialogStack.length > 0; + } + + // Methods + + /** + * @param {string} title + * @param {string} text + * @param {Array} buttons + */ + showInfo(title, text, buttons = ["ok:good"]) { + const dialog = new Dialog({ + app: this.app, + title: title, + contentHTML: text, + buttons: buttons, + type: "info", + }); + this.internalShowDialog(dialog); + + if (this.app) { + this.app.sound.playUiSound(SOUNDS.dialogOk); + } + + return dialog.buttonSignals; + } + + /** + * @param {string} title + * @param {string} text + * @param {Array} buttons + */ + showWarning(title, text, buttons = ["ok:good"]) { + const dialog = new Dialog({ + app: this.app, + title: title, + contentHTML: text, + buttons: buttons, + type: "warning", + }); + this.internalShowDialog(dialog); + + if (this.app) { + this.app.sound.playUiSound(SOUNDS.dialogError); + } + + return dialog.buttonSignals; + } + + /** + * @param {string} feature + * @param {string} textPrefab + */ + showFeatureRestrictionInfo(feature, textPrefab = T.dialogs.featureRestriction.desc) { + const dialog = new Dialog({ + app: this.app, + title: T.dialogs.featureRestriction.title, + contentHTML: textPrefab.replace("", feature), + buttons: ["cancel:bad", "getStandalone:good"], + type: "warning", + }); + this.internalShowDialog(dialog); + + if (this.app) { + this.app.sound.playUiSound(SOUNDS.dialogOk); + } + + this.app.analytics.trackUiClick("demo_dialog_show"); + + dialog.buttonSignals.cancel.add(() => { + this.app.analytics.trackUiClick("demo_dialog_cancel"); + }); + + dialog.buttonSignals.getStandalone.add(() => { + this.app.analytics.trackUiClick("demo_dialog_click"); + window.open(THIRDPARTY_URLS.standaloneStorePage + "?ref=ddc"); + }); + + return dialog.buttonSignals; + } + + showOptionChooser(title, options) { + const dialog = new DialogOptionChooser({ + app: this.app, + title, + options, + }); + this.internalShowDialog(dialog); + return dialog.buttonSignals; + } + + // Returns method to be called when laoding finishd + showLoadingDialog() { + const dialog = new DialogLoading(this.app); + this.internalShowDialog(dialog); + return this.closeDialog.bind(this, dialog); + } + + internalShowDialog(dialog) { + const elem = dialog.createElement(); + dialog.setIndex(this.dialogStack.length); + + // Hide last dialog in queue + if (this.dialogStack.length > 0) { + this.dialogStack[this.dialogStack.length - 1].hide(); + } + + this.dialogStack.push(dialog); + + // Append dialog + dialog.show(); + dialog.closeRequested.add(this.closeDialog.bind(this, dialog)); + + // Append to HTML + this.dialogParent.appendChild(elem); + + document.body.classList.toggle("modalDialogActive", this.dialogStack.length > 0); + + // IMPORTANT: Attach element directly, otherwise double submit is possible + this.update(); + } + + update() { + if (this.domWatcher) { + this.domWatcher.update(this.dialogStack.length > 0); + } + } + + closeDialog(dialog) { + dialog.destroy(); + + let index = -1; + for (let i = 0; i < this.dialogStack.length; ++i) { + if (this.dialogStack[i] === dialog) { + index = i; + break; + } + } + assert(index >= 0, "Dialog not in dialog stack"); + this.dialogStack.splice(index, 1); + + if (this.dialogStack.length > 0) { + // Show the dialog which was previously open + this.dialogStack[this.dialogStack.length - 1].show(); + } + + document.body.classList.toggle("modalDialogActive", this.dialogStack.length > 0); + } + + close() { + for (let i = 0; i < this.dialogStack.length; ++i) { + const dialog = this.dialogStack[i]; + dialog.destroy(); + } + this.dialogStack = []; + } + + cleanup() { + super.cleanup(); + for (let i = 0; i < this.dialogStack.length; ++i) { + this.dialogStack[i].destroy(); + } + this.dialogStack = []; + this.dialogParent = null; + } +} diff --git a/src/js/game/hud/parts/notifications.js b/src/js/game/hud/parts/notifications.js index aef0cc75..bef8dd0f 100644 --- a/src/js/game/hud/parts/notifications.js +++ b/src/js/game/hud/parts/notifications.js @@ -1,56 +1,55 @@ -import { BaseHUDPart } from "../base_hud_part"; -import { makeDiv } from "../../../core/utils"; -import { T } from "../../../translations"; -import { IS_DEMO } from "../../../core/config"; - -/** @enum {string} */ -export const enumNotificationType = { - saved: "saved", - upgrade: "upgrade", - success: "success", -}; - -const notificationDuration = 3; - -export class HUDNotifications extends BaseHUDPart { - createElements(parent) { - this.element = makeDiv(parent, "ingame_HUD_Notifications", [], ``); - } - - initialize() { - this.root.hud.signals.notification.add(this.onNotification, this); - - /** @type {Array<{ element: HTMLElement, expireAt: number}>} */ - this.notificationElements = []; - - // Automatic notifications - this.root.signals.gameSaved.add(() => - this.onNotification(T.ingame.notifications.gameSaved, enumNotificationType.saved) - ); - } - - /** - * @param {string} message - * @param {enumNotificationType} type - */ - onNotification(message, type) { - const element = makeDiv(this.element, null, ["notification", "type-" + type], message); - element.setAttribute("data-icon", "icons/notification_" + type + ".png"); - - this.notificationElements.push({ - element, - expireAt: this.root.time.realtimeNow() + notificationDuration, - }); - } - - update() { - const now = this.root.time.realtimeNow(); - for (let i = 0; i < this.notificationElements.length; ++i) { - const handle = this.notificationElements[i]; - if (handle.expireAt <= now) { - handle.element.remove(); - this.notificationElements.splice(i, 1); - } - } - } -} +import { makeDiv } from "../../../core/utils"; +import { T } from "../../../translations"; +import { BaseHUDPart } from "../base_hud_part"; + +/** @enum {string} */ +export const enumNotificationType = { + saved: "saved", + upgrade: "upgrade", + success: "success", +}; + +const notificationDuration = 3; + +export class HUDNotifications extends BaseHUDPart { + createElements(parent) { + this.element = makeDiv(parent, "ingame_HUD_Notifications", [], ``); + } + + initialize() { + this.root.hud.signals.notification.add(this.onNotification, this); + + /** @type {Array<{ element: HTMLElement, expireAt: number}>} */ + this.notificationElements = []; + + // Automatic notifications + this.root.signals.gameSaved.add(() => + this.onNotification(T.ingame.notifications.gameSaved, enumNotificationType.saved) + ); + } + + /** + * @param {string} message + * @param {enumNotificationType} type + */ + onNotification(message, type) { + const element = makeDiv(this.element, null, ["notification", "type-" + type], message); + element.setAttribute("data-icon", "icons/notification_" + type + ".png"); + + this.notificationElements.push({ + element, + expireAt: this.root.time.realtimeNow() + notificationDuration, + }); + } + + update() { + const now = this.root.time.realtimeNow(); + for (let i = 0; i < this.notificationElements.length; ++i) { + const handle = this.notificationElements[i]; + if (handle.expireAt <= now) { + handle.element.remove(); + this.notificationElements.splice(i, 1); + } + } + } +} diff --git a/src/js/game/hud/parts/pinned_shapes.js b/src/js/game/hud/parts/pinned_shapes.js index bda49f1e..542a38b2 100644 --- a/src/js/game/hud/parts/pinned_shapes.js +++ b/src/js/game/hud/parts/pinned_shapes.js @@ -1,291 +1,326 @@ -import { ClickDetector } from "../../../core/click_detector"; -import { formatBigNumber, makeDiv, arrayDelete, arrayDeleteValue } from "../../../core/utils"; -import { ShapeDefinition } from "../../shape_definition"; -import { BaseHUDPart } from "../base_hud_part"; -import { blueprintShape, UPGRADES } from "../../upgrades"; -import { enumHubGoalRewards } from "../../tutorial_goals"; - -/** - * Manages the pinned shapes on the left side of the screen - */ -export class HUDPinnedShapes extends BaseHUDPart { - constructor(root) { - super(root); - /** - * Store a list of pinned shapes - * @type {Array} - */ - this.pinnedShapes = []; - - /** - * Store handles to the currently rendered elements, so we can update them more - * convenient. Also allows for cleaning up handles. - * @type {Array<{ - * key: string, - * amountLabel: HTMLElement, - * lastRenderedValue: string, - * element: HTMLElement, - * detector?: ClickDetector, - * infoDetector?: ClickDetector - * }>} - */ - this.handles = []; - } - - createElements(parent) { - this.element = makeDiv(parent, "ingame_HUD_PinnedShapes", []); - } - - /** - * Serializes the pinned shapes - */ - serialize() { - return { - shapes: this.pinnedShapes, - }; - } - - /** - * Deserializes the pinned shapes - * @param {{ shapes: Array}} data - */ - deserialize(data) { - if (!data || !data.shapes || !Array.isArray(data.shapes)) { - return "Invalid pinned shapes data"; - } - this.pinnedShapes = data.shapes; - } - - /** - * Initializes the hud component - */ - initialize() { - // Connect to any relevant signals - this.root.signals.storyGoalCompleted.add(this.rerenderFull, this); - this.root.signals.upgradePurchased.add(this.updateShapesAfterUpgrade, this); - this.root.signals.postLoadHook.add(this.rerenderFull, this); - this.root.hud.signals.shapePinRequested.add(this.pinNewShape, this); - this.root.hud.signals.shapeUnpinRequested.add(this.unpinShape, this); - - // Perform initial render - this.updateShapesAfterUpgrade(); - } - - /** - * Updates all shapes after an upgrade has been purchased and removes the unused ones - */ - updateShapesAfterUpgrade() { - for (let i = 0; i < this.pinnedShapes.length; ++i) { - const key = this.pinnedShapes[i]; - if (key === blueprintShape) { - // Ignore blueprint shapes - continue; - } - let goal = this.findGoalValueForShape(key); - if (!goal) { - // Seems no longer relevant - this.pinnedShapes.splice(i, 1); - i -= 1; - } - } - - this.rerenderFull(); - } - - /** - * Finds the current goal for the given key. If the key is the story goal, returns - * the story goal. If its the blueprint shape, no goal is returned. Otherwise - * it's searched for upgrades. - * @param {string} key - */ - findGoalValueForShape(key) { - if (key === this.root.hubGoals.currentGoal.definition.getHash()) { - return this.root.hubGoals.currentGoal.required; - } - if (key === blueprintShape) { - return null; - } - - // Check if this shape is required for any upgrade - for (const upgradeId in UPGRADES) { - const { tiers } = UPGRADES[upgradeId]; - const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId); - const tierHandle = tiers[currentTier]; - - if (!tierHandle) { - // Max level - continue; - } - - for (let i = 0; i < tierHandle.required.length; ++i) { - const { shape, amount } = tierHandle.required[i]; - if (shape === key) { - return amount; - } - } - } - - return null; - } - - /** - * Returns whether a given shape is currently pinned - * @param {string} key - */ - isShapePinned(key) { - if (key === this.root.hubGoals.currentGoal.definition.getHash() || key === blueprintShape) { - // This is a "special" shape which is always pinned - return true; - } - - return this.pinnedShapes.indexOf(key) >= 0; - } - - /** - * Rerenders the whole component - */ - rerenderFull() { - const currentGoal = this.root.hubGoals.currentGoal; - const currentKey = currentGoal.definition.getHash(); - - // First, remove all old shapes - for (let i = 0; i < this.handles.length; ++i) { - this.handles[i].element.remove(); - const detector = this.handles[i].detector; - if (detector) { - detector.cleanup(); - } - const infoDetector = this.handles[i].infoDetector; - if (infoDetector) { - infoDetector.cleanup(); - } - } - this.handles = []; - - // Pin story goal - this.internalPinShape(currentKey, false, "goal"); - - // Pin blueprint shape as well - if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) { - this.internalPinShape(blueprintShape, false, "blueprint"); - } - - // Pin manually pinned shapes - for (let i = 0; i < this.pinnedShapes.length; ++i) { - const key = this.pinnedShapes[i]; - if (key !== currentKey) { - this.internalPinShape(key); - } - } - } - - /** - * Pins a new shape - * @param {string} key - * @param {boolean} canUnpin - * @param {string=} className - */ - internalPinShape(key, canUnpin = true, className = null) { - const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey(key); - - const element = makeDiv(this.element, null, ["shape"]); - const canvas = definition.generateAsCanvas(120); - element.appendChild(canvas); - - if (className) { - element.classList.add(className); - } - - let detector = null; - if (canUnpin) { - element.classList.add("unpinable"); - detector = new ClickDetector(element, { - consumeEvents: true, - preventDefault: true, - targetOnly: true, - }); - detector.click.add(() => this.unpinShape(key)); - } else { - element.classList.add("marked"); - } - - // Show small info icon - const infoButton = document.createElement("button"); - infoButton.classList.add("infoButton"); - element.appendChild(infoButton); - const infoDetector = new ClickDetector(infoButton, { - consumeEvents: true, - preventDefault: true, - targetOnly: true, - }); - infoDetector.click.add(() => this.root.hud.signals.viewShapeDetailsRequested.dispatch(definition)); - - const amountLabel = makeDiv(element, null, ["amountLabel"], ""); - - const goal = this.findGoalValueForShape(key); - if (goal) { - makeDiv(element, null, ["goalLabel"], "/" + formatBigNumber(goal)); - } - - this.handles.push({ - key, - element, - amountLabel, - lastRenderedValue: "", - detector, - infoDetector, - }); - } - - /** - * Updates all amount labels - */ - update() { - for (let i = 0; i < this.handles.length; ++i) { - const handle = this.handles[i]; - - const currentValue = this.root.hubGoals.getShapesStoredByKey(handle.key); - const currentValueFormatted = formatBigNumber(currentValue); - if (currentValueFormatted !== handle.lastRenderedValue) { - handle.lastRenderedValue = currentValueFormatted; - handle.amountLabel.innerText = currentValueFormatted; - const goal = this.findGoalValueForShape(handle.key); - handle.element.classList.toggle("completed", goal && currentValue > goal); - } - } - } - - /** - * Unpins a shape - * @param {string} key - */ - unpinShape(key) { - arrayDeleteValue(this.pinnedShapes, key); - this.rerenderFull(); - } - - /** - * Requests to pin a new shape - * @param {ShapeDefinition} definition - */ - pinNewShape(definition) { - const key = definition.getHash(); - if (key === this.root.hubGoals.currentGoal.definition.getHash()) { - // Can not pin current goal - return; - } - - if (key === blueprintShape) { - // Can not pin the blueprint shape - return; - } - - // Check if its already pinned - if (this.pinnedShapes.indexOf(key) >= 0) { - return; - } - - this.pinnedShapes.push(key); - this.rerenderFull(); - } -} +import { ClickDetector } from "../../../core/click_detector"; +import { globalConfig } from "../../../core/config"; +import { arrayDeleteValue, formatBigNumber, makeDiv } from "../../../core/utils"; +import { T } from "../../../translations"; +import { enumAnalyticsDataSource } from "../../production_analytics"; +import { ShapeDefinition } from "../../shape_definition"; +import { enumHubGoalRewards } from "../../tutorial_goals"; +import { BaseHUDPart } from "../base_hud_part"; + +/** + * Manages the pinned shapes on the left side of the screen + */ +export class HUDPinnedShapes extends BaseHUDPart { + constructor(root) { + super(root); + /** + * Store a list of pinned shapes + * @type {Array} + */ + this.pinnedShapes = []; + + /** + * Store handles to the currently rendered elements, so we can update them more + * convenient. Also allows for cleaning up handles. + * @type {Array<{ + * key: string, + * definition: ShapeDefinition, + * amountLabel: HTMLElement, + * lastRenderedValue: string, + * element: HTMLElement, + * detector?: ClickDetector, + * infoDetector?: ClickDetector, + * throughputOnly?: boolean + * }>} + */ + this.handles = []; + } + + createElements(parent) { + this.element = makeDiv(parent, "ingame_HUD_PinnedShapes", []); + } + + /** + * Serializes the pinned shapes + */ + serialize() { + return { + shapes: this.pinnedShapes, + }; + } + + /** + * Deserializes the pinned shapes + * @param {{ shapes: Array}} data + */ + deserialize(data) { + if (!data || !data.shapes || !Array.isArray(data.shapes)) { + return "Invalid pinned shapes data"; + } + this.pinnedShapes = data.shapes; + } + + /** + * Initializes the hud component + */ + initialize() { + // Connect to any relevant signals + this.root.signals.storyGoalCompleted.add(this.rerenderFull, this); + this.root.signals.upgradePurchased.add(this.updateShapesAfterUpgrade, this); + this.root.signals.postLoadHook.add(this.rerenderFull, this); + this.root.hud.signals.shapePinRequested.add(this.pinNewShape, this); + this.root.hud.signals.shapeUnpinRequested.add(this.unpinShape, this); + + // Perform initial render + this.updateShapesAfterUpgrade(); + } + + /** + * Updates all shapes after an upgrade has been purchased and removes the unused ones + */ + updateShapesAfterUpgrade() { + for (let i = 0; i < this.pinnedShapes.length; ++i) { + const key = this.pinnedShapes[i]; + if (key === this.root.gameMode.getBlueprintShapeKey()) { + // Ignore blueprint shapes + continue; + } + let goal = this.findGoalValueForShape(key); + if (!goal) { + // Seems no longer relevant + this.pinnedShapes.splice(i, 1); + i -= 1; + } + } + + this.rerenderFull(); + } + + /** + * Finds the current goal for the given key. If the key is the story goal, returns + * the story goal. If its the blueprint shape, no goal is returned. Otherwise + * it's searched for upgrades. + * @param {string} key + */ + findGoalValueForShape(key) { + if (key === this.root.hubGoals.currentGoal.definition.getHash()) { + return this.root.hubGoals.currentGoal.required; + } + if (key === this.root.gameMode.getBlueprintShapeKey()) { + return null; + } + + // Check if this shape is required for any upgrade + const upgrades = this.root.gameMode.getUpgrades(); + for (const upgradeId in upgrades) { + const upgradeTiers = upgrades[upgradeId]; + const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId); + const tierHandle = upgradeTiers[currentTier]; + + if (!tierHandle) { + // Max level + continue; + } + + for (let i = 0; i < tierHandle.required.length; ++i) { + const { shape, amount } = tierHandle.required[i]; + if (shape === key) { + return amount; + } + } + } + + return null; + } + + /** + * Returns whether a given shape is currently pinned + * @param {string} key + */ + isShapePinned(key) { + if ( + key === this.root.hubGoals.currentGoal.definition.getHash() || + key === this.root.gameMode.getBlueprintShapeKey() + ) { + // This is a "special" shape which is always pinned + return true; + } + + return this.pinnedShapes.indexOf(key) >= 0; + } + + /** + * Rerenders the whole component + */ + rerenderFull() { + const currentGoal = this.root.hubGoals.currentGoal; + const currentKey = currentGoal.definition.getHash(); + + // First, remove all old shapes + for (let i = 0; i < this.handles.length; ++i) { + this.handles[i].element.remove(); + const detector = this.handles[i].detector; + if (detector) { + detector.cleanup(); + } + const infoDetector = this.handles[i].infoDetector; + if (infoDetector) { + infoDetector.cleanup(); + } + } + this.handles = []; + + // Pin story goal + this.internalPinShape({ + key: currentKey, + canUnpin: false, + className: "goal", + throughputOnly: currentGoal.throughputOnly, + }); + + // Pin blueprint shape as well + if (this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_blueprints)) { + this.internalPinShape({ + key: this.root.gameMode.getBlueprintShapeKey(), + canUnpin: false, + className: "blueprint", + }); + } + + // Pin manually pinned shapes + for (let i = 0; i < this.pinnedShapes.length; ++i) { + const key = this.pinnedShapes[i]; + if (key !== currentKey) { + this.internalPinShape({ key }); + } + } + } + + /** + * Pins a new shape + * @param {object} param0 + * @param {string} param0.key + * @param {boolean=} param0.canUnpin + * @param {string=} param0.className + * @param {boolean=} param0.throughputOnly + */ + internalPinShape({ key, canUnpin = true, className = null, throughputOnly = false }) { + const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey(key); + + const element = makeDiv(this.element, null, ["shape"]); + const canvas = definition.generateAsCanvas(120); + element.appendChild(canvas); + + if (className) { + element.classList.add(className); + } + + let detector = null; + if (canUnpin) { + element.classList.add("removable"); + detector = new ClickDetector(element, { + consumeEvents: true, + preventDefault: true, + targetOnly: false, + }); + detector.click.add(() => this.unpinShape(key)); + } else { + element.classList.add("marked"); + } + + // Show small info icon + const infoButton = document.createElement("button"); + infoButton.classList.add("infoButton"); + element.appendChild(infoButton); + const infoDetector = new ClickDetector(infoButton, { + consumeEvents: true, + preventDefault: true, + targetOnly: true, + }); + infoDetector.click.add(() => this.root.hud.signals.viewShapeDetailsRequested.dispatch(definition)); + + const amountLabel = makeDiv(element, null, ["amountLabel"], ""); + + const goal = this.findGoalValueForShape(key); + if (goal) { + makeDiv(element, null, ["goalLabel"], "/" + formatBigNumber(goal)); + } + + this.handles.push({ + key, + definition, + element, + amountLabel, + lastRenderedValue: "", + detector, + infoDetector, + throughputOnly, + }); + } + + /** + * Updates all amount labels + */ + update() { + for (let i = 0; i < this.handles.length; ++i) { + const handle = this.handles[i]; + + let currentValue = this.root.hubGoals.getShapesStoredByKey(handle.key); + let currentValueFormatted = formatBigNumber(currentValue); + + if (handle.throughputOnly) { + currentValue = + this.root.productionAnalytics.getCurrentShapeRate( + enumAnalyticsDataSource.delivered, + handle.definition + ) / globalConfig.analyticsSliceDurationSeconds; + currentValueFormatted = T.ingame.statistics.shapesDisplayUnits.second.replace( + "", + String(currentValue) + ); + } + + if (currentValueFormatted !== handle.lastRenderedValue) { + handle.lastRenderedValue = currentValueFormatted; + handle.amountLabel.innerText = currentValueFormatted; + const goal = this.findGoalValueForShape(handle.key); + handle.element.classList.toggle("completed", goal && currentValue > goal); + } + } + } + + /** + * Unpins a shape + * @param {string} key + */ + unpinShape(key) { + console.log("unpin", key); + arrayDeleteValue(this.pinnedShapes, key); + this.rerenderFull(); + } + + /** + * Requests to pin a new shape + * @param {ShapeDefinition} definition + */ + pinNewShape(definition) { + const key = definition.getHash(); + if (key === this.root.hubGoals.currentGoal.definition.getHash()) { + // Can not pin current goal + return; + } + + if (key === this.root.gameMode.getBlueprintShapeKey()) { + // Can not pin the blueprint shape + return; + } + + // Check if its already pinned + if (this.pinnedShapes.indexOf(key) >= 0) { + return; + } + + this.pinnedShapes.push(key); + this.rerenderFull(); + } +} 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..592487ee 100644 --- a/src/js/game/hud/parts/sandbox_controller.js +++ b/src/js/game/hud/parts/sandbox_controller.js @@ -1,158 +1,158 @@ -import { BaseHUDPart } from "../base_hud_part"; -import { makeDiv } from "../../../core/utils"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; -import { blueprintShape, UPGRADES } from "../../upgrades"; -import { enumNotificationType } from "./notifications"; -import { tutorialGoals } from "../../tutorial_goals"; - -export class HUDSandboxController extends BaseHUDPart { - createElements(parent) { - this.element = makeDiv( - parent, - "ingame_HUD_SandboxController", - [], - ` - - Use F6 to toggle this overlay - -
-
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - -
-
- ` - ); - - const bind = (selector, handler) => this.trackClicks(this.element.querySelector(selector), handler); - - bind(".giveBlueprints", this.giveBlueprints); - bind(".maxOutAll", this.maxOutAll); - bind(".levelToggle .minus", () => this.modifyLevel(-1)); - bind(".levelToggle .plus", () => this.modifyLevel(1)); - - bind(".upgradesBelt .minus", () => this.modifyUpgrade("belt", -1)); - bind(".upgradesBelt .plus", () => this.modifyUpgrade("belt", 1)); - - bind(".upgradesExtraction .minus", () => this.modifyUpgrade("miner", -1)); - bind(".upgradesExtraction .plus", () => this.modifyUpgrade("miner", 1)); - - bind(".upgradesProcessing .minus", () => this.modifyUpgrade("processors", -1)); - bind(".upgradesProcessing .plus", () => this.modifyUpgrade("processors", 1)); - - bind(".upgradesPainting .minus", () => this.modifyUpgrade("painting", -1)); - bind(".upgradesPainting .plus", () => this.modifyUpgrade("painting", 1)); - } - - giveBlueprints() { - if (!this.root.hubGoals.storedShapes[blueprintShape]) { - this.root.hubGoals.storedShapes[blueprintShape] = 0; - } - this.root.hubGoals.storedShapes[blueprintShape] += 1e4; - } - - maxOutAll() { - this.modifyUpgrade("belt", 100); - this.modifyUpgrade("miner", 100); - this.modifyUpgrade("processors", 100); - this.modifyUpgrade("painting", 100); - } - - modifyUpgrade(id, amount) { - const handle = UPGRADES[id]; - const maxLevel = handle.tiers.length; - - this.root.hubGoals.upgradeLevels[id] = Math.max( - 0, - Math.min(maxLevel, (this.root.hubGoals.upgradeLevels[id] || 0) + amount) - ); - - // Compute improvement - let improvement = 1; - for (let i = 0; i < this.root.hubGoals.upgradeLevels[id]; ++i) { - improvement += handle.tiers[i].improvement; - } - 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], - enumNotificationType.upgrade - ); - } - - modifyLevel(amount) { - const hubGoals = this.root.hubGoals; - hubGoals.level = Math.max(1, hubGoals.level + amount); - hubGoals.createNextGoal(); - - // Clear all shapes of this level - hubGoals.storedShapes[hubGoals.currentGoal.definition.getHash()] = 0; - - this.root.hud.parts.pinnedShapes.rerenderFull(); - - // Compute gained rewards - hubGoals.gainedRewards = {}; - for (let i = 0; i < hubGoals.level - 1; ++i) { - if (i < tutorialGoals.length) { - const reward = tutorialGoals[i].reward; - hubGoals.gainedRewards[reward] = (hubGoals.gainedRewards[reward] || 0) + 1; - } - } - - this.root.hud.signals.notification.dispatch( - "Changed level to " + hubGoals.level, - enumNotificationType.upgrade - ); - } - - initialize() { - // Allow toggling the controller overlay - this.root.gameState.inputReciever.keydown.add(key => { - if (key.keyCode === 117) { - // F6 - this.toggle(); - } - }); - - this.visible = !G_IS_DEV; - this.domAttach = new DynamicDomAttach(this.root, this.element); - } - - toggle() { - this.visible = !this.visible; - } - - update() { - this.domAttach.update(this.visible); - } -} +import { makeDiv } from "../../../core/utils"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; +import { enumNotificationType } from "./notifications"; + +export class HUDSandboxController extends BaseHUDPart { + createElements(parent) { + this.element = makeDiv( + parent, + "ingame_HUD_SandboxController", + [], + ` + + Use F6 to toggle this overlay + +
+
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + +
+
+ ` + ); + + const bind = (selector, handler) => this.trackClicks(this.element.querySelector(selector), handler); + + bind(".giveBlueprints", this.giveBlueprints); + bind(".maxOutAll", this.maxOutAll); + bind(".levelToggle .minus", () => this.modifyLevel(-1)); + bind(".levelToggle .plus", () => this.modifyLevel(1)); + + bind(".upgradesBelt .minus", () => this.modifyUpgrade("belt", -1)); + bind(".upgradesBelt .plus", () => this.modifyUpgrade("belt", 1)); + + bind(".upgradesExtraction .minus", () => this.modifyUpgrade("miner", -1)); + bind(".upgradesExtraction .plus", () => this.modifyUpgrade("miner", 1)); + + bind(".upgradesProcessing .minus", () => this.modifyUpgrade("processors", -1)); + bind(".upgradesProcessing .plus", () => this.modifyUpgrade("processors", 1)); + + bind(".upgradesPainting .minus", () => this.modifyUpgrade("painting", -1)); + bind(".upgradesPainting .plus", () => this.modifyUpgrade("painting", 1)); + } + + giveBlueprints() { + const shape = this.root.gameMode.getBlueprintShapeKey(); + if (!this.root.hubGoals.storedShapes[shape]) { + this.root.hubGoals.storedShapes[shape] = 0; + } + this.root.hubGoals.storedShapes[shape] += 1e9; + } + + maxOutAll() { + this.modifyUpgrade("belt", 100); + this.modifyUpgrade("miner", 100); + this.modifyUpgrade("processors", 100); + this.modifyUpgrade("painting", 100); + } + + modifyUpgrade(id, amount) { + const upgradeTiers = this.root.gameMode.getUpgrades()[id]; + const maxLevel = upgradeTiers.length; + + this.root.hubGoals.upgradeLevels[id] = Math.max( + 0, + Math.min(maxLevel, (this.root.hubGoals.upgradeLevels[id] || 0) + amount) + ); + + // Compute improvement + let improvement = 1; + for (let i = 0; i < this.root.hubGoals.upgradeLevels[id]; ++i) { + improvement += upgradeTiers[i].improvement; + } + this.root.hubGoals.upgradeImprovements[id] = improvement; + this.root.signals.upgradePurchased.dispatch(id); + this.root.hud.signals.notification.dispatch( + "Upgrade '" + id + "' is now at tier " + (this.root.hubGoals.upgradeLevels[id] + 1), + enumNotificationType.upgrade + ); + } + + modifyLevel(amount) { + const hubGoals = this.root.hubGoals; + hubGoals.level = Math.max(1, hubGoals.level + amount); + hubGoals.computeNextGoal(); + + // Clear all shapes of this level + hubGoals.storedShapes[hubGoals.currentGoal.definition.getHash()] = 0; + + this.root.hud.parts.pinnedShapes.rerenderFull(); + + // Compute gained rewards + hubGoals.gainedRewards = {}; + const levels = this.root.gameMode.getLevelDefinitions(); + for (let i = 0; i < hubGoals.level - 1; ++i) { + if (i < levels.length) { + const reward = levels[i].reward; + hubGoals.gainedRewards[reward] = (hubGoals.gainedRewards[reward] || 0) + 1; + } + } + + this.root.hud.signals.notification.dispatch( + "Changed level to " + hubGoals.level, + enumNotificationType.upgrade + ); + } + + initialize() { + // Allow toggling the controller overlay + this.root.gameState.inputReciever.keydown.add(key => { + if (key.keyCode === 117) { + // F6 + this.toggle(); + } + }); + + this.visible = !G_IS_DEV; + this.domAttach = new DynamicDomAttach(this.root, this.element); + } + + toggle() { + this.visible = !this.visible; + } + + update() { + this.domAttach.update(this.visible); + } +} diff --git a/src/js/game/hud/parts/screenshot_exporter.js b/src/js/game/hud/parts/screenshot_exporter.js index 19c644e9..dd81f8b6 100644 --- a/src/js/game/hud/parts/screenshot_exporter.js +++ b/src/js/game/hud/parts/screenshot_exporter.js @@ -1,13 +1,13 @@ -import { BaseHUDPart } from "../base_hud_part"; -import { KEYMAPPINGS } from "../../key_action_mapper"; -import { IS_DEMO, globalConfig } from "../../../core/config"; -import { T } from "../../../translations"; -import { createLogger } from "../../../core/logging"; -import { StaticMapEntityComponent } from "../../components/static_map_entity"; -import { Vector } from "../../../core/vector"; import { makeOffscreenBuffer } from "../../../core/buffer_utils"; +import { globalConfig } from "../../../core/config"; import { DrawParameters } from "../../../core/draw_parameters"; +import { createLogger } from "../../../core/logging"; import { Rectangle } from "../../../core/rectangle"; +import { Vector } from "../../../core/vector"; +import { T } from "../../../translations"; +import { StaticMapEntityComponent } from "../../components/static_map_entity"; +import { KEYMAPPINGS } from "../../key_action_mapper"; +import { BaseHUDPart } from "../base_hud_part"; const logger = createLogger("screenshot_exporter"); @@ -19,7 +19,7 @@ export class HUDScreenshotExporter extends BaseHUDPart { } startExport() { - if (IS_DEMO) { + if (!this.root.app.restrictionMgr.getIsExportingScreenshotsPossible()) { this.root.hud.parts.dialogs.showFeatureRestrictionInfo(T.demo.features.exportingBase); return; } @@ -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,15 +79,15 @@ 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, visibleRect, - desiredAtlasScale: "1", + desiredAtlasScale: 0.25, root: this.root, zoomLevel: chunkScale, }); diff --git a/src/js/game/hud/parts/settings_menu.js b/src/js/game/hud/parts/settings_menu.js index c70d6afc..eb902934 100644 --- a/src/js/game/hud/parts/settings_menu.js +++ b/src/js/game/hud/parts/settings_menu.js @@ -1,133 +1,125 @@ -import { BaseHUDPart } from "../base_hud_part"; -import { makeDiv, formatSeconds, 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) { - this.background = makeDiv(parent, "ingame_HUD_SettingsMenu", ["ingameDialog"]); - - this.menuElement = makeDiv(this.background, null, ["menuElement"]); - - this.statsElement = makeDiv( - this.background, - null, - ["statsElement"], - ` - ${T.ingame.settingsMenu.beltsPlaced} - ${T.ingame.settingsMenu.buildingsPlaced} - ${T.ingame.settingsMenu.playtime} - - ` - ); - - this.buttonContainer = makeDiv(this.menuElement, null, ["buttons"]); - - const buttons = [ - { - title: T.ingame.settingsMenu.buttons.continue, - action: () => this.close(), - }, - { - title: T.ingame.settingsMenu.buttons.settings, - action: () => this.goToSettings(), - }, - { - title: T.ingame.settingsMenu.buttons.menu, - action: () => this.returnToMenu(), - }, - ]; - - for (let i = 0; i < buttons.length; ++i) { - const { title, action } = buttons[i]; - - const element = document.createElement("button"); - element.classList.add("styledButton"); - element.innerText = title; - this.buttonContainer.appendChild(element); - - this.trackClicks(element, action); - } - } - - 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() { - this.root.gameState.goToSettings(); - } - - shouldPauseGame() { - return this.visible; - } - - shouldPauseRendering() { - return this.visible; - } - - initialize() { - this.root.keyMapper.getBinding(KEYMAPPINGS.general.back).add(this.show, this); - - this.domAttach = new DynamicDomAttach(this.root, this.background, { - attachClass: "visible", - }); - - this.inputReciever = new InputReceiver("settingsmenu"); - this.keyActionMapper = new KeyActionMapper(this.root, this.inputReciever); - this.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.close, this); - - this.close(); - } - - cleanup() { - document.body.classList.remove("ingameDialogOpen"); - } - - 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( - this.root.entityMgr.getAllWithComponent(StaticMapEntityComponent).length - - this.root.entityMgr.getAllWithComponent(BeltComponent).length - ); - this.statsElement.querySelector(".beltsPlaced").innerText = formatBigNumberFull( - this.root.entityMgr.getAllWithComponent(BeltComponent).length - ); - } - - close() { - this.visible = false; - document.body.classList.remove("ingameDialogOpen"); - this.root.app.inputMgr.makeSureDetached(this.inputReciever); - this.update(); - } - - update() { - this.domAttach.update(this.visible); - } -} +import { BaseHUDPart } from "../base_hud_part"; +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 { BeltComponent } from "../../components/belt"; + +export class HUDSettingsMenu extends BaseHUDPart { + createElements(parent) { + this.background = makeDiv(parent, "ingame_HUD_SettingsMenu", ["ingameDialog"]); + + this.menuElement = makeDiv(this.background, null, ["menuElement"]); + + this.statsElement = makeDiv( + this.background, + null, + ["statsElement"], + ` + ${T.ingame.settingsMenu.beltsPlaced} + ${T.ingame.settingsMenu.buildingsPlaced} + ${T.ingame.settingsMenu.playtime} + + ` + ); + + this.buttonContainer = makeDiv(this.menuElement, null, ["buttons"]); + + const buttons = [ + { + id: "continue", + action: () => this.close(), + }, + { + id: "settings", + action: () => this.goToSettings(), + }, + { + id: "menu", + action: () => this.returnToMenu(), + }, + ]; + + for (let i = 0; i < buttons.length; ++i) { + const { action, id } = buttons[i]; + + const element = document.createElement("button"); + element.classList.add("styledButton"); + element.classList.add(id); + this.buttonContainer.appendChild(element); + + this.trackClicks(element, action); + } + } + + isBlockingOverlay() { + return this.visible; + } + + returnToMenu() { + this.root.gameState.goBackToMenu(); + } + + goToSettings() { + this.root.gameState.goToSettings(); + } + + shouldPauseGame() { + return this.visible; + } + + shouldPauseRendering() { + return this.visible; + } + + initialize() { + this.root.keyMapper.getBinding(KEYMAPPINGS.general.back).add(this.show, this); + + this.domAttach = new DynamicDomAttach(this.root, this.background, { + attachClass: "visible", + }); + + this.inputReciever = new InputReceiver("settingsmenu"); + this.keyActionMapper = new KeyActionMapper(this.root, this.inputReciever); + this.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.close, this); + + this.close(); + } + + show() { + this.visible = true; + this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); + + const totalMinutesPlayed = Math.ceil(this.root.time.now() / 60); + + /** @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 + ); + + beltsPlacedElement.innerText = formatBigNumberFull( + this.root.entityMgr.getAllWithComponent(BeltComponent).length + ); + } + + close() { + this.visible = false; + this.root.app.inputMgr.makeSureDetached(this.inputReciever); + this.update(); + } + + update() { + this.domAttach.update(this.visible); + } +} diff --git a/src/js/game/hud/parts/shape_viewer.js b/src/js/game/hud/parts/shape_viewer.js index 55feb976..a7f5d206 100644 --- a/src/js/game/hud/parts/shape_viewer.js +++ b/src/js/game/hud/parts/shape_viewer.js @@ -1,133 +1,128 @@ -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(); + } + + isBlockingOverlay() { + return this.visible; + } + + /** + * 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; + this.root.app.inputMgr.makeSureDetached(this.inputReciever); + this.update(); + } + + /** + * Shows the viewer for a given definition + * @param {ShapeDefinition} definition + */ + renderForShape(definition) { + this.visible = true; + 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 + ); + } + } + } + } + + update() { + this.domAttach.update(this.visible); + } +} diff --git a/src/js/game/hud/parts/shop.js b/src/js/game/hud/parts/shop.js index e2b8837b..96521898 100644 --- a/src/js/game/hud/parts/shop.js +++ b/src/js/game/hud/parts/shop.js @@ -1,251 +1,247 @@ -import { ClickDetector } from "../../../core/click_detector"; -import { InputReceiver } from "../../../core/input_receiver"; -import { formatBigNumber, makeDiv } from "../../../core/utils"; -import { T } from "../../../translations"; -import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper"; -import { UPGRADES } from "../../upgrades"; -import { BaseHUDPart } from "../base_hud_part"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; - -export class HUDShop extends BaseHUDPart { - createElements(parent) { - this.background = makeDiv(parent, "ingame_HUD_Shop", ["ingameDialog"]); - - // DIALOG Inner / Wrapper - this.dialogInner = makeDiv(this.background, null, ["dialogInner"]); - this.title = makeDiv(this.dialogInner, null, ["title"], T.ingame.shop.title); - this.closeButton = makeDiv(this.title, null, ["closeButton"]); - this.trackClicks(this.closeButton, this.close); - this.contentDiv = makeDiv(this.dialogInner, null, ["content"]); - - this.upgradeToElements = {}; - - // Upgrades - for (const upgradeId in UPGRADES) { - const handle = {}; - handle.requireIndexToElement = []; - - // Wrapper - handle.elem = makeDiv(this.contentDiv, null, ["upgrade"]); - handle.elem.setAttribute("data-upgrade-id", upgradeId); - - // Title - const title = makeDiv(handle.elem, null, ["title"], T.shopUpgrades[upgradeId].name); - - // Title > Tier - handle.elemTierLabel = makeDiv(title, null, ["tier"]); - - // Icon - handle.icon = makeDiv(handle.elem, null, ["icon"]); - handle.icon.setAttribute("data-icon", "upgrades/" + upgradeId + ".png"); - - // Description - handle.elemDescription = makeDiv(handle.elem, null, ["description"], "??"); - handle.elemRequirements = makeDiv(handle.elem, null, ["requirements"]); - - // Buy button - handle.buyButton = document.createElement("button"); - handle.buyButton.classList.add("buy", "styledButton"); - handle.buyButton.innerText = T.ingame.shop.buttonUnlock; - handle.elem.appendChild(handle.buyButton); - - this.trackClicks(handle.buyButton, () => this.tryUnlockNextTier(upgradeId)); - - // Assign handle - this.upgradeToElements[upgradeId] = handle; - } - } - - rerenderFull() { - for (const upgradeId in this.upgradeToElements) { - const handle = this.upgradeToElements[upgradeId]; - const { tiers } = UPGRADES[upgradeId]; - - const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId); - const currentTierMultiplier = this.root.hubGoals.upgradeImprovements[upgradeId]; - const tierHandle = tiers[currentTier]; - - // Set tier - handle.elemTierLabel.innerText = T.ingame.shop.tier.replace( - "", - "" + T.ingame.shop.tierLabels[currentTier] - ); - - handle.elemTierLabel.setAttribute("data-tier", currentTier); - - // Cleanup detectors - for (let i = 0; i < handle.requireIndexToElement.length; ++i) { - const requiredHandle = handle.requireIndexToElement[i]; - requiredHandle.container.remove(); - requiredHandle.pinDetector.cleanup(); - requiredHandle.infoDetector.cleanup(); - } - - // Cleanup - handle.requireIndexToElement = []; - - handle.elem.classList.toggle("maxLevel", !tierHandle); - - if (!tierHandle) { - // Max level - handle.elemDescription.innerText = T.ingame.shop.maximumLevel.replace( - "", - currentTierMultiplier.toString() - ); - continue; - } - - // Set description - handle.elemDescription.innerText = T.shopUpgrades[upgradeId].description - .replace("", currentTierMultiplier.toString()) - .replace("", (currentTierMultiplier + tierHandle.improvement).toString()) - // Backwards compatibility - .replace("", (tierHandle.improvement * 100.0).toString()); - - tierHandle.required.forEach(({ shape, amount }) => { - const container = makeDiv(handle.elemRequirements, null, ["requirement"]); - - const shapeDef = this.root.shapeDefinitionMgr.getShapeFromShortKey(shape); - const shapeCanvas = shapeDef.generateAsCanvas(120); - shapeCanvas.classList.add(); - container.appendChild(shapeCanvas); - - const progressContainer = makeDiv(container, null, ["amount"]); - const progressBar = document.createElement("label"); - progressBar.classList.add("progressBar"); - progressContainer.appendChild(progressBar); - - const progressLabel = document.createElement("label"); - progressContainer.appendChild(progressLabel); - - const pinButton = document.createElement("button"); - pinButton.classList.add("pin"); - container.appendChild(pinButton); - - const viewInfoButton = document.createElement("button"); - viewInfoButton.classList.add("showInfo"); - container.appendChild(viewInfoButton); - - const currentGoalShape = this.root.hubGoals.currentGoal.definition.getHash(); - if (shape === currentGoalShape) { - pinButton.classList.add("isGoal"); - } else if (this.root.hud.parts.pinnedShapes.isShapePinned(shape)) { - pinButton.classList.add("alreadyPinned"); - } - - const pinDetector = new ClickDetector(pinButton, { - consumeEvents: true, - preventDefault: true, - }); - pinDetector.click.add(() => { - if (this.root.hud.parts.pinnedShapes.isShapePinned(shape)) { - this.root.hud.signals.shapeUnpinRequested.dispatch(shape); - pinButton.classList.add("unpinned"); - pinButton.classList.remove("pinned", "alreadyPinned"); - } else { - this.root.hud.signals.shapePinRequested.dispatch(shapeDef); - pinButton.classList.add("pinned"); - pinButton.classList.remove("unpinned"); - } - }); - - const infoDetector = new ClickDetector(viewInfoButton, { - consumeEvents: true, - preventDefault: true, - }); - infoDetector.click.add(() => - this.root.hud.signals.viewShapeDetailsRequested.dispatch(shapeDef) - ); - - handle.requireIndexToElement.push({ - container, - progressLabel, - progressBar, - definition: shapeDef, - required: amount, - pinDetector, - infoDetector, - }); - }); - } - } - - renderCountsAndStatus() { - for (const upgradeId in this.upgradeToElements) { - const handle = this.upgradeToElements[upgradeId]; - for (let i = 0; i < handle.requireIndexToElement.length; ++i) { - const { progressLabel, progressBar, definition, required } = handle.requireIndexToElement[i]; - - const haveAmount = this.root.hubGoals.getShapesStored(definition); - const progress = Math.min(haveAmount / required, 1.0); - - progressLabel.innerText = formatBigNumber(haveAmount) + " / " + formatBigNumber(required); - progressBar.style.width = progress * 100.0 + "%"; - progressBar.classList.toggle("complete", progress >= 1.0); - } - - handle.buyButton.classList.toggle("buyable", this.root.hubGoals.canUnlockUpgrade(upgradeId)); - } - } - - initialize() { - this.domAttach = new DynamicDomAttach(this.root, this.background, { - attachClass: "visible", - }); - - this.inputReciever = new InputReceiver("shop"); - this.keyActionMapper = new KeyActionMapper(this.root, this.inputReciever); - - this.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.close, this); - this.keyActionMapper.getBinding(KEYMAPPINGS.ingame.menuClose).add(this.close, this); - this.keyActionMapper.getBinding(KEYMAPPINGS.ingame.menuOpenShop).add(this.close, this); - - this.close(); - - this.rerenderFull(); - this.root.signals.upgradePurchased.add(this.rerenderFull, this); - } - - cleanup() { - document.body.classList.remove("ingameDialogOpen"); - - // Cleanup detectors - for (const upgradeId in this.upgradeToElements) { - const handle = this.upgradeToElements[upgradeId]; - for (let i = 0; i < handle.requireIndexToElement.length; ++i) { - const requiredHandle = handle.requireIndexToElement[i]; - requiredHandle.container.remove(); - requiredHandle.pinDetector.cleanup(); - requiredHandle.infoDetector.cleanup(); - } - handle.requireIndexToElement = []; - } - } - - show() { - this.visible = true; - document.body.classList.add("ingameDialogOpen"); - // this.background.classList.add("visible"); - this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); - this.rerenderFull(); - } - - close() { - this.visible = false; - document.body.classList.remove("ingameDialogOpen"); - this.root.app.inputMgr.makeSureDetached(this.inputReciever); - this.update(); - } - - update() { - this.domAttach.update(this.visible); - if (this.visible) { - this.renderCountsAndStatus(); - } - } - - tryUnlockNextTier(upgradeId) { - // Nothing - this.root.hubGoals.tryUnlockUpgrade(upgradeId); - } -} +import { ClickDetector } from "../../../core/click_detector"; +import { InputReceiver } from "../../../core/input_receiver"; +import { formatBigNumber, getRomanNumber, makeDiv } from "../../../core/utils"; +import { T } from "../../../translations"; +import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; + +export class HUDShop extends BaseHUDPart { + createElements(parent) { + this.background = makeDiv(parent, "ingame_HUD_Shop", ["ingameDialog"]); + + // DIALOG Inner / Wrapper + this.dialogInner = makeDiv(this.background, null, ["dialogInner"]); + this.title = makeDiv(this.dialogInner, null, ["title"], T.ingame.shop.title); + this.closeButton = makeDiv(this.title, null, ["closeButton"]); + this.trackClicks(this.closeButton, this.close); + this.contentDiv = makeDiv(this.dialogInner, null, ["content"]); + + this.upgradeToElements = {}; + + // Upgrades + for (const upgradeId in this.root.gameMode.getUpgrades()) { + const handle = {}; + handle.requireIndexToElement = []; + + // Wrapper + handle.elem = makeDiv(this.contentDiv, null, ["upgrade"]); + handle.elem.setAttribute("data-upgrade-id", upgradeId); + + // Title + const title = makeDiv(handle.elem, null, ["title"], T.shopUpgrades[upgradeId].name); + + // Title > Tier + handle.elemTierLabel = makeDiv(title, null, ["tier"]); + + // Icon + handle.icon = makeDiv(handle.elem, null, ["icon"]); + handle.icon.setAttribute("data-icon", "upgrades/" + upgradeId + ".png"); + + // Description + handle.elemDescription = makeDiv(handle.elem, null, ["description"], "??"); + handle.elemRequirements = makeDiv(handle.elem, null, ["requirements"]); + + // Buy button + handle.buyButton = document.createElement("button"); + handle.buyButton.classList.add("buy", "styledButton"); + handle.buyButton.innerText = T.ingame.shop.buttonUnlock; + handle.elem.appendChild(handle.buyButton); + + this.trackClicks(handle.buyButton, () => this.tryUnlockNextTier(upgradeId)); + + // Assign handle + this.upgradeToElements[upgradeId] = handle; + } + } + + rerenderFull() { + for (const upgradeId in this.upgradeToElements) { + const handle = this.upgradeToElements[upgradeId]; + const upgradeTiers = this.root.gameMode.getUpgrades()[upgradeId]; + + const currentTier = this.root.hubGoals.getUpgradeLevel(upgradeId); + const currentTierMultiplier = this.root.hubGoals.upgradeImprovements[upgradeId]; + const tierHandle = upgradeTiers[currentTier]; + + // Set tier + handle.elemTierLabel.innerText = T.ingame.shop.tier.replace( + "", + getRomanNumber(currentTier + 1) + ); + + handle.elemTierLabel.setAttribute("data-tier", currentTier); + + // Cleanup detectors + for (let i = 0; i < handle.requireIndexToElement.length; ++i) { + const requiredHandle = handle.requireIndexToElement[i]; + requiredHandle.container.remove(); + requiredHandle.pinDetector.cleanup(); + requiredHandle.infoDetector.cleanup(); + } + + // Cleanup + handle.requireIndexToElement = []; + + handle.elem.classList.toggle("maxLevel", !tierHandle); + + if (!tierHandle) { + // Max level + handle.elemDescription.innerText = T.ingame.shop.maximumLevel.replace( + "", + formatBigNumber(currentTierMultiplier) + ); + continue; + } + + // Set description + handle.elemDescription.innerText = T.shopUpgrades[upgradeId].description + .replace("", formatBigNumber(currentTierMultiplier)) + .replace("", formatBigNumber(currentTierMultiplier + tierHandle.improvement)); + + tierHandle.required.forEach(({ shape, amount }) => { + const container = makeDiv(handle.elemRequirements, null, ["requirement"]); + + const shapeDef = this.root.shapeDefinitionMgr.getShapeFromShortKey(shape); + const shapeCanvas = shapeDef.generateAsCanvas(120); + shapeCanvas.classList.add(); + container.appendChild(shapeCanvas); + + const progressContainer = makeDiv(container, null, ["amount"]); + const progressBar = document.createElement("label"); + progressBar.classList.add("progressBar"); + progressContainer.appendChild(progressBar); + + const progressLabel = document.createElement("label"); + progressContainer.appendChild(progressLabel); + + const pinButton = document.createElement("button"); + pinButton.classList.add("pin"); + container.appendChild(pinButton); + + const viewInfoButton = document.createElement("button"); + viewInfoButton.classList.add("showInfo"); + container.appendChild(viewInfoButton); + + const currentGoalShape = this.root.hubGoals.currentGoal.definition.getHash(); + if (shape === currentGoalShape) { + pinButton.classList.add("isGoal"); + } else if (this.root.hud.parts.pinnedShapes.isShapePinned(shape)) { + pinButton.classList.add("alreadyPinned"); + } + + const pinDetector = new ClickDetector(pinButton, { + consumeEvents: true, + preventDefault: true, + }); + pinDetector.click.add(() => { + if (this.root.hud.parts.pinnedShapes.isShapePinned(shape)) { + this.root.hud.signals.shapeUnpinRequested.dispatch(shape); + pinButton.classList.add("unpinned"); + pinButton.classList.remove("pinned", "alreadyPinned"); + } else { + this.root.hud.signals.shapePinRequested.dispatch(shapeDef); + pinButton.classList.add("pinned"); + pinButton.classList.remove("unpinned"); + } + }); + + const infoDetector = new ClickDetector(viewInfoButton, { + consumeEvents: true, + preventDefault: true, + }); + infoDetector.click.add(() => + this.root.hud.signals.viewShapeDetailsRequested.dispatch(shapeDef) + ); + + handle.requireIndexToElement.push({ + container, + progressLabel, + progressBar, + definition: shapeDef, + required: amount, + pinDetector, + infoDetector, + }); + }); + } + } + + renderCountsAndStatus() { + for (const upgradeId in this.upgradeToElements) { + const handle = this.upgradeToElements[upgradeId]; + for (let i = 0; i < handle.requireIndexToElement.length; ++i) { + const { progressLabel, progressBar, definition, required } = handle.requireIndexToElement[i]; + + const haveAmount = this.root.hubGoals.getShapesStored(definition); + const progress = Math.min(haveAmount / required, 1.0); + + progressLabel.innerText = formatBigNumber(haveAmount) + " / " + formatBigNumber(required); + progressBar.style.width = progress * 100.0 + "%"; + progressBar.classList.toggle("complete", progress >= 1.0); + } + + handle.buyButton.classList.toggle("buyable", this.root.hubGoals.canUnlockUpgrade(upgradeId)); + } + } + + initialize() { + this.domAttach = new DynamicDomAttach(this.root, this.background, { + attachClass: "visible", + }); + + this.inputReciever = new InputReceiver("shop"); + this.keyActionMapper = new KeyActionMapper(this.root, this.inputReciever); + + this.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.close, this); + this.keyActionMapper.getBinding(KEYMAPPINGS.ingame.menuClose).add(this.close, this); + this.keyActionMapper.getBinding(KEYMAPPINGS.ingame.menuOpenShop).add(this.close, this); + + this.close(); + + this.rerenderFull(); + this.root.signals.upgradePurchased.add(this.rerenderFull, this); + } + + cleanup() { + // Cleanup detectors + for (const upgradeId in this.upgradeToElements) { + const handle = this.upgradeToElements[upgradeId]; + for (let i = 0; i < handle.requireIndexToElement.length; ++i) { + const requiredHandle = handle.requireIndexToElement[i]; + requiredHandle.container.remove(); + requiredHandle.pinDetector.cleanup(); + requiredHandle.infoDetector.cleanup(); + } + handle.requireIndexToElement = []; + } + } + + show() { + this.visible = true; + this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); + this.rerenderFull(); + } + + close() { + this.visible = false; + this.root.app.inputMgr.makeSureDetached(this.inputReciever); + this.update(); + } + + update() { + this.domAttach.update(this.visible); + if (this.visible) { + this.renderCountsAndStatus(); + } + } + + tryUnlockNextTier(upgradeId) { + // Nothing + this.root.hubGoals.tryUnlockUpgrade(upgradeId); + } + + isBlockingOverlay() { + return this.visible; + } +} diff --git a/src/js/game/hud/parts/standalone_advantages.js b/src/js/game/hud/parts/standalone_advantages.js new file mode 100644 index 00000000..4e39e005 --- /dev/null +++ b/src/js/game/hud/parts/standalone_advantages.js @@ -0,0 +1,85 @@ +import { A_B_TESTING_LINK_TYPE, THIRDPARTY_URLS } from "../../../core/config"; +import { InputReceiver } from "../../../core/input_receiver"; +import { makeDiv } from "../../../core/utils"; +import { T } from "../../../translations"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; + +const showIntervalSeconds = 30 * 60; + +export class HUDStandaloneAdvantages extends BaseHUDPart { + createElements(parent) { + this.background = makeDiv(parent, "ingame_HUD_StandaloneAdvantages", ["ingameDialog"]); + + // DIALOG Inner / Wrapper + this.dialogInner = makeDiv(this.background, null, ["dialogInner"]); + this.title = makeDiv(this.dialogInner, null, ["title"], T.ingame.standaloneAdvantages.title); + this.contentDiv = makeDiv( + this.dialogInner, + null, + ["content"], + ` +
+ ${Object.entries(T.ingame.standaloneAdvantages.points) + .map( + ([key, trans]) => ` +
+ ${trans.title} +

${trans.desc}

+
` + ) + .join("")} + +
+ +
+ + +
+ ` + ); + + this.trackClicks(this.contentDiv.querySelector("button.steamLinkButton"), () => { + this.root.app.analytics.trackUiClick("standalone_advantage_visit_steam"); + this.root.app.platformWrapper.openExternalLink( + THIRDPARTY_URLS.standaloneStorePage + "?ref=savs&prc=" + A_B_TESTING_LINK_TYPE + ); + this.close(); + }); + this.trackClicks(this.contentDiv.querySelector("button.otherCloseButton"), () => { + this.root.app.analytics.trackUiClick("standalone_advantage_no_thanks"); + this.close(); + }); + } + + initialize() { + this.domAttach = new DynamicDomAttach(this.root, this.background, { + attachClass: "visible", + }); + + this.inputReciever = new InputReceiver("standalone-advantages"); + this.close(); + + this.lastShown = this.root.gameIsFresh ? this.root.time.now() : 0; + } + + show() { + this.lastShown = this.root.time.now(); + this.visible = true; + this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); + } + + close() { + this.visible = false; + this.root.app.inputMgr.makeSureDetached(this.inputReciever); + this.update(); + } + + update() { + if (!this.visible && this.root.time.now() - this.lastShown > showIntervalSeconds) { + this.show(); + } + + 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..a28ed288 100644 --- a/src/js/game/hud/parts/statistics.js +++ b/src/js/game/hud/parts/statistics.js @@ -1,12 +1,20 @@ 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"; import { DynamicDomAttach } from "../dynamic_dom_attach"; -import { enumDisplayMode, HUDShapeStatisticsHandle } from "./statistics_handle"; +import { enumDisplayMode, HUDShapeStatisticsHandle, statisticsUnitsSeconds } 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,13 @@ export class HUDStatistics extends BaseHUDPart { this.trackClicks(button, () => this.setDataSource(dataSource)); } + const buttonIterateUnit = makeButton(this.filtersDisplayMode, ["displayIterateUnit"]); + const buttonDisplaySorted = makeButton(this.filtersDisplayMode, ["displaySorted"]); const buttonDisplayDetailed = makeButton(this.filtersDisplayMode, ["displayDetailed"]); const buttonDisplayIcons = makeButton(this.filtersDisplayMode, ["displayIcons"]); + this.trackClicks(buttonIterateUnit, () => this.iterateUnit()); + this.trackClicks(buttonDisplaySorted, () => this.toggleSorted()); this.trackClicks(buttonDisplayIcons, () => this.setDisplayMode(enumDisplayMode.icons)); this.trackClicks(buttonDisplayDetailed, () => this.setDisplayMode(enumDisplayMode.detailed)); @@ -72,6 +84,32 @@ 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); + } + + /** + * Chooses the next unit + */ + iterateUnit() { + const units = Array.from(Object.keys(statisticsUnitsSeconds)); + const newIndex = (units.indexOf(this.currentUnit) + 1) % units.length; + this.currentUnit = units[newIndex]; + + this.rerenderPartial(); + } + initialize() { this.domAttach = new DynamicDomAttach(this.root, this.background, { attachClass: "visible", @@ -87,6 +125,9 @@ export class HUDStatistics extends BaseHUDPart { /** @type {Object.} */ this.activeHandles = {}; + this.currentUnit = "second"; + + this.setSorted(true); this.setDataSource(enumAnalyticsDataSource.produced); this.setDisplayMode(enumDisplayMode.detailed); @@ -110,13 +151,12 @@ export class HUDStatistics extends BaseHUDPart { } } - cleanup() { - document.body.classList.remove("ingameDialogOpen"); + isBlockingOverlay() { + return this.visible; } show() { this.visible = true; - document.body.classList.add("ingameDialogOpen"); this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); this.rerenderFull(); this.update(); @@ -124,7 +164,6 @@ export class HUDStatistics extends BaseHUDPart { close() { this.visible = false; - document.body.classList.remove("ingameDialogOpen"); this.root.app.inputMgr.makeSureDetached(this.inputReciever); this.update(); } @@ -147,7 +186,7 @@ export class HUDStatistics extends BaseHUDPart { rerenderPartial() { for (const key in this.activeHandles) { const handle = this.activeHandles[key]; - handle.update(this.displayMode, this.dataSource); + handle.update(this.displayMode, this.dataSource, this.currentUnit); } } @@ -175,7 +214,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..a64a5f5b 100644 --- a/src/js/game/hud/parts/statistics_handle.js +++ b/src/js/game/hud/parts/statistics_handle.js @@ -12,6 +12,16 @@ export const enumDisplayMode = { detailed: "detailed", }; +/** + * Stores how many seconds one unit is + * @type {Object} + */ +export const statisticsUnitsSeconds = { + second: 1, + minute: 60, + hour: 3600, +}; + /** * Simple wrapper for a shape definition within the shape statistics */ @@ -64,9 +74,10 @@ export class HUDShapeStatisticsHandle { * * @param {enumDisplayMode} displayMode * @param {enumAnalyticsDataSource} dataSource + * @param {string} unit * @param {boolean=} forced */ - update(displayMode, dataSource, forced = false) { + update(displayMode, dataSource, unit, forced = false) { if (!this.element) { return; } @@ -74,6 +85,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( @@ -84,18 +100,13 @@ export class HUDShapeStatisticsHandle { case enumAnalyticsDataSource.delivered: case enumAnalyticsDataSource.produced: { let rate = - (this.root.productionAnalytics.getCurrentShapeRate(dataSource, this.definition) / - globalConfig.analyticsSliceDurationSeconds) * - 60; - this.counter.innerText = T.ingame.statistics.shapesPerMinute.replace( + this.root.productionAnalytics.getCurrentShapeRate(dataSource, this.definition) / + globalConfig.analyticsSliceDurationSeconds; + + this.counter.innerText = T.ingame.statistics.shapesDisplayUnits[unit].replace( "", - formatBigNumber(rate) + formatBigNumber(rate * statisticsUnitsSeconds[unit]) ); - - if (G_IS_DEV && globalConfig.debug.detailedStatistics) { - this.counter.innerText = "" + round2Digits(rate / 60) + " /s"; - } - break; } } diff --git a/src/js/game/hud/parts/tutorial_hints.js b/src/js/game/hud/parts/tutorial_hints.js index 428923d0..c9499f85 100644 --- a/src/js/game/hud/parts/tutorial_hints.js +++ b/src/js/game/hud/parts/tutorial_hints.js @@ -1,109 +1,106 @@ -import { InputReceiver } from "../../../core/input_receiver"; -import { TrackedState } from "../../../core/tracked_state"; -import { makeDiv } from "../../../core/utils"; -import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper"; -import { BaseHUDPart } from "../base_hud_part"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; -import { T } from "../../../translations"; - -const tutorialVideos = [2, 3, 4, 5, 6, 7, 9, 10, 11]; - -export class HUDPartTutorialHints extends BaseHUDPart { - createElements(parent) { - this.element = makeDiv( - parent, - "ingame_HUD_TutorialHints", - [], - ` -
- ${T.ingame.tutorialHints.title} - -
- - - ` - ); - - this.videoElement = this.element.querySelector("video"); - } - - shouldPauseGame() { - return this.enlarged; - } - - initialize() { - this.trackClicks(this.element.querySelector(".toggleHint"), this.toggleHintEnlarged); - - this.videoAttach = new DynamicDomAttach(this.root, this.videoElement, { - timeToKeepSeconds: 0.3, - }); - - this.videoAttach.update(false); - this.enlarged = false; - - this.inputReciever = new InputReceiver("tutorial_hints"); - this.keyActionMapper = new KeyActionMapper(this.root, this.inputReciever); - this.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.close, this); - - this.domAttach = new DynamicDomAttach(this.root, this.element); - - this.currentShownLevel = new TrackedState(this.updateVideoUrl, this); - } - - updateVideoUrl(level) { - if (tutorialVideos.indexOf(level) < 0) { - this.videoElement.querySelector("source").setAttribute("src", ""); - this.videoElement.pause(); - } else { - this.videoElement - .querySelector("source") - .setAttribute("src", "https://static.shapez.io/tutorial_videos/level_" + level + ".webm"); - this.videoElement.currentTime = 0; - this.videoElement.load(); - } - } - - close() { - this.enlarged = false; - document.body.classList.remove("ingameDialogOpen"); - this.element.classList.remove("enlarged", "noBlur"); - this.root.app.inputMgr.makeSureDetached(this.inputReciever); - this.update(); - } - - show() { - this.root.app.analytics.trackUiClick("tutorial_hint_show"); - this.root.app.analytics.trackUiClick("tutorial_hint_show_lvl_" + this.root.hubGoals.level); - - document.body.classList.add("ingameDialogOpen"); - this.element.classList.add("enlarged", "noBlur"); - this.enlarged = true; - this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); - this.update(); - - this.videoElement.currentTime = 0; - this.videoElement.play(); - } - - update() { - this.videoAttach.update(this.enlarged); - - this.currentShownLevel.set(this.root.hubGoals.level); - - const tutorialVisible = tutorialVideos.indexOf(this.root.hubGoals.level) >= 0; - this.domAttach.update(tutorialVisible); - } - - toggleHintEnlarged() { - if (this.enlarged) { - this.close(); - } else { - this.show(); - } - } -} +import { InputReceiver } from "../../../core/input_receiver"; +import { TrackedState } from "../../../core/tracked_state"; +import { makeDiv } from "../../../core/utils"; +import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; +import { T } from "../../../translations"; + +const tutorialVideos = [2, 3, 4, 5, 6, 7, 9, 10, 11]; + +export class HUDPartTutorialHints extends BaseHUDPart { + createElements(parent) { + this.element = makeDiv( + parent, + "ingame_HUD_TutorialHints", + [], + ` +
+ ${T.ingame.tutorialHints.title} + +
+ + + ` + ); + + this.videoElement = this.element.querySelector("video"); + } + + shouldPauseGame() { + return this.enlarged; + } + + initialize() { + this.trackClicks(this.element.querySelector(".toggleHint"), this.toggleHintEnlarged); + + this.videoAttach = new DynamicDomAttach(this.root, this.videoElement, { + timeToKeepSeconds: 0.3, + }); + + this.videoAttach.update(false); + this.enlarged = false; + + this.inputReciever = new InputReceiver("tutorial_hints"); + this.keyActionMapper = new KeyActionMapper(this.root, this.inputReciever); + this.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.close, this); + + this.domAttach = new DynamicDomAttach(this.root, this.element); + + this.currentShownLevel = new TrackedState(this.updateVideoUrl, this); + } + + updateVideoUrl(level) { + if (tutorialVideos.indexOf(level) < 0) { + this.videoElement.querySelector("source").setAttribute("src", ""); + this.videoElement.pause(); + } else { + this.videoElement + .querySelector("source") + .setAttribute("src", "https://static.shapez.io/tutorial_videos/level_" + level + ".webm"); + this.videoElement.currentTime = 0; + this.videoElement.load(); + } + } + + close() { + this.enlarged = false; + this.element.classList.remove("enlarged", "noBlur"); + this.root.app.inputMgr.makeSureDetached(this.inputReciever); + this.update(); + } + + show() { + this.root.app.analytics.trackUiClick("tutorial_hint_show"); + this.root.app.analytics.trackUiClick("tutorial_hint_show_lvl_" + this.root.hubGoals.level); + this.element.classList.add("enlarged", "noBlur"); + this.enlarged = true; + this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); + this.update(); + + this.videoElement.currentTime = 0; + this.videoElement.play(); + } + + update() { + this.videoAttach.update(this.enlarged); + + this.currentShownLevel.set(this.root.hubGoals.level); + + const tutorialVisible = tutorialVideos.indexOf(this.root.hubGoals.level) >= 0; + this.domAttach.update(tutorialVisible); + } + + toggleHintEnlarged() { + if (this.enlarged) { + this.close(); + } else { + this.show(); + } + } +} diff --git a/src/js/game/hud/parts/tutorial_video_offer.js b/src/js/game/hud/parts/tutorial_video_offer.js new file mode 100644 index 00000000..3cd2cb90 --- /dev/null +++ b/src/js/game/hud/parts/tutorial_video_offer.js @@ -0,0 +1,34 @@ +import { THIRDPARTY_URLS } from "../../../core/config"; +import { T } from "../../../translations"; +import { BaseHUDPart } from "../base_hud_part"; + +/** + * Offers to open the tutorial video after completing a level + */ +export class HUDTutorialVideoOffer extends BaseHUDPart { + createElements() {} + + initialize() { + this.root.hud.signals.unlockNotificationFinished.add(() => { + const level = this.root.hubGoals.level; + const tutorialVideoLink = THIRDPARTY_URLS.levelTutorialVideos[level]; + if (tutorialVideoLink) { + const isForeign = this.root.app.settings.getLanguage() !== "en"; + const dialogData = isForeign + ? T.dialogs.tutorialVideoAvailableForeignLanguage + : T.dialogs.tutorialVideoAvailable; + + const { ok } = this.root.hud.parts.dialogs.showInfo(dialogData.title, dialogData.desc, [ + "cancel:bad", + "ok:good", + ]); + + this.root.app.analytics.trackUiClick("ingame_video_link_show_" + level); + ok.add(() => { + this.root.app.platformWrapper.openExternalLink(tutorialVideoLink); + this.root.app.analytics.trackUiClick("ingame_video_link_open_" + level); + }); + } + }); + } +} diff --git a/src/js/game/hud/parts/unlock_notification.js b/src/js/game/hud/parts/unlock_notification.js index 7a5c923b..98549784 100644 --- a/src/js/game/hud/parts/unlock_notification.js +++ b/src/js/game/hud/parts/unlock_notification.js @@ -1,156 +1,174 @@ -import { globalConfig } from "../../../core/config"; -import { gMetaBuildingRegistry } from "../../../core/global_registries"; -import { makeDiv } from "../../../core/utils"; -import { SOUNDS } from "../../../platform/sound"; -import { T } from "../../../translations"; -import { defaultBuildingVariant } from "../../meta_building"; -import { enumHubGoalRewards } from "../../tutorial_goals"; -import { BaseHUDPart } from "../base_hud_part"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; -import { enumHubGoalRewardsToContentUnlocked } from "../../tutorial_goals_mappings"; -import { InputReceiver } from "../../../core/input_receiver"; - -export class HUDUnlockNotification extends BaseHUDPart { - initialize() { - this.visible = false; - - this.domAttach = new DynamicDomAttach(this.root, this.element, { - timeToKeepSeconds: 0, - }); - - if (!(G_IS_DEV && globalConfig.debug.disableUnlockDialog)) { - this.root.signals.storyGoalCompleted.add(this.showForLevel, this); - } - - this.buttonShowTimeout = null; - } - - createElements(parent) { - this.inputReciever = new InputReceiver("unlock-notification"); - - this.element = makeDiv(parent, "ingame_HUD_UnlockNotification", ["noBlur"]); - - const dialog = makeDiv(this.element, null, ["dialog"]); - - this.elemTitle = makeDiv(dialog, null, ["title"]); - this.elemSubTitle = makeDiv(dialog, null, ["subTitle"], T.ingame.levelCompleteNotification.completed); - - this.elemContents = makeDiv(dialog, null, ["contents"]); - - this.btnClose = document.createElement("button"); - this.btnClose.classList.add("close", "styledButton"); - this.btnClose.innerText = T.ingame.levelCompleteNotification.buttonNextLevel; - dialog.appendChild(this.btnClose); - - this.trackClicks(this.btnClose, this.requestClose); - } - - /** - * @param {number} level - * @param {enumHubGoalRewards} reward - */ - showForLevel(level, reward) { - this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); - this.elemTitle.innerText = T.ingame.levelCompleteNotification.levelTitle.replace( - "", - ("" + level).padStart(2, "0") - ); - - const rewardName = T.storyRewards[reward].title; - - let html = ` -
- ${T.ingame.levelCompleteNotification.unlockText.replace("", rewardName)} -
- -
- ${T.storyRewards[reward].desc} -
- - `; - - html += "
"; - const gained = enumHubGoalRewardsToContentUnlocked[reward]; - if (gained) { - gained.forEach(([metaBuildingClass, variant]) => { - const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass); - html += `
`; - }); - } - html += "
"; - - this.elemContents.innerHTML = html; - this.visible = true; - this.root.soundProxy.playUi(SOUNDS.levelComplete); - - if (this.buttonShowTimeout) { - clearTimeout(this.buttonShowTimeout); - } - - this.element.querySelector("button.close").classList.remove("unlocked"); - - if (this.root.app.settings.getAllSettings().offerHints) { - this.buttonShowTimeout = setTimeout( - () => this.element.querySelector("button.close").classList.add("unlocked"), - G_IS_DEV ? 100 : 5000 - ); - } else { - this.element.querySelector("button.close").classList.add("unlocked"); - } - } - - cleanup() { - this.root.app.inputMgr.makeSureDetached(this.inputReciever); - if (this.buttonShowTimeout) { - clearTimeout(this.buttonShowTimeout); - this.buttonShowTimeout = null; - } - } - - requestClose() { - this.root.app.adProvider.showVideoAd().then(() => { - this.close(); - - if (!this.root.app.settings.getAllSettings().offerHints) { - return; - } - - if (this.root.hubGoals.level === 3) { - const { showUpgrades } = this.root.hud.parts.dialogs.showInfo( - T.dialogs.upgradesIntroduction.title, - T.dialogs.upgradesIntroduction.desc, - ["showUpgrades:good:timeout"] - ); - showUpgrades.add(() => this.root.hud.parts.shop.show()); - } - - if (this.root.hubGoals.level === 5) { - const { showKeybindings } = this.root.hud.parts.dialogs.showInfo( - T.dialogs.keybindingsIntroduction.title, - T.dialogs.keybindingsIntroduction.desc, - ["showKeybindings:misc", "ok:good:timeout"] - ); - showKeybindings.add(() => this.root.gameState.goToKeybindings()); - } - }); - } - - close() { - this.root.app.inputMgr.makeSureDetached(this.inputReciever); - if (this.buttonShowTimeout) { - clearTimeout(this.buttonShowTimeout); - this.buttonShowTimeout = null; - } - this.visible = false; - } - - update() { - this.domAttach.update(this.visible); - if (!this.visible && this.buttonShowTimeout) { - clearTimeout(this.buttonShowTimeout); - this.buttonShowTimeout = null; - } - } -} +import { globalConfig } from "../../../core/config"; +import { gMetaBuildingRegistry } from "../../../core/global_registries"; +import { InputReceiver } from "../../../core/input_receiver"; +import { makeDiv } from "../../../core/utils"; +import { SOUNDS } from "../../../platform/sound"; +import { T } from "../../../translations"; +import { defaultBuildingVariant } from "../../meta_building"; +import { enumHubGoalRewards } from "../../tutorial_goals"; +import { enumHubGoalRewardsToContentUnlocked } from "../../tutorial_goals_mappings"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; +import { enumNotificationType } from "./notifications"; + +export class HUDUnlockNotification extends BaseHUDPart { + initialize() { + this.visible = false; + + this.domAttach = new DynamicDomAttach(this.root, this.element, { + timeToKeepSeconds: 0, + }); + + if (!(G_IS_DEV && globalConfig.debug.disableUnlockDialog)) { + this.root.signals.storyGoalCompleted.add(this.showForLevel, this); + } + + this.buttonShowTimeout = null; + } + + createElements(parent) { + this.inputReciever = new InputReceiver("unlock-notification"); + + this.element = makeDiv(parent, "ingame_HUD_UnlockNotification", ["noBlur"]); + + const dialog = makeDiv(this.element, null, ["dialog"]); + + this.elemTitle = makeDiv(dialog, null, ["title"]); + this.elemSubTitle = makeDiv(dialog, null, ["subTitle"], T.ingame.levelCompleteNotification.completed); + + this.elemContents = makeDiv(dialog, null, ["contents"]); + + this.btnClose = document.createElement("button"); + this.btnClose.classList.add("close", "styledButton"); + this.btnClose.innerText = T.ingame.levelCompleteNotification.buttonNextLevel; + dialog.appendChild(this.btnClose); + + this.trackClicks(this.btnClose, this.requestClose); + } + + /** + * @param {number} level + * @param {enumHubGoalRewards} reward + */ + showForLevel(level, reward) { + this.root.soundProxy.playUi(SOUNDS.levelComplete); + + const levels = this.root.gameMode.getLevelDefinitions(); + // Don't use getIsFreeplay() because we want the freeplay level up to show + if (level > levels.length) { + this.root.hud.signals.notification.dispatch( + T.ingame.notifications.freeplayLevelComplete.replace("", String(level)), + enumNotificationType.success + ); + return; + } + + this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); + this.elemTitle.innerText = T.ingame.levelCompleteNotification.levelTitle.replace( + "", + ("" + level).padStart(2, "0") + ); + + const rewardName = T.storyRewards[reward].title; + + let html = ` +
+ ${T.ingame.levelCompleteNotification.unlockText.replace("", rewardName)} +
+ +
+ ${T.storyRewards[reward].desc} +
+ + `; + + html += "
"; + const gained = enumHubGoalRewardsToContentUnlocked[reward]; + if (gained) { + gained.forEach(([metaBuildingClass, variant]) => { + const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass); + html += `
`; + }); + } + html += "
"; + + this.elemContents.innerHTML = html; + this.visible = true; + + if (this.buttonShowTimeout) { + clearTimeout(this.buttonShowTimeout); + } + + this.element.querySelector("button.close").classList.remove("unlocked"); + + if (this.root.app.settings.getAllSettings().offerHints) { + this.buttonShowTimeout = setTimeout( + () => this.element.querySelector("button.close").classList.add("unlocked"), + G_IS_DEV ? 100 : 5000 + ); + } else { + this.element.querySelector("button.close").classList.add("unlocked"); + } + } + + cleanup() { + this.root.app.inputMgr.makeSureDetached(this.inputReciever); + if (this.buttonShowTimeout) { + clearTimeout(this.buttonShowTimeout); + this.buttonShowTimeout = null; + } + } + + isBlockingOverlay() { + return this.visible; + } + + requestClose() { + this.root.app.adProvider.showVideoAd().then(() => { + this.close(); + + this.root.hud.signals.unlockNotificationFinished.dispatch(); + + if (!this.root.app.settings.getAllSettings().offerHints) { + return; + } + + if (this.root.hubGoals.level === 3) { + const { showUpgrades } = this.root.hud.parts.dialogs.showInfo( + T.dialogs.upgradesIntroduction.title, + T.dialogs.upgradesIntroduction.desc, + ["showUpgrades:good:timeout"] + ); + showUpgrades.add(() => this.root.hud.parts.shop.show()); + } + + if (this.root.hubGoals.level === 5) { + const { showKeybindings } = this.root.hud.parts.dialogs.showInfo( + T.dialogs.keybindingsIntroduction.title, + T.dialogs.keybindingsIntroduction.desc, + ["showKeybindings:misc", "ok:good:timeout"] + ); + showKeybindings.add(() => this.root.gameState.goToKeybindings()); + } + }); + } + + close() { + this.root.app.inputMgr.makeSureDetached(this.inputReciever); + if (this.buttonShowTimeout) { + clearTimeout(this.buttonShowTimeout); + this.buttonShowTimeout = null; + } + this.visible = false; + } + + update() { + this.domAttach.update(this.visible); + if (!this.visible && this.buttonShowTimeout) { + clearTimeout(this.buttonShowTimeout); + this.buttonShowTimeout = null; + } + } +} diff --git a/src/js/game/hud/parts/watermark.js b/src/js/game/hud/parts/watermark.js index d10bc07c..4a75ea76 100644 --- a/src/js/game/hud/parts/watermark.js +++ b/src/js/game/hud/parts/watermark.js @@ -1,44 +1,72 @@ -import { BaseHUDPart } from "../base_hud_part"; -import { DrawParameters } from "../../../core/draw_parameters"; -import { makeDiv } from "../../../core/utils"; -import { THIRDPARTY_URLS } from "../../../core/config"; -import { T } from "../../../translations"; - -export class HUDWatermark extends BaseHUDPart { - createElements(parent) { - this.element = makeDiv(parent, "ingame_HUD_Watermark"); - } - - initialize() { - this.trackClicks(this.element, this.onWatermarkClick); - } - - onWatermarkClick() { - this.root.app.analytics.trackUiClick("watermark_click_2"); - this.root.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.standaloneStorePage); - } - - /** - * - * @param {DrawParameters} parameters - */ - drawOverlays(parameters) { - const w = this.root.gameWidth; - const x = 280 * this.root.app.getEffectiveUiScale(); - - parameters.context.fillStyle = "#f77"; - parameters.context.font = "bold " + this.root.app.getEffectiveUiScale() * 17 + "px GameFont"; - // parameters.context.textAlign = "center"; - parameters.context.fillText( - T.demoBanners.title.toUpperCase(), - x, - this.root.app.getEffectiveUiScale() * 27 - ); - - parameters.context.font = "bold " + this.root.app.getEffectiveUiScale() * 12 + "px GameFont"; - // parameters.context.textAlign = "center"; - parameters.context.fillText(T.demoBanners.intro, x, this.root.app.getEffectiveUiScale() * 45); - - // parameters.context.textAlign = "left"; - } -} +import { THIRDPARTY_URLS } from "../../../core/config"; +import { makeDiv } from "../../../core/utils"; +import { T } from "../../../translations"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; + +const watermarkShowIntervalSeconds = G_IS_DEV ? 120 : 7 * 60; +const watermarkShowDuration = 5; + +export class HUDWatermark extends BaseHUDPart { + createElements(parent) { + this.element = makeDiv( + parent, + "ingame_HUD_Watermark", + [], + ` + ${T.ingame.watermark.title} +

${T.ingame.watermark.desc}

+ ` + ); + + this.linkElement = makeDiv( + parent, + "ingame_HUD_WatermarkClicker", + [], + T.ingame.watermark.get_on_steam + ); + this.trackClicks(this.linkElement, () => { + this.root.app.analytics.trackUiClick("watermark_click_2_direct"); + this.root.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.standaloneStorePage + "?ref=wtmd"); + }); + } + + initialize() { + this.trackClicks(this.element, this.onWatermarkClick); + + this.domAttach = new DynamicDomAttach(this.root, this.element, { + attachClass: "visible", + timeToKeepSeconds: 0.5, + }); + } + + update() { + this.domAttach.update( + this.root.time.realtimeNow() % watermarkShowIntervalSeconds < watermarkShowDuration + ); + } + + onWatermarkClick() { + this.root.app.analytics.trackUiClick("watermark_click_2_new"); + this.root.hud.parts.standaloneAdvantages.show(); + } + + /** + * + * @param {import("../../../core/draw_utils").DrawParameters} parameters + */ + drawOverlays(parameters) { + const w = this.root.gameWidth; + + parameters.context.fillStyle = "rgba(230, 230, 230, 0.9)"; + parameters.context.font = "bold " + this.root.app.getEffectiveUiScale() * 40 + "px GameFont"; + parameters.context.textAlign = "center"; + parameters.context.fillText( + T.demoBanners.title.toUpperCase(), + w / 2, + this.root.app.getEffectiveUiScale() * 50 + ); + + parameters.context.textAlign = "left"; + } +} diff --git a/src/js/game/hud/parts/waypoints.js b/src/js/game/hud/parts/waypoints.js index 8cab85c5..a6f37b93 100644 --- a/src/js/game/hud/parts/waypoints.js +++ b/src/js/game/hud/parts/waypoints.js @@ -1,556 +1,630 @@ -import { makeOffscreenBuffer } from "../../../core/buffer_utils"; -import { globalConfig, IS_DEMO } from "../../../core/config"; -import { DrawParameters } from "../../../core/draw_parameters"; -import { Loader } from "../../../core/loader"; -import { DialogWithForm } from "../../../core/modal_dialog_elements"; -import { FormElementInput } from "../../../core/modal_dialog_forms"; -import { Rectangle } from "../../../core/rectangle"; -import { STOP_PROPAGATION } from "../../../core/signal"; -import { arrayDeleteValue, lerp, makeDiv, removeAllChildren, clamp } from "../../../core/utils"; -import { Vector } from "../../../core/vector"; -import { T } from "../../../translations"; -import { enumMouseButton } from "../../camera"; -import { KEYMAPPINGS } from "../../key_action_mapper"; -import { BaseHUDPart } from "../base_hud_part"; -import { DynamicDomAttach } from "../dynamic_dom_attach"; -import { enumNotificationType } from "./notifications"; -import { ShapeDefinition } from "../../shape_definition"; - -/** @typedef {{ - * label: string | null, - * center: { x: number, y: number }, - * zoomLevel: number - * }} Waypoint */ - -/** - * Used when a shape icon is rendered instead - */ -const SHAPE_LABEL_PLACEHOLDER = " "; - -const MAX_LABEL_LENGTH = 71; - -export class HUDWaypoints extends BaseHUDPart { - /** - * Creates the overview of waypoints - * @param {HTMLElement} parent - */ - createElements(parent) { - // Create the helper box on the lower right when zooming out - if (this.root.app.settings.getAllSettings().offerHints) { - this.hintElement = makeDiv( - parent, - "ingame_HUD_Waypoints_Hint", - [], - ` - ${T.ingame.waypoints.waypoints} - ${T.ingame.waypoints.description.replace( - "", - `${this.root.keyMapper - .getBinding(KEYMAPPINGS.navigation.createMarker) - .getKeyCodeString()}` - )} - ` - ); - } - - // Create the waypoint list on the upper right - this.waypointsListElement = makeDiv(parent, "ingame_HUD_Waypoints", [], "Waypoints"); - } - - /** - * Serializes the waypoints - */ - serialize() { - return { - waypoints: this.waypoints, - }; - } - - /** - * Deserializes the waypoints - * @param {{waypoints: Array}} data - */ - deserialize(data) { - if (!data || !data.waypoints || !Array.isArray(data.waypoints)) { - return "Invalid waypoints data"; - } - this.waypoints = data.waypoints; - this.rerenderWaypointList(); - } - - /** - * Initializes everything - */ - initialize() { - // Cache the sprite for the waypoints - this.waypointSprite = Loader.getSprite("sprites/misc/waypoint.png"); - this.directionIndicatorSprite = Loader.getSprite("sprites/misc/hub_direction_indicator.png"); - - /** @type {Array} - */ - this.waypoints = [ - { - label: null, - center: { x: 0, y: 0 }, - zoomLevel: 3, - }, - ]; - - // Create a buffer we can use to measure text - this.dummyBuffer = makeOffscreenBuffer(1, 1, { - reusable: false, - label: "waypoints-measure-canvas", - })[1]; - - // Dynamically attach/detach the lower right hint in the map overview - if (this.hintElement) { - this.domAttach = new DynamicDomAttach(this.root, this.hintElement); - } - - // Catch mouse and key events - this.root.camera.downPreHandler.add(this.onMouseDown, this); - this.root.keyMapper - .getBinding(KEYMAPPINGS.navigation.createMarker) - .add(() => this.requestSaveMarker({})); - - /** - * Stores at how much opacity the markers should be rendered on the map. - * This is interpolated over multiple frames so we have some sort of fade effect - */ - this.currentMarkerOpacity = 1; - this.currentCompassOpacity = 0; - - // Create buffer which is used to indicate the hub direction - const [canvas, context] = makeOffscreenBuffer(48, 48, { - smooth: true, - reusable: false, - label: "waypoints-compass", - }); - this.compassBuffer = { canvas, context }; - - /** - * Stores a cache from a shape short key to its canvas representation - */ - this.cachedKeyToCanvas = {}; - - // Initial render - this.rerenderWaypointList(); - } - - /** - * Re-renders the waypoint list to account for changes - */ - rerenderWaypointList() { - removeAllChildren(this.waypointsListElement); - this.cleanupClickDetectors(); - - for (let i = 0; i < this.waypoints.length; ++i) { - const waypoint = this.waypoints[i]; - const label = this.getWaypointLabel(waypoint); - - const element = makeDiv(this.waypointsListElement, null, ["waypoint"]); - - if (ShapeDefinition.isValidShortKey(label)) { - const canvas = this.getWaypointCanvas(waypoint); - /** - * Create a clone of the cached canvas, as calling appendElement when a canvas is - * already in the document will move the existing canvas to the new position. - */ - const [newCanvas, context] = makeOffscreenBuffer(48, 48, { - smooth: true, - label: label + "-waypoint-" + i, - }); - context.drawImage(canvas, 0, 0); - element.appendChild(newCanvas); - element.classList.add("shapeIcon"); - } else { - element.innerText = label; - } - - if (this.isWaypointDeletable(waypoint)) { - const editButton = makeDiv(element, null, ["editButton"]); - this.trackClicks(editButton, () => this.requestSaveMarker({ waypoint })); - } - - if (!waypoint.label) { - // This must be the hub label - element.classList.add("hub"); - element.insertBefore(this.compassBuffer.canvas, element.childNodes[0]); - } - - this.trackClicks(element, () => this.moveToWaypoint(waypoint), { - targetOnly: true, - }); - } - } - - /** - * Moves the camera to a given waypoint - * @param {Waypoint} waypoint - */ - moveToWaypoint(waypoint) { - this.root.camera.setDesiredCenter(new Vector(waypoint.center.x, waypoint.center.y)); - this.root.camera.setDesiredZoom(waypoint.zoomLevel); - } - - /** - * Deletes a waypoint from the list - * @param {Waypoint} waypoint - */ - deleteWaypoint(waypoint) { - arrayDeleteValue(this.waypoints, waypoint); - this.rerenderWaypointList(); - } - - /** - * Gets the canvas for a given waypoint - * @param {Waypoint} waypoint - * @returns {HTMLCanvasElement} - */ - getWaypointCanvas(waypoint) { - const key = waypoint.label; - if (this.cachedKeyToCanvas[key]) { - return this.cachedKeyToCanvas[key]; - } - - assert(ShapeDefinition.isValidShortKey(key), "Invalid short key: " + key); - const definition = ShapeDefinition.fromShortKey(key); - const preRendered = definition.generateAsCanvas(48); - return (this.cachedKeyToCanvas[key] = preRendered); - } - - /** - * Requests to save a marker at the current camera position. If worldPos is set, - * uses that position instead. - * @param {object} param0 - * @param {Vector=} param0.worldPos Override the world pos, otherwise it is the camera position - * @param {Waypoint=} param0.waypoint Waypoint to be edited. If omitted, create new - */ - requestSaveMarker({ worldPos = null, waypoint = null }) { - // Construct dialog with input field - const markerNameInput = new FormElementInput({ - id: "markerName", - label: null, - placeholder: "", - defaultValue: waypoint ? waypoint.label : "", - validator: val => - val.length > 0 && (val.length < MAX_LABEL_LENGTH || ShapeDefinition.isValidShortKey(val)), - }); - const dialog = new DialogWithForm({ - app: this.root.app, - title: waypoint ? T.dialogs.createMarker.titleEdit : T.dialogs.createMarker.title, - desc: T.dialogs.createMarker.desc, - formElements: [markerNameInput], - buttons: waypoint ? ["delete:bad", "cancel", "ok:good"] : ["cancel", "ok:good"], - }); - this.root.hud.parts.dialogs.internalShowDialog(dialog); - - // Edit marker - if (waypoint) { - dialog.buttonSignals.ok.add(() => { - // Actually rename the waypoint - this.renameWaypoint(waypoint, markerNameInput.getValue()); - }); - dialog.buttonSignals.delete.add(() => { - // Actually delete the waypoint - this.deleteWaypoint(waypoint); - }); - } else { - // Compute where to create the marker - const center = worldPos || this.root.camera.center; - - dialog.buttonSignals.ok.add(() => { - // Show info that you can have only N markers in the demo, - // actually show this *after* entering the name so you want the - // standalone even more (I'm evil :P) - if (IS_DEMO && this.waypoints.length > 2) { - this.root.hud.parts.dialogs.showFeatureRestrictionInfo( - "", - T.dialogs.markerDemoLimit.desc - ); - return; - } - - // Actually create the waypoint - this.addWaypoint(markerNameInput.getValue(), center); - }); - } - } - - /** - * Adds a new waypoint at the given location with the given label - * @param {string} label - * @param {Vector} position - */ - addWaypoint(label, position) { - this.waypoints.push({ - label, - center: { x: position.x, y: position.y }, - // Make sure the zoom is *just* a bit above the zoom level where the map overview - // starts, so you always see all buildings - zoomLevel: Math.max(this.root.camera.zoomLevel, globalConfig.mapChunkOverviewMinZoom + 0.05), - }); - - this.sortWaypoints(); - - // Show notification about creation - this.root.hud.signals.notification.dispatch( - T.ingame.waypoints.creationSuccessNotification, - enumNotificationType.success - ); - - // Re-render the list and thus add it - this.rerenderWaypointList(); - } - - /** - * Renames a waypoint with the given label - * @param {Waypoint} waypoint - * @param {string} label - */ - renameWaypoint(waypoint, label) { - waypoint.label = label; - - this.sortWaypoints(); - - // Show notification about renamed - this.root.hud.signals.notification.dispatch( - T.ingame.waypoints.creationSuccessNotification, - enumNotificationType.success - ); - - // Re-render the list and thus add it - this.rerenderWaypointList(); - } - - /** - * Called every frame to update stuff - */ - update() { - if (this.domAttach) { - this.domAttach.update(this.root.camera.getIsMapOverlayActive()); - } - } - - /** - * Sort waypoints by name - */ - sortWaypoints() { - this.waypoints.sort((a, b) => { - if (!a.label) { - return -1; - } - if (!b.label) { - return 1; - } - return this.getWaypointLabel(a) - .padEnd(MAX_LABEL_LENGTH, "0") - .localeCompare(this.getWaypointLabel(b).padEnd(MAX_LABEL_LENGTH, "0")); - }); - } - - /** - * Returns the label for a given waypoint - * @param {Waypoint} waypoint - * @returns {string} - */ - getWaypointLabel(waypoint) { - return waypoint.label || T.ingame.waypoints.hub; - } - - /** - * Returns if a waypoint is deletable - * @param {Waypoint} waypoint - * @returns {boolean} - */ - isWaypointDeletable(waypoint) { - return waypoint.label !== null; - } - - /** - * Finds the currently intersected waypoint on the map overview under - * the cursor. - * - * @returns {Waypoint | null} - */ - findCurrentIntersectedWaypoint() { - const mousePos = this.root.app.mousePosition; - if (!mousePos) { - 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)) { - return waypoint; - } - } - } - - /** - * Mouse-Down handler - * @param {Vector} pos - * @param {enumMouseButton} button - */ - onMouseDown(pos, button) { - const waypoint = this.findCurrentIntersectedWaypoint(); - if (waypoint) { - if (button === enumMouseButton.left) { - this.root.soundProxy.playUiClick(); - this.moveToWaypoint(waypoint); - } else if (button === enumMouseButton.right) { - if (this.isWaypointDeletable(waypoint)) { - this.root.soundProxy.playUiClick(); - this.requestSaveMarker({ waypoint }); - } else { - this.root.soundProxy.playUiError(); - } - } - - return STOP_PROPAGATION; - } else { - // Allow right click to create a marker - if (button === enumMouseButton.right) { - if (this.root.camera.getIsMapOverlayActive()) { - const worldPos = this.root.camera.screenToWorld(pos); - this.requestSaveMarker({ worldPos }); - return STOP_PROPAGATION; - } - } - } - } - - /** - * 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 distanceToHub = cameraPos.length(); - const compassVisible = distanceToHub > (10 * globalConfig.tileSize) / this.root.camera.zoomLevel; - const targetCompassAlpha = compassVisible ? 1 : 0; - this.currentCompassOpacity = lerp(this.currentCompassOpacity, targetCompassAlpha, 0.08); - - if (this.currentCompassOpacity > 0.01) { - context.globalAlpha = this.currentCompassOpacity; - const angle = cameraPos.angle() + Math.radians(45) + Math.PI / 2; - context.translate(dims / 2, dims / 2); - context.rotate(angle); - this.directionIndicatorSprite.drawCentered(context, 0, 0, indicatorSize); - context.rotate(-angle); - context.translate(-dims / 2, -dims / 2); - context.globalAlpha = 1; - } - - 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; - } - } - - /** - * Draws the waypoints on the map - * @param {DrawParameters} parameters - */ - draw(parameters) { - const desiredOpacity = this.root.camera.getIsMapOverlayActive() ? 1 : 0; - this.currentMarkerOpacity = lerp(this.currentMarkerOpacity, desiredOpacity, 0.08); - - this.rerenderWaypointsCompass(); - - // Don't render with low opacity - if (this.currentMarkerOpacity < 0.01) { - return; - } - - // Find waypoint below cursor - const selected = this.findCurrentIntersectedWaypoint(); - - // Determine rendering scale - const scale = (1 / this.root.camera.zoomLevel) * this.root.app.getEffectiveUiScale(); - - // Render all of 'em - 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; - } - - // Render the background rectangle - parameters.context.font = "bold " + 12 * scale + "px GameFont"; - 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 - ); - - // Render the text - if (isShapeIcon) { - const canvas = this.getWaypointCanvas(waypoint); - parameters.context.drawImage( - canvas, - pos.x + 6 * scale, - pos.y - 11.5 * scale, - 14 * scale, - 14 * scale - ); - } else { - // 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.textBaseline = "alphabetic"; - } - - // Render the small icon on the left - this.waypointSprite.drawCentered(parameters.context, pos.x, pos.y + yOffset, 10 * scale); - } - - parameters.context.globalAlpha = 1; - } -} +import { makeOffscreenBuffer } from "../../../core/buffer_utils"; +import { globalConfig, THIRDPARTY_URLS } from "../../../core/config"; +import { DrawParameters } from "../../../core/draw_parameters"; +import { Loader } from "../../../core/loader"; +import { DialogWithForm } from "../../../core/modal_dialog_elements"; +import { FormElementInput } from "../../../core/modal_dialog_forms"; +import { Rectangle } from "../../../core/rectangle"; +import { STOP_PROPAGATION } from "../../../core/signal"; +import { + arrayDeleteValue, + fillInLinkIntoTranslation, + lerp, + makeDiv, + removeAllChildren, +} from "../../../core/utils"; +import { Vector } from "../../../core/vector"; +import { T } from "../../../translations"; +import { BaseItem } from "../../base_item"; +import { enumMouseButton } from "../../camera"; +import { KEYMAPPINGS } from "../../key_action_mapper"; +import { ShapeDefinition } from "../../shape_definition"; +import { BaseHUDPart } from "../base_hud_part"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; +import { enumNotificationType } from "./notifications"; + +/** @typedef {{ + * label: string | null, + * center: { x: number, y: number }, + * zoomLevel: number + * }} Waypoint */ + +/** + * Used when a shape icon is rendered instead + */ +const MAX_LABEL_LENGTH = 71; + +export class HUDWaypoints extends BaseHUDPart { + /** + * Creates the overview of waypoints + * @param {HTMLElement} parent + */ + createElements(parent) { + // Create the helper box on the lower right when zooming out + if (this.root.app.settings.getAllSettings().offerHints) { + this.hintElement = makeDiv( + parent, + "ingame_HUD_Waypoints_Hint", + [], + ` + ${T.ingame.waypoints.waypoints} + ${T.ingame.waypoints.description.replace( + "", + `${this.root.keyMapper + .getBinding(KEYMAPPINGS.navigation.createMarker) + .getKeyCodeString()}` + )} + ` + ); + } + + // Create the waypoint list on the upper right + this.waypointsListElement = makeDiv(parent, "ingame_HUD_Waypoints", [], "Waypoints"); + } + + /** + * Serializes the waypoints + */ + serialize() { + return { + waypoints: this.waypoints, + }; + } + + /** + * Deserializes the waypoints + * @param {{waypoints: Array}} data + */ + deserialize(data) { + if (!data || !data.waypoints || !Array.isArray(data.waypoints)) { + return "Invalid waypoints data"; + } + this.waypoints = data.waypoints; + this.rerenderWaypointList(); + } + + /** + * Initializes everything + */ + initialize() { + // Cache the sprite for the waypoints + this.waypointSprite = Loader.getSprite("sprites/misc/waypoint.png"); + this.directionIndicatorSprite = Loader.getSprite("sprites/misc/hub_direction_indicator.png"); + + /** @type {Array} + */ + this.waypoints = [ + { + label: null, + center: { x: 0, y: 0 }, + zoomLevel: 3, + }, + ]; + + // Create a buffer we can use to measure text + this.dummyBuffer = makeOffscreenBuffer(1, 1, { + reusable: false, + label: "waypoints-measure-canvas", + })[1]; + + // Dynamically attach/detach the lower right hint in the map overview + if (this.hintElement) { + this.domAttach = new DynamicDomAttach(this.root, this.hintElement); + } + + // Catch mouse and key events + this.root.camera.downPreHandler.add(this.onMouseDown, this); + this.root.keyMapper + .getBinding(KEYMAPPINGS.navigation.createMarker) + .add(() => this.requestSaveMarker({})); + + /** + * Stores at how much opacity the markers should be rendered on the map. + * This is interpolated over multiple frames so we have some sort of fade effect + */ + this.currentMarkerOpacity = 1; + this.currentCompassOpacity = 0; + + // Create buffer which is used to indicate the hub direction + const [canvas, context] = makeOffscreenBuffer(48, 48, { + smooth: true, + reusable: false, + label: "waypoints-compass", + }); + this.compassBuffer = { canvas, context }; + + /** + * Stores a cache from a shape short key to its canvas representation + */ + 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 + */ + rerenderWaypointList() { + removeAllChildren(this.waypointsListElement); + this.cleanupClickDetectors(); + + for (let i = 0; i < this.waypoints.length; ++i) { + const waypoint = this.waypoints[i]; + const label = this.getWaypointLabel(waypoint); + + const element = makeDiv(this.waypointsListElement, null, ["waypoint"]); + + if (ShapeDefinition.isValidShortKey(label)) { + const canvas = this.getWaypointCanvas(waypoint); + /** + * Create a clone of the cached canvas, as calling appendElement when a canvas is + * already in the document will move the existing canvas to the new position. + */ + const [newCanvas, context] = makeOffscreenBuffer(48, 48, { + smooth: true, + label: label + "-waypoint-" + i, + }); + context.drawImage(canvas, 0, 0); + element.appendChild(newCanvas); + element.classList.add("shapeIcon"); + } else { + element.innerText = label; + } + + if (this.isWaypointDeletable(waypoint)) { + const editButton = makeDiv(element, null, ["editButton"]); + this.trackClicks(editButton, () => this.requestSaveMarker({ waypoint })); + } + + if (!waypoint.label) { + // This must be the hub label + element.classList.add("hub"); + element.insertBefore(this.compassBuffer.canvas, element.childNodes[0]); + } + + this.trackClicks(element, () => this.moveToWaypoint(waypoint), { + targetOnly: true, + }); + } + } + + /** + * Moves the camera to a given waypoint + * @param {Waypoint} waypoint + */ + moveToWaypoint(waypoint) { + this.root.camera.setDesiredCenter(new Vector(waypoint.center.x, waypoint.center.y)); + this.root.camera.setDesiredZoom(waypoint.zoomLevel); + } + + /** + * Deletes a waypoint from the list + * @param {Waypoint} waypoint + */ + deleteWaypoint(waypoint) { + arrayDeleteValue(this.waypoints, waypoint); + this.rerenderWaypointList(); + } + + /** + * Gets the canvas for a given waypoint + * @param {Waypoint} waypoint + * @returns {HTMLCanvasElement} + */ + getWaypointCanvas(waypoint) { + const key = waypoint.label; + if (this.cachedKeyToCanvas[key]) { + return this.cachedKeyToCanvas[key]; + } + + assert(ShapeDefinition.isValidShortKey(key), "Invalid short key: " + key); + const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey(key); + const preRendered = definition.generateAsCanvas(48); + return (this.cachedKeyToCanvas[key] = preRendered); + } + + /** + * Requests to save a marker at the current camera position. If worldPos is set, + * uses that position instead. + * @param {object} param0 + * @param {Vector=} param0.worldPos Override the world pos, otherwise it is the camera position + * @param {Waypoint=} param0.waypoint Waypoint to be edited. If omitted, create new + */ + requestSaveMarker({ worldPos = null, waypoint = null }) { + // Construct dialog with input field + const markerNameInput = new FormElementInput({ + id: "markerName", + label: null, + placeholder: "", + defaultValue: waypoint ? waypoint.label : "", + validator: val => + val.length > 0 && (val.length < MAX_LABEL_LENGTH || ShapeDefinition.isValidShortKey(val)), + }); + const dialog = new DialogWithForm({ + app: this.root.app, + title: waypoint ? T.dialogs.createMarker.titleEdit : T.dialogs.createMarker.title, + desc: fillInLinkIntoTranslation(T.dialogs.createMarker.desc, THIRDPARTY_URLS.shapeViewer), + formElements: [markerNameInput], + buttons: waypoint ? ["delete:bad", "cancel", "ok:good"] : ["cancel", "ok:good"], + }); + this.root.hud.parts.dialogs.internalShowDialog(dialog); + + // Edit marker + if (waypoint) { + dialog.buttonSignals.ok.add(() => { + // Actually rename the waypoint + this.renameWaypoint(waypoint, markerNameInput.getValue()); + }); + dialog.buttonSignals.delete.add(() => { + // Actually delete the waypoint + this.deleteWaypoint(waypoint); + }); + } else { + // Compute where to create the marker + const center = worldPos || this.root.camera.center; + + dialog.buttonSignals.ok.add(() => { + // Show info that you can have only N markers in the demo, + // actually show this *after* entering the name so you want the + // standalone even more (I'm evil :P) + if (this.waypoints.length > this.root.app.restrictionMgr.getMaximumWaypoints()) { + this.root.hud.parts.dialogs.showFeatureRestrictionInfo( + "", + T.dialogs.markerDemoLimit.desc + ); + return; + } + + // Actually create the waypoint + this.addWaypoint(markerNameInput.getValue(), center); + }); + } + } + + /** + * Adds a new waypoint at the given location with the given label + * @param {string} label + * @param {Vector} position + */ + addWaypoint(label, position) { + this.waypoints.push({ + label, + center: { x: position.x, y: position.y }, + zoomLevel: this.root.camera.zoomLevel, + }); + + this.sortWaypoints(); + + // Show notification about creation + this.root.hud.signals.notification.dispatch( + T.ingame.waypoints.creationSuccessNotification, + enumNotificationType.success + ); + + // Re-render the list and thus add it + this.rerenderWaypointList(); + } + + /** + * Renames a waypoint with the given label + * @param {Waypoint} waypoint + * @param {string} label + */ + renameWaypoint(waypoint, label) { + waypoint.label = label; + + this.sortWaypoints(); + + // Show notification about renamed + this.root.hud.signals.notification.dispatch( + T.ingame.waypoints.creationSuccessNotification, + enumNotificationType.success + ); + + // Re-render the list and thus add it + this.rerenderWaypointList(); + } + + /** + * Called every frame to update stuff + */ + update() { + if (this.domAttach) { + this.domAttach.update(this.root.camera.getIsMapOverlayActive()); + } + } + + /** + * Sort waypoints by name + */ + sortWaypoints() { + this.waypoints.sort((a, b) => { + if (!a.label) { + return -1; + } + if (!b.label) { + return 1; + } + return this.getWaypointLabel(a) + .padEnd(MAX_LABEL_LENGTH, "0") + .localeCompare(this.getWaypointLabel(b).padEnd(MAX_LABEL_LENGTH, "0")); + }); + } + + /** + * Returns the label for a given waypoint + * @param {Waypoint} waypoint + * @returns {string} + */ + getWaypointLabel(waypoint) { + return waypoint.label || T.ingame.waypoints.hub; + } + + /** + * Returns if a waypoint is deletable + * @param {Waypoint} waypoint + * @returns {boolean} + */ + isWaypointDeletable(waypoint) { + 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. + * + * @returns {Waypoint | null} + */ + findCurrentIntersectedWaypoint() { + const mousePos = this.root.app.mousePosition; + if (!mousePos) { + return; + } + + for (let i = 0; i < this.waypoints.length; ++i) { + const waypoint = this.waypoints[i]; + const params = this.getWaypointScreenParams(waypoint); + if (params && params.screenBounds.containsPoint(mousePos.x, mousePos.y)) { + return waypoint; + } + } + } + + /** + * Mouse-Down handler + * @param {Vector} pos + * @param {enumMouseButton} button + */ + onMouseDown(pos, button) { + const waypoint = this.findCurrentIntersectedWaypoint(); + if (waypoint) { + if (button === enumMouseButton.left) { + this.root.soundProxy.playUiClick(); + this.moveToWaypoint(waypoint); + } else if (button === enumMouseButton.right) { + if (this.isWaypointDeletable(waypoint)) { + this.root.soundProxy.playUiClick(); + this.requestSaveMarker({ waypoint }); + } else { + this.root.soundProxy.playUiError(); + } + } + + return STOP_PROPAGATION; + } else { + // Allow right click to create a marker + if (button === enumMouseButton.right) { + if (this.root.camera.getIsMapOverlayActive()) { + const worldPos = this.root.camera.screenToWorld(pos); + this.requestSaveMarker({ worldPos }); + return STOP_PROPAGATION; + } + } + } + } + + /** + * Rerenders the compass + */ + rerenderWaypointsCompass() { + const dims = 48; + 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; + context.translate(dims / 2, dims / 2); + context.rotate(angle); + this.directionIndicatorSprite.drawCentered(context, 0, 0, indicatorSize); + context.rotate(-angle); + context.translate(-dims / 2, -dims / 2); + context.globalAlpha = 1; + } + + // Render the regualr icon + const iconOpacity = 1 - this.currentCompassOpacity; + if (iconOpacity > 0.01) { + context.globalAlpha = iconOpacity; + this.waypointSprite.drawCentered(context, dims / 2, dims / 2, dims * 0.7); + context.globalAlpha = 1; + } + } + + /** + * Draws the waypoints on the map + * @param {DrawParameters} 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); + + this.rerenderWaypointsCompass(); + + // Don't render with low opacity + if (this.currentMarkerOpacity < 0.01) { + return; + } + + // Determine rendering scale + const scale = this.getWaypointUiScale(); + + // 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 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.globalAlpha = this.currentMarkerOpacity * (isSelected ? 1 : 0.7); + parameters.context.fillStyle = "rgba(255, 255, 255, 0.7)"; + parameters.context.fillRect(bounds.x, bounds.y, bounds.w, bounds.h); + + // Render the text + if (waypointData.item) { + const canvas = this.getWaypointCanvas(waypoint); + const itemSize = 14 * scale; + parameters.context.drawImage( + canvas, + bounds.x + contentPaddingX + 6 * scale, + bounds.y + bounds.h / 2 - itemSize / 2, + itemSize, + itemSize + ); + } else if (waypointData.text) { + // Render the text + parameters.context.fillStyle = "#000"; + parameters.context.textBaseline = "middle"; + 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, + 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..752d9cb3 100644 --- a/src/js/game/hud/parts/wires_overlay.js +++ b/src/js/game/hud/parts/wires_overlay.js @@ -1,97 +1,146 @@ -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 { Loader } from "../../../core/loader"; +import { lerp } from "../../../core/utils"; +import { SOUNDS } from "../../../platform/sound"; +import { KEYMAPPINGS } from "../../key_action_mapper"; +import { enumHubGoalRewards } from "../../tutorial_goals"; +import { BaseHUDPart } from "../base_hud_part"; + +const copy = require("clipboard-copy"); +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.root.keyMapper.getBinding(KEYMAPPINGS.placement.copyWireValue).add(this.copyWireValue, this); + + this.generateTilePattern(); + + this.currentAlpha = 0.0; + } + + /** + * Switches between layers + */ + switchLayers() { + if (this.root.currentLayer === "regular") { + if ( + this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_painter_and_levers) || + (G_IS_DEV && globalConfig.debug.allBuildingsUnlocked) + ) { + 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; + + // On low performance, skip the fade + if (this.root.entityMgr.entities.length > 5000 || this.root.dynamicTickrate.averageFps < 50) { + this.currentAlpha = desiredAlpha; + } else { + this.currentAlpha = lerp(this.currentAlpha, desiredAlpha, 0.12); + } + } + + /** + * Copies the wires value below the cursor + */ + copyWireValue() { + if (this.root.currentLayer !== "wires") { + return; + } + + const mousePos = this.root.app.mousePosition; + if (!mousePos) { + return; + } + + const tile = this.root.camera.screenToWorld(mousePos).toTileSpace(); + const contents = this.root.map.getLayerContentXY(tile.x, tile.y, "wires"); + if (!contents) { + return; + } + + let value = null; + if (contents.components.Wire) { + const network = contents.components.Wire.linkedNetwork; + if (network && network.hasValue()) { + value = network.currentValue; + } + } + + if (contents.components.ConstantSignal) { + value = contents.components.ConstantSignal.signal; + } + + if (value) { + copy(value.getAsCopyableKey()); + this.root.soundProxy.playUi(SOUNDS.copy); + } else { + copy(""); + this.root.soundProxy.playUiError(); + } + } + + /** + * + * @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..5141bbeb 100644 --- a/src/js/game/hud/parts/wires_toolbar.js +++ b/src/js/game/hud/parts/wires_toolbar.js @@ -1,17 +1,42 @@ -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"; +import { MetaTransistorBuilding } from "../../buildings/transistor"; +import { MetaAnalyzerBuilding } from "../../buildings/analyzer"; +import { MetaComparatorBuilding } from "../../buildings/comparator"; +import { MetaReaderBuilding } from "../../buildings/reader"; +import { MetaFilterBuilding } from "../../buildings/filter"; +import { MetaDisplayBuilding } from "../../buildings/display"; +import { MetaStorageBuilding } from "../../buildings/storage"; + +export class HUDWiresToolbar extends HUDBaseToolbar { + constructor(root) { + super(root, { + primaryBuildings: [ + MetaWireBuilding, + MetaWireTunnelBuilding, + MetaConstantSignalBuilding, + MetaLogicGateBuilding, + MetaVirtualProcessorBuilding, + MetaAnalyzerBuilding, + MetaComparatorBuilding, + MetaTransistorBuilding, + ], + secondaryBuildings: [ + MetaStorageBuilding, + MetaReaderBuilding, + MetaLeverBuilding, + MetaFilterBuilding, + MetaDisplayBuilding, + ], + visibilityCondition: () => + !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "wires", + htmlElementId: "ingame_HUD_wires_toolbar", + layer: "wires", + }); + } +} diff --git a/src/js/game/hud/trailer_maker.js b/src/js/game/hud/trailer_maker.js index 2834b40d..e9193a93 100644 --- a/src/js/game/hud/trailer_maker.js +++ b/src/js/game/hud/trailer_maker.js @@ -1,125 +1,122 @@ -import { GameRoot, enumLayer } from "../root"; -import { globalConfig } from "../../core/config"; -import { Vector, mixVector } from "../../core/vector"; -import { lerp } from "../../core/utils"; - -/* dev:start */ -import trailerPoints from "./trailer_points"; -import { gMetaBuildingRegistry } from "../../core/global_registries"; -import { MetaBeltBaseBuilding } from "../buildings/belt_base"; -import { MinerComponent } from "../components/miner"; - -const tickrate = 1 / 165; - -export class TrailerMaker { - /** - * - * @param {GameRoot} root - */ - constructor(root) { - this.root = root; - - this.markers = []; - this.playbackMarkers = null; - this.currentPlaybackOrigin = new Vector(); - this.currentPlaybackZoom = 3; - - window.addEventListener("keydown", ev => { - if (ev.key === "j") { - console.log("Record"); - this.markers.push({ - pos: this.root.camera.center.copy(), - zoom: this.root.camera.zoomLevel, - time: 1, - wait: 0, - }); - } else if (ev.key === "k") { - console.log("Export"); - const json = JSON.stringify(this.markers); - const handle = window.open("about:blank"); - handle.document.write(json); - } else if (ev.key === "u") { - if (this.playbackMarkers && this.playbackMarkers.length > 0) { - this.playbackMarkers = []; - return; - } - console.log("Playback"); - this.playbackMarkers = trailerPoints.map(p => Object.assign({}, p)); - this.playbackMarkers.unshift(this.playbackMarkers[0]); - this.currentPlaybackOrigin = Vector.fromSerializedObject(this.playbackMarkers[0].pos); - - this.currentPlaybackZoom = this.playbackMarkers[0].zoom; - this.root.camera.center = this.currentPlaybackOrigin.copy(); - this.root.camera.zoomLevel = this.currentPlaybackZoom; - console.log("STart at", this.currentPlaybackOrigin); - - // this.root.entityMgr.getAllWithComponent(MinerComponent).forEach(miner => { - // miner.components.Miner.itemChainBuffer = []; - // miner.components.Miner.lastMiningTime = this.root.time.now() + 5; - // miner.components.ItemEjector.slots.forEach(slot => (slot.item = null)); - // }); - - // this.root.logic.tryPlaceBuilding({ - // origin: new Vector(-428, -15), - // building: gMetaBuildingRegistry.findByClass(MetaBeltBaseBuilding), - // originalRotation: 0, - // rotation: 0, - // variant: "default", - // rotationVariant: 0, - // }); - - // this.root.logic.tryPlaceBuilding({ - // origin: new Vector(-427, -15), - // building: gMetaBuildingRegistry.findByClass(MetaBeltBaseBuilding), - // originalRotation: 0, - // rotation: 0, - // variant: "default", - // rotationVariant: 0, - // }); - } - }); - } - - update() { - if (this.playbackMarkers && this.playbackMarkers.length > 0) { - const nextMarker = this.playbackMarkers[0]; - - if (!nextMarker.startTime) { - console.log("Starting to approach", nextMarker.pos); - nextMarker.startTime = performance.now() / 1000.0; - } - - const speed = - globalConfig.tileSize * - globalConfig.beltSpeedItemsPerSecond * - globalConfig.beltItemSpacingByLayer[enumLayer.regular]; - // let time = - // this.currentPlaybackOrigin.distance(Vector.fromSerializedObject(nextMarker.pos)) / speed; - const time = nextMarker.time; - - const progress = (performance.now() / 1000.0 - nextMarker.startTime) / time; - - if (progress > 1.0) { - if (nextMarker.wait > 0) { - nextMarker.wait -= tickrate; - } else { - console.log("Approached"); - this.currentPlaybackOrigin = this.root.camera.center.copy(); - this.currentPlaybackZoom = this.root.camera.zoomLevel; - this.playbackMarkers.shift(); - } - return; - } - - const targetPos = Vector.fromSerializedObject(nextMarker.pos); - const targetZoom = nextMarker.zoom; - - const pos = mixVector(this.currentPlaybackOrigin, targetPos, progress); - const zoom = lerp(this.currentPlaybackZoom, targetZoom, progress); - this.root.camera.zoomLevel = zoom; - this.root.camera.center = pos; - } - } -} - -/* dev:end */ +import { GameRoot } from "../root"; +import { globalConfig } from "../../core/config"; +import { Vector, mixVector } from "../../core/vector"; +import { lerp } from "../../core/utils"; + +/* dev:start */ +import trailerPoints from "./trailer_points"; + +const tickrate = 1 / 165; + +export class TrailerMaker { + /** + * + * @param {GameRoot} root + */ + constructor(root) { + this.root = root; + + this.markers = []; + this.playbackMarkers = null; + this.currentPlaybackOrigin = new Vector(); + this.currentPlaybackZoom = 3; + + window.addEventListener("keydown", ev => { + if (ev.key === "j") { + console.log("Record"); + this.markers.push({ + pos: this.root.camera.center.copy(), + zoom: this.root.camera.zoomLevel, + time: 1, + wait: 0, + }); + } else if (ev.key === "k") { + console.log("Export"); + const json = JSON.stringify(this.markers); + const handle = window.open("about:blank"); + handle.document.write(json); + } else if (ev.key === "u") { + if (this.playbackMarkers && this.playbackMarkers.length > 0) { + this.playbackMarkers = []; + return; + } + console.log("Playback"); + this.playbackMarkers = trailerPoints.map(p => Object.assign({}, p)); + this.playbackMarkers.unshift(this.playbackMarkers[0]); + this.currentPlaybackOrigin = Vector.fromSerializedObject(this.playbackMarkers[0].pos); + + this.currentPlaybackZoom = this.playbackMarkers[0].zoom; + this.root.camera.center = this.currentPlaybackOrigin.copy(); + this.root.camera.zoomLevel = this.currentPlaybackZoom; + console.log("STart at", this.currentPlaybackOrigin); + + // this.root.entityMgr.getAllWithComponent(MinerComponent).forEach(miner => { + // miner.components.Miner.itemChainBuffer = []; + // miner.components.Miner.lastMiningTime = this.root.time.now() + 5; + // miner.components.ItemEjector.slots.forEach(slot => (slot.item = null)); + // }); + + // this.root.logic.tryPlaceBuilding({ + // origin: new Vector(-428, -15), + // building: gMetaBuildingRegistry.findByClass(MetaBeltBaseBuilding), + // originalRotation: 0, + // rotation: 0, + // variant: "default", + // rotationVariant: 0, + // }); + + // this.root.logic.tryPlaceBuilding({ + // origin: new Vector(-427, -15), + // building: gMetaBuildingRegistry.findByClass(MetaBeltBaseBuilding), + // originalRotation: 0, + // rotation: 0, + // variant: "default", + // rotationVariant: 0, + // }); + } + }); + } + + update() { + if (this.playbackMarkers && this.playbackMarkers.length > 0) { + const nextMarker = this.playbackMarkers[0]; + + if (!nextMarker.startTime) { + console.log("Starting to approach", nextMarker.pos); + nextMarker.startTime = performance.now() / 1000.0; + } + + const speed = + globalConfig.tileSize * + globalConfig.beltSpeedItemsPerSecond * + globalConfig.itemSpacingOnBelts; + // let time = + // this.currentPlaybackOrigin.distance(Vector.fromSerializedObject(nextMarker.pos)) / speed; + const time = nextMarker.time; + + const progress = (performance.now() / 1000.0 - nextMarker.startTime) / time; + + if (progress > 1.0) { + if (nextMarker.wait > 0) { + nextMarker.wait -= tickrate; + } else { + console.log("Approached"); + this.currentPlaybackOrigin = this.root.camera.center.copy(); + this.currentPlaybackZoom = this.root.camera.zoomLevel; + this.playbackMarkers.shift(); + } + return; + } + + const targetPos = Vector.fromSerializedObject(nextMarker.pos); + const targetZoom = nextMarker.zoom; + + const pos = mixVector(this.currentPlaybackOrigin, targetPos, progress); + const zoom = lerp(this.currentPlaybackZoom, targetZoom, progress); + this.root.camera.zoomLevel = zoom; + this.root.camera.center = pos; + } + } +} + +/* dev:end */ 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..9ee3e3e5 --- /dev/null +++ b/src/js/game/items/boolean_item.js @@ -0,0 +1,110 @@ +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"; + } + + /** + * @returns {string} + */ + getAsCopyableKey() { + return this.value ? "1" : "0"; + } + + /** + * @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); + } + + /** + * Draws the item to a canvas + * @param {CanvasRenderingContext2D} context + * @param {number} size + */ + drawFullSizeOnCanvas(context, size) { + let sprite; + if (this.value) { + sprite = Loader.getSprite("sprites/wires/boolean_true.png"); + } else { + sprite = Loader.getSprite("sprites/wires/boolean_false.png"); + } + sprite.drawCentered(context, size / 2, size / 2, size); + } +} + +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..fb7f1701 100644 --- a/src/js/game/items/color_item.js +++ b/src/js/game/items/color_item.js @@ -1,93 +1,92 @@ -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 { enumColors, enumColorsToHexCode } from "../colors"; -import { THEME } from "../theme"; - -export class ColorItem extends BaseItem { - static getId() { - return "color"; - } - - static getSchema() { - return types.enum(enumColors); - } - - serialize() { - return this.color; - } - - deserialize(data) { - this.color = data; - } - - getItemType() { - return enumItemType.color; - } - - /** - * @param {enumColors} color - */ - constructor(color) { - super(); - this.color = color; - this.bufferGenerator = null; - } - - getBackgroundColorAsResource() { - return THEME.map.resources[this.color]; - } - - /** - * @param {number} x - * @param {number} y - * @param {number} size - * @param {DrawParameters} parameters - */ - draw(x, y, parameters, size = 12) { - if (!this.bufferGenerator) { - this.bufferGenerator = this.internalGenerateColorBuffer.bind(this); - } - - const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel); - - const key = size + "/" + dpi; - const canvas = parameters.root.buffers.getForKey( - key, - this.color, - size, - size, - dpi, - this.bufferGenerator - ); - parameters.context.drawImage(canvas, x - size / 2, y - size / 2, size, size); - } - /** - * - * @param {HTMLCanvasElement} canvas - * @param {CanvasRenderingContext2D} context - * @param {number} w - * @param {number} h - * @param {number} dpi - */ - internalGenerateColorBuffer(canvas, context, w, h, dpi) { - context.translate((w * dpi) / 2, (h * dpi) / 2); - context.scale((dpi * w) / 12, (dpi * h) / 12); - - context.fillStyle = enumColorsToHexCode[this.color]; - context.strokeStyle = THEME.items.outline; - context.lineWidth = 2 * THEME.items.outlineWidth; - context.beginCircle(2, -1, 3); - context.stroke(); - context.fill(); - context.beginCircle(-2, -1, 3); - context.stroke(); - context.fill(); - context.beginCircle(0, 2, 3); - context.closePath(); - context.stroke(); - context.fill(); - } -} +import { globalConfig } from "../../core/config"; +import { DrawParameters } from "../../core/draw_parameters"; +import { Loader } from "../../core/loader"; +import { types } from "../../savegame/serialization"; +import { BaseItem } from "../base_item"; +import { enumColors } from "../colors"; +import { THEME } from "../theme"; + +export class ColorItem extends BaseItem { + static getId() { + return "color"; + } + + static getSchema() { + return types.enum(enumColors); + } + + serialize() { + return this.color; + } + + deserialize(data) { + this.color = data; + } + + /** @returns {"color"} **/ + getItemType() { + return "color"; + } + + /** + * @returns {string} + */ + getAsCopyableKey() { + return this.color; + } + + /** + * @param {BaseItem} other + */ + equalsImpl(other) { + return this.color === /** @type {ColorItem} */ (other).color; + } + + /** + * @param {enumColors} color + */ + constructor(color) { + super(); + this.color = color; + } + + getBackgroundColorAsResource() { + return THEME.map.resources[this.color]; + } + + /** + * Draws the item to a canvas + * @param {CanvasRenderingContext2D} context + * @param {number} size + */ + drawFullSizeOnCanvas(context, size) { + if (!this.cachedSprite) { + this.cachedSprite = Loader.getSprite("sprites/colors/" + this.color + ".png"); + } + this.cachedSprite.drawCentered(context, size / 2, size / 2, size); + } + + /** + * @param {number} x + * @param {number} y + * @param {number} diameter + * @param {DrawParameters} parameters + */ + drawItemCenteredClipped(x, y, parameters, diameter = globalConfig.defaultItemDiameter) { + const realDiameter = diameter * 0.6; + if (!this.cachedSprite) { + this.cachedSprite = Loader.getSprite("sprites/colors/" + this.color + ".png"); + } + this.cachedSprite.drawCachedCentered(parameters, x, y, realDiameter); + } +} + +/** + * 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..d61b8f2e 100644 --- a/src/js/game/items/shape_item.js +++ b/src/js/game/items/shape_item.js @@ -1,54 +1,78 @@ -import { DrawParameters } from "../../core/draw_parameters"; -import { types } from "../../savegame/serialization"; -import { BaseItem, enumItemType } from "../base_item"; -import { ShapeDefinition } from "../shape_definition"; -import { THEME } from "../theme"; - -export class ShapeItem extends BaseItem { - static getId() { - return "shape"; - } - - static getSchema() { - return types.string; - } - - serialize() { - return this.definition.getHash(); - } - - deserialize(data) { - this.definition = ShapeDefinition.fromShortKey(data); - } - - getItemType() { - return enumItemType.shape; - } - - /** - * @param {ShapeDefinition} definition - */ - 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 - */ - this.definition = definition; - } - - getBackgroundColorAsResource() { - return THEME.map.resources.shape; - } - - /** - * @param {number} x - * @param {number} y - * @param {DrawParameters} parameters - * @param {number=} size - */ - draw(x, y, parameters, size) { - this.definition.draw(x, y, parameters, size); - } -} +import { DrawParameters } from "../../core/draw_parameters"; +import { types } from "../../savegame/serialization"; +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() { + return "shape"; + } + + static getSchema() { + return types.string; + } + + serialize() { + return this.definition.getHash(); + } + + deserialize(data) { + this.definition = ShapeDefinition.fromShortKey(data); + } + + /** @returns {"shape"} **/ + getItemType() { + return "shape"; + } + + /** + * @returns {string} + */ + getAsCopyableKey() { + return this.definition.getHash(); + } + + /** + * @param {BaseItem} other + */ + equalsImpl(other) { + return this.definition.getHash() === /** @type {ShapeItem} */ (other).definition.getHash(); + } + + /** + * @param {ShapeDefinition} definition + */ + constructor(definition) { + super(); + + /** + * This property must not be modified on runtime, you have to clone the class in order to change the definition + */ + this.definition = definition; + } + + getBackgroundColorAsResource() { + return THEME.map.resources.shape; + } + + /** + * Draws the item to a canvas + * @param {CanvasRenderingContext2D} context + * @param {number} size + */ + drawFullSizeOnCanvas(context, size) { + this.definition.drawFullSizeOnCanvas(context, size); + } + + /** + * @param {number} x + * @param {number} y + * @param {DrawParameters} parameters + * @param {number=} diameter + */ + 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..9fa4ffe1 100644 --- a/src/js/game/key_action_mapper.js +++ b/src/js/game/key_action_mapper.js @@ -1,453 +1,480 @@ -/* 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("E") }, + }, + + 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: { + // Primary Toolbar + belt: { keyCode: key("1") }, + balancer: { 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") }, + + // Sandbox + item_producer: { keyCode: key("L") }, + + // Secondary toolbar + storage: { keyCode: key("Y") }, + reader: { keyCode: key("U") }, + lever: { keyCode: key("I") }, + filter: { keyCode: key("O") }, + display: { keyCode: key("P") }, + + // Wires toolbar + wire: { keyCode: key("1") }, + wire_tunnel: { keyCode: key("2") }, + constant_signal: { keyCode: key("3") }, + logic_gate: { keyCode: key("4") }, + virtual_processor: { keyCode: key("5") }, + analyzer: { keyCode: key("6") }, + comparator: { keyCode: key("7") }, + transistor: { keyCode: key("8") }, + }, + + 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") }, + + copyWireValue: { keyCode: key("Z") }, + }, + + 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) { + // @todo: Refactor into dictionary + 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 "F5"; + case 117: + return "F6"; + case 118: + return "F7"; + case 119: + return "F8"; + case 120: + return "F9"; + case 121: + return "F10"; + case 122: + return "F11"; + case 123: + 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 190: + return "."; + case 191: + return "/"; + case 219: + return "["; + case 220: + return "\\"; + case 221: + return "]"; + case 222: + return "'"; + } + + return (48 <= code && code <= 57) || (65 <= code && code <= 90) + ? String.fromCharCode(code) + : "[" + 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); + + if (G_IS_DEV) { + // Sanity + if (!T.keybindings.mappings[key]) { + assertAlways(false, "Keybinding " + key + " has no translation!"); + } + } + } + } + + 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..7ec7b8ab 100644 --- a/src/js/game/logic.js +++ b/src/js/game/logic.js @@ -1,10 +1,15 @@ +import { globalConfig } from "../core/config"; import { createLogger } from "../core/logging"; -import { round2Digits } from "../core/utils"; -import { enumDirection, enumDirectionToVector, Vector } from "../core/vector"; -import { Entity } from "./entity"; -import { MetaBuilding } from "./meta_building"; -import { enumLayer, GameRoot } from "./root"; import { STOP_PROPAGATION } from "../core/signal"; +import { round2Digits } from "../core/utils"; +import { enumDirection, enumDirectionToVector, enumInvertedDirections, Vector } from "../core/vector"; +import { getBuildingDataFromCode } from "./building_codes"; +import { enumWireVariant } from "./components/wire"; +import { Entity } from "./entity"; +import { CHUNK_OVERLAY_RES } from "./map_chunk_view"; +import { MetaBuilding } from "./meta_building"; +import { GameRoot } from "./root"; +import { WireNetwork } from "./systems/wire"; const logger = createLogger("ingame/logic"); @@ -63,9 +68,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 +129,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 +166,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 +184,172 @@ export class GameLogic { return true; } + /** + * + * Computes the flag for a given tile + * @param {object} param0 + * @param {enumWireVariant} param0.wireVariant + * @param {Vector} param0.tile The tile to check at + * @param {enumDirection} param0.edge The edge to check for + */ + computeWireEdgeStatus({ wireVariant, tile, edge }) { + const offset = enumDirectionToVector[edge]; + const targetTile = tile.add(offset); + + // Search for relevant pins + const pinEntities = this.root.map.getLayersContentsMultipleXY(targetTile.x, targetTile.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(targetTile)) { + continue; + } + + // Check if the pin has the right direction + if (pinDirection !== enumInvertedDirections[edge]) { + continue; + } + + // Found a pin! + return true; + } + } + + // Now check if there's a connectable entity on the wires layer + const targetEntity = this.root.map.getTileContent(targetTile, "wires"); + if (!targetEntity) { + return false; + } + + const targetStaticComp = targetEntity.components.StaticMapEntity; + + // Check if its a crossing + const wireTunnelComp = targetEntity.components.WireTunnel; + if (wireTunnelComp) { + return true; + } + + // Check if its a wire + const wiresComp = targetEntity.components.Wire; + if (!wiresComp) { + return false; + } + + // It's connected if its the same variant + return wiresComp.variant === wireVariant; + } + + /** + * 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]; + } + + g(tile, edge) {} + /** * 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 +362,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..a5ec8f21 100644 --- a/src/js/game/map.js +++ b/src/js/game/map.js @@ -1,240 +1,236 @@ -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"); - -export class BaseMap extends BasicSerializableObject { - static getId() { - return "Map"; - } - - static getSchema() { - return { - seed: types.uint, - }; - } - - /** - * - * @param {GameRoot} root - */ - constructor(root) { - super(); - this.root = root; - - this.seed = 0; - - /** - * Mapping of 'X|Y' to chunk - * @type {Map} */ - this.chunksById = new Map(); - } - - /** - * Returns the given chunk by index - * @param {number} chunkX - * @param {number} chunkY - */ - getChunk(chunkX, chunkY, createIfNotExistent = false) { - const chunkIdentifier = chunkX + "|" + chunkY; - let storedChunk; - - if ((storedChunk = this.chunksById.get(chunkIdentifier))) { - return storedChunk; - } - - if (createIfNotExistent) { - const instance = new MapChunkView(this.root, chunkX, chunkY); - this.chunksById.set(chunkIdentifier, instance); - return instance; - } - - return null; - } - - /** - * Gets or creates a new chunk if not existent for the given tile - * @param {number} tileX - * @param {number} tileY - * @returns {MapChunkView} - */ - getOrCreateChunkAtTile(tileX, tileY) { - const chunkX = Math.floor(tileX / globalConfig.mapChunkSize); - const chunkY = Math.floor(tileY / globalConfig.mapChunkSize); - return this.getChunk(chunkX, chunkY, true); - } - - /** - * Gets a chunk if not existent for the given tile - * @param {number} tileX - * @param {number} tileY - * @returns {MapChunkView?} - */ - getChunkAtTileOrNull(tileX, tileY) { - const chunkX = Math.floor(tileX / globalConfig.mapChunkSize); - const chunkY = Math.floor(tileY / globalConfig.mapChunkSize); - return this.getChunk(chunkX, chunkY, false); - } - - /** - * Checks if a given tile is within the map bounds - * @param {Vector} tile - * @returns {boolean} - */ - isValidTile(tile) { - if (G_IS_DEV) { - assert(tile instanceof Vector, "tile is not a vector"); - } - return Number.isInteger(tile.x) && Number.isInteger(tile.y); - } - - /** - * Returns the tile content of a given tile - * @param {Vector} tile - * @param {enumLayer} layer - * @returns {Entity} Entity or null - */ - getTileContent(tile, layer) { - if (G_IS_DEV) { - this.internalCheckTile(tile); - } - const chunk = this.getChunkAtTileOrNull(tile.x, tile.y); - return chunk && chunk.getLayerContentFromWorldCoords(tile.x, tile.y, layer); - } - - /** - * Returns the lower layers content of the given tile - * @param {number} x - * @param {number} y - * @returns {BaseItem=} - */ - getLowerLayerContentXY(x, y) { - return this.getOrCreateChunkAtTile(x, y).getLowerLayerFromWorldCoords(x, y); - } - - /** - * Returns the tile content of a given tile - * @param {number} x - * @param {number} y - * @param {enumLayer} layer - * @returns {Entity} Entity or null - */ - getLayerContentXY(x, y, layer) { - const chunk = this.getChunkAtTileOrNull(x, y); - return chunk && chunk.getLayerContentFromWorldCoords(x, y, layer); - } - - /** - * Returns the tile contents of a given tile - * @param {number} x - * @param {number} y - * @returns {Array} Entity or null - */ - getLayersContentsMultipleXY(x, y) { - const chunk = this.getChunkAtTileOrNull(x, y); - if (!chunk) { - return []; - } - return chunk.getLayersContentsMultipleFromWorldCoords(x, y); - } - - /** - * Checks if the tile is used - * @param {Vector} tile - * @param {enumLayer} layer - * @returns {boolean} - */ - isTileUsed(tile, layer) { - if (G_IS_DEV) { - this.internalCheckTile(tile); - } - const chunk = this.getChunkAtTileOrNull(tile.x, tile.y); - return chunk && chunk.getLayerContentFromWorldCoords(tile.x, tile.y, layer) != null; - } - - /** - * Checks if the tile is used - * @param {number} x - * @param {number} y - * @param {enumLayer} layer - * @returns {boolean} - */ - isTileUsedXY(x, y, layer) { - const chunk = this.getChunkAtTileOrNull(x, y); - return chunk && chunk.getLayerContentFromWorldCoords(x, y, layer) != null; - } - - /** - * Sets the tiles content - * @param {Vector} tile - * @param {Entity} entity - */ - setTileContent(tile, entity) { - if (G_IS_DEV) { - this.internalCheckTile(tile); - } - - this.getOrCreateChunkAtTile(tile.x, tile.y).setLayerContentFromWorldCords( - tile.x, - tile.y, - entity, - entity.layer - ); - - const staticComponent = entity.components.StaticMapEntity; - assert(staticComponent, "Can only place static map entities in tiles"); - } - - /** - * Places an entity with the StaticMapEntity component - * @param {Entity} entity - */ - placeStaticEntity(entity) { - assert(entity.components.StaticMapEntity, "Entity is not static"); - const staticComp = entity.components.StaticMapEntity; - const rect = staticComp.getTileSpaceBounds(); - for (let dx = 0; dx < rect.w; ++dx) { - for (let dy = 0; dy < rect.h; ++dy) { - const x = rect.x + dx; - const y = rect.y + dy; - this.getOrCreateChunkAtTile(x, y).setLayerContentFromWorldCords(x, y, entity, entity.layer); - } - } - } - - /** - * Removes an entity with the StaticMapEntity component - * @param {Entity} entity - */ - removeStaticEntity(entity) { - assert(entity.components.StaticMapEntity, "Entity is not static"); - const staticComp = entity.components.StaticMapEntity; - const rect = staticComp.getTileSpaceBounds(); - for (let dx = 0; dx < rect.w; ++dx) { - for (let dy = 0; dy < rect.h; ++dy) { - const x = rect.x + dx; - const y = rect.y + dy; - this.getOrCreateChunkAtTile(x, y).setLayerContentFromWorldCords(x, y, null, entity.layer); - } - } - } - - // Internal - - /** - * Checks a given tile for validty - * @param {Vector} tile - */ - internalCheckTile(tile) { - assert(tile instanceof Vector, "tile is not a vector: " + tile); - assert(tile.x % 1 === 0, "Tile X is not a valid integer: " + tile.x); - assert(tile.y % 1 === 0, "Tile Y is not a valid integer: " + tile.y); - } -} +import { globalConfig } from "../core/config"; +import { Vector } from "../core/vector"; +import { BasicSerializableObject, types } from "../savegame/serialization"; +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() { + return "Map"; + } + + static getSchema() { + return { + seed: types.uint, + }; + } + + /** + * + * @param {GameRoot} root + */ + constructor(root) { + super(); + this.root = root; + + this.seed = 0; + + /** + * Mapping of 'X|Y' to chunk + * @type {Map} */ + this.chunksById = new Map(); + } + + /** + * Returns the given chunk by index + * @param {number} chunkX + * @param {number} chunkY + */ + getChunk(chunkX, chunkY, createIfNotExistent = false) { + const chunkIdentifier = chunkX + "|" + chunkY; + let storedChunk; + + if ((storedChunk = this.chunksById.get(chunkIdentifier))) { + return storedChunk; + } + + if (createIfNotExistent) { + const instance = new MapChunkView(this.root, chunkX, chunkY); + this.chunksById.set(chunkIdentifier, instance); + return instance; + } + + return null; + } + + /** + * Gets or creates a new chunk if not existent for the given tile + * @param {number} tileX + * @param {number} tileY + * @returns {MapChunkView} + */ + getOrCreateChunkAtTile(tileX, tileY) { + const chunkX = Math.floor(tileX / globalConfig.mapChunkSize); + const chunkY = Math.floor(tileY / globalConfig.mapChunkSize); + return this.getChunk(chunkX, chunkY, true); + } + + /** + * Gets a chunk if not existent for the given tile + * @param {number} tileX + * @param {number} tileY + * @returns {MapChunkView?} + */ + getChunkAtTileOrNull(tileX, tileY) { + const chunkX = Math.floor(tileX / globalConfig.mapChunkSize); + const chunkY = Math.floor(tileY / globalConfig.mapChunkSize); + return this.getChunk(chunkX, chunkY, false); + } + + /** + * Checks if a given tile is within the map bounds + * @param {Vector} tile + * @returns {boolean} + */ + isValidTile(tile) { + if (G_IS_DEV) { + assert(tile instanceof Vector, "tile is not a vector"); + } + return Number.isInteger(tile.x) && Number.isInteger(tile.y); + } + + /** + * Returns the tile content of a given tile + * @param {Vector} tile + * @param {Layer} layer + * @returns {Entity} Entity or null + */ + getTileContent(tile, layer) { + if (G_IS_DEV) { + this.internalCheckTile(tile); + } + const chunk = this.getChunkAtTileOrNull(tile.x, tile.y); + return chunk && chunk.getLayerContentFromWorldCoords(tile.x, tile.y, layer); + } + + /** + * Returns the lower layers content of the given tile + * @param {number} x + * @param {number} y + * @returns {BaseItem=} + */ + getLowerLayerContentXY(x, y) { + return this.getOrCreateChunkAtTile(x, y).getLowerLayerFromWorldCoords(x, y); + } + + /** + * Returns the tile content of a given tile + * @param {number} x + * @param {number} y + * @param {Layer} layer + * @returns {Entity} Entity or null + */ + getLayerContentXY(x, y, layer) { + const chunk = this.getChunkAtTileOrNull(x, y); + return chunk && chunk.getLayerContentFromWorldCoords(x, y, layer); + } + + /** + * Returns the tile contents of a given tile + * @param {number} x + * @param {number} y + * @returns {Array} Entity or null + */ + getLayersContentsMultipleXY(x, y) { + const chunk = this.getChunkAtTileOrNull(x, y); + if (!chunk) { + return []; + } + return chunk.getLayersContentsMultipleFromWorldCoords(x, y); + } + + /** + * Checks if the tile is used + * @param {Vector} tile + * @param {Layer} layer + * @returns {boolean} + */ + isTileUsed(tile, layer) { + if (G_IS_DEV) { + this.internalCheckTile(tile); + } + const chunk = this.getChunkAtTileOrNull(tile.x, tile.y); + return chunk && chunk.getLayerContentFromWorldCoords(tile.x, tile.y, layer) != null; + } + + /** + * Checks if the tile is used + * @param {number} x + * @param {number} y + * @param {Layer} layer + * @returns {boolean} + */ + isTileUsedXY(x, y, layer) { + const chunk = this.getChunkAtTileOrNull(x, y); + return chunk && chunk.getLayerContentFromWorldCoords(x, y, layer) != null; + } + + /** + * Sets the tiles content + * @param {Vector} tile + * @param {Entity} entity + */ + setTileContent(tile, entity) { + if (G_IS_DEV) { + this.internalCheckTile(tile); + } + + this.getOrCreateChunkAtTile(tile.x, tile.y).setLayerContentFromWorldCords( + tile.x, + tile.y, + entity, + entity.layer + ); + + const staticComponent = entity.components.StaticMapEntity; + assert(staticComponent, "Can only place static map entities in tiles"); + } + + /** + * Places an entity with the StaticMapEntity component + * @param {Entity} entity + */ + placeStaticEntity(entity) { + assert(entity.components.StaticMapEntity, "Entity is not static"); + const staticComp = entity.components.StaticMapEntity; + const rect = staticComp.getTileSpaceBounds(); + for (let dx = 0; dx < rect.w; ++dx) { + for (let dy = 0; dy < rect.h; ++dy) { + const x = rect.x + dx; + const y = rect.y + dy; + this.getOrCreateChunkAtTile(x, y).setLayerContentFromWorldCords(x, y, entity, entity.layer); + } + } + } + + /** + * Removes an entity with the StaticMapEntity component + * @param {Entity} entity + */ + removeStaticEntity(entity) { + assert(entity.components.StaticMapEntity, "Entity is not static"); + const staticComp = entity.components.StaticMapEntity; + const rect = staticComp.getTileSpaceBounds(); + for (let dx = 0; dx < rect.w; ++dx) { + for (let dy = 0; dy < rect.h; ++dy) { + const x = rect.x + dx; + const y = rect.y + dy; + this.getOrCreateChunkAtTile(x, y).setLayerContentFromWorldCords(x, y, null, entity.layer); + } + } + } + + // Internal + + /** + * Checks a given tile for validty + * @param {Vector} tile + */ + internalCheckTile(tile) { + assert(tile instanceof Vector, "tile is not a vector: " + tile); + assert(tile.x % 1 === 0, "Tile X is not a valid integer: " + tile.x); + assert(tile.y % 1 === 0, "Tile Y is not a valid integer: " + tile.y); + } +} 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..848afbab 100644 --- a/src/js/game/map_chunk_view.js +++ b/src/js/game/map_chunk_view.js @@ -1,77 +1,298 @@ -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; + const extrude = 0.05; + + // Draw chunk "pixel" art + parameters.context.imageSmoothingEnabled = false; + drawSpriteClipped({ + parameters, + sprite, + x: this.x * dims - extrude, + y: this.y * dims - extrude, + w: dims + 2 * extrude, + h: dims + 2 * extrude, + originalW: overlaySize, + originalH: overlaySize, + }); + + parameters.context.imageSmoothingEnabled = true; + const resourcesScale = this.root.app.settings.getAllSettings().mapResourcesScale; + + // Draw patch items + if (this.root.currentLayer === "regular" && resourcesScale > 0.05) { + const diameter = (70 / Math.pow(parameters.zoomLevel, 0.35)) * (0.2 + 2 * resourcesScale); + + for (let i = 0; i < this.patches.length; ++i) { + const patch = this.patches[i]; + if (patch.item.getItemType() === "shape") { + const destX = this.x * dims + patch.pos.x * globalConfig.tileSize; + const destY = this.y * dims + patch.pos.y * globalConfig.tileSize; + 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( + data.variant, + data.rotationVariant + ); + 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( + data.variant, + data.rotationVariant + ); + 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(data.variant, data.rotationVariant); + 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..296291e9 100644 --- a/src/js/game/map_view.js +++ b/src/js/game/map_view.js @@ -1,254 +1,208 @@ -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; + 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; + } + + /** + * 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) { + if (G_IS_DEV && (globalConfig.debug.showAcceptorEjectors || globalConfig.debug.showEntityBounds)) { + 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) { + // Render tile grid + if (!this.root.app.settings.getAllSettings().disableTileGrid) { + const dpi = this.backgroundCacheDPI; + parameters.context.scale(1 / dpi, 1 / dpi); + + parameters.context.fillStyle = parameters.context.createPattern( + this.cachedBackgroundCanvas, + "repeat" + ); + 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..9deee272 100644 --- a/src/js/game/meta_building.js +++ b/src/js/game/meta_building.js @@ -1,222 +1,275 @@ -import { Loader } from "../core/loader"; -import { AtlasSprite } from "../core/sprites"; -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"; - -export const defaultBuildingVariant = "default"; - -export class MetaBuilding { - /** - * - * @param {string} id Building id - */ - constructor(id) { - this.id = id; - } - - /** - * Returns the id of this building - */ - getId() { - return this.id; - } - - /** - * Returns the edit layer of the building - * @returns {enumLayer} - */ - getLayer() { - return enumLayer.regular; - } - - /** - * Should return the dimensions of the building - */ - getDimensions(variant = defaultBuildingVariant) { - return new Vector(1, 1); - } - - /** - * Returns whether the building has the direction lock switch available - */ - getHasDirectionLockAvailable() { - return false; - } - - /** - * Whether to stay in placement mode after having placed a building - */ - getStayInPlacementMode() { - return false; - } - - /** - * Should return additional statistics about this building - * @param {GameRoot} root - * @param {string} variant - * @returns {Array<[string, string]>} - */ - getAdditionalStatistics(root, variant) { - return []; - } - - /** - * Whether to flip the orientation after a building has been placed - useful - * for tunnels. - */ - getFlipOrientationAfterPlacement() { - return false; - } - - /** - * Whether to rotate automatically in the dragging direction while placing - * @param {string} variant - */ - getRotateAutomaticallyWhilePlacing(variant) { - return false; - } - - /** - * Returns the placement sound - * @returns {string} - */ - getPlacementSound() { - return SOUNDS.placeBuilding; - } - - /** - * @param {GameRoot} root - */ - getAvailableVariants(root) { - return [defaultBuildingVariant]; - } - - /** - * Returns a preview sprite - * @returns {AtlasSprite} - */ - getPreviewSprite(rotationVariant = 0, variant = defaultBuildingVariant) { - return Loader.getSprite( - "sprites/buildings/" + - this.id + - (variant === defaultBuildingVariant ? "" : "-" + variant) + - ".png" - ); - } - - /** - * Returns a sprite for blueprints - * @returns {AtlasSprite} - */ - getBlueprintSprite(rotationVariant = 0, variant = defaultBuildingVariant) { - return Loader.getSprite( - "sprites/blueprints/" + - this.id + - (variant === defaultBuildingVariant ? "" : "-" + variant) + - ".png" - ); - } - - /** - * Returns whether this building is rotateable - * @param {string} variant - * @returns {boolean} - */ - isRotateable(variant) { - return true; - } - - /** - * Returns whether this building is unlocked for the given game - * @param {GameRoot} root - */ - getIsUnlocked(root) { - return true; - } - - /** - * Should return a silhouette color for the map overview or null if not set - */ - getSilhouetteColor() { - return null; - } - - /** - * Creates the entity without placing it - * @param {object} param0 - * @param {GameRoot} param0.root - * @param {Vector} param0.origin Origin tile - * @param {number=} param0.rotation Rotation - * @param {number} param0.originalRotation Original Rotation - * @param {number} param0.rotationVariant Rotation variant - * @param {string} param0.variant - */ - 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 : "", - }) - ); - this.setupEntityComponents(entity, root); - this.updateVariants(entity, rotationVariant, variant); - return entity; - } - - /** - * 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 }) { - if (!this.isRotateable(variant)) { - return { - rotation: 0, - rotationVariant: 0, - }; - } - return { - rotation, - rotationVariant: 0, - }; - } - - /** - * Should update the entity to match the given variants - * @param {Entity} entity - * @param {number} rotationVariant - * @param {string} variant - */ - updateVariants(entity, rotationVariant, variant) {} - - // PRIVATE INTERFACE - - /** - * Should setup the entity components - * @param {Entity} entity - * @param {GameRoot} root - */ - setupEntityComponents(entity, root) { - abstract; - } -} +import { Loader } from "../core/loader"; +import { AtlasSprite } from "../core/sprites"; +import { Vector } from "../core/vector"; +import { SOUNDS } from "../platform/sound"; +import { StaticMapEntityComponent } from "./components/static_map_entity"; +import { Entity } from "./entity"; +import { GameRoot } from "./root"; +import { getCodeFromBuildingData } from "./building_codes"; + +export const defaultBuildingVariant = "default"; + +export class MetaBuilding { + /** + * + * @param {string} id Building id + */ + constructor(id) { + this.id = id; + } + + /** + * Returns the id of this building + */ + getId() { + return this.id; + } + + /** + * Returns the edit layer of the building + * @returns {Layer} + */ + getLayer() { + return "regular"; + } + + /** + * Should return the dimensions of the building + */ + getDimensions(variant = defaultBuildingVariant) { + return new Vector(1, 1); + } + + /** + * Returns whether the building has the direction lock switch available + */ + getHasDirectionLockAvailable() { + return false; + } + + /** + * Whether to stay in placement mode after having placed a building + */ + getStayInPlacementMode() { + 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 + * @param {string} variant + * @returns {Array<[string, string]>} + */ + getAdditionalStatistics(root, variant) { + 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. + */ + getFlipOrientationAfterPlacement() { + 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 + */ + getRotateAutomaticallyWhilePlacing(variant) { + return false; + } + + /** + * Returns whether this building is removable + * @returns {boolean} + */ + getIsRemovable() { + return true; + } + + /** + * Returns the placement sound + * @returns {string} + */ + getPlacementSound() { + return SOUNDS.placeBuilding; + } + + /** + * @param {GameRoot} root + */ + getAvailableVariants(root) { + return [defaultBuildingVariant]; + } + + /** + * Returns a preview sprite + * @returns {AtlasSprite} + */ + getPreviewSprite(rotationVariant = 0, variant = defaultBuildingVariant) { + return Loader.getSprite( + "sprites/buildings/" + + this.id + + (variant === defaultBuildingVariant ? "" : "-" + variant) + + ".png" + ); + } + + /** + * Returns a sprite for blueprints + * @returns {AtlasSprite} + */ + getBlueprintSprite(rotationVariant = 0, variant = defaultBuildingVariant) { + return Loader.getSprite( + "sprites/blueprints/" + + this.id + + (variant === defaultBuildingVariant ? "" : "-" + variant) + + ".png" + ); + } + + /** + * Returns whether this building is rotateable + * @param {string} variant + * @returns {boolean} + */ + getIsRotateable(variant) { + return true; + } + + /** + * Returns whether this building is unlocked for the given game + * @param {GameRoot} root + */ + getIsUnlocked(root) { + return true; + } + + /** + * Should return a silhouette color for the map overview or null if not set + * @param {string} variant + * @param {number} rotationVariant + */ + getSilhouetteColor(variant, rotationVariant) { + 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 + * @param {GameRoot} param0.root + * @param {Vector} param0.origin Origin tile + * @param {number=} param0.rotation Rotation + * @param {number} param0.originalRotation Original Rotation + * @param {number} param0.rotationVariant Rotation variant + * @param {string} param0.variant + */ + createEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) { + const entity = new Entity(root); + entity.layer = this.getLayer(); + entity.addComponent( + new StaticMapEntityComponent({ + origin: new Vector(origin.x, origin.y), + rotation, + originalRotation, + tileSize: this.getDimensions(variant).copy(), + code: getCodeFromBuildingData(this, variant, rotationVariant), + }) + ); + this.setupEntityComponents(entity, root); + this.updateVariants(entity, rotationVariant, variant); + 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 + * @param {GameRoot} param0.root + * @param {Vector} param0.tile + * @param {number} param0.rotation + * @param {string} param0.variant + * @param {Layer} param0.layer + * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array }} + */ + computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { + if (!this.getIsRotateable(variant)) { + return { + rotation: 0, + rotationVariant: 0, + }; + } + return { + rotation, + rotationVariant: 0, + }; + } + + /** + * Should update the entity to match the given variants + * @param {Entity} entity + * @param {number} rotationVariant + * @param {string} variant + */ + updateVariants(entity, rotationVariant, variant) {} + + // PRIVATE INTERFACE + + /** + * Should setup the entity components + * @param {Entity} entity + * @param {GameRoot} root + */ + setupEntityComponents(entity, root) { + abstract; + } +} diff --git a/src/js/game/meta_building_registry.js b/src/js/game/meta_building_registry.js index 4e1fdd81..0613103e 100644 --- a/src/js/game/meta_building_registry.js +++ b/src/js/game/meta_building_registry.js @@ -1,35 +1,235 @@ -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 { T } from "../translations"; +import { MetaAnalyzerBuilding } from "./buildings/analyzer"; +import { enumBalancerVariants, MetaBalancerBuilding } from "./buildings/balancer"; +import { MetaBeltBuilding } from "./buildings/belt"; +import { MetaComparatorBuilding } from "./buildings/comparator"; +import { MetaConstantSignalBuilding } from "./buildings/constant_signal"; +import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter"; +import { MetaDisplayBuilding } from "./buildings/display"; +import { MetaFilterBuilding } from "./buildings/filter"; +import { MetaHubBuilding } from "./buildings/hub"; +import { MetaItemProducerBuilding } from "./buildings/item_producer"; +import { MetaLeverBuilding } from "./buildings/lever"; +import { enumLogicGateVariants, MetaLogicGateBuilding } from "./buildings/logic_gate"; +import { enumMinerVariants, MetaMinerBuilding } from "./buildings/miner"; +import { MetaMixerBuilding } from "./buildings/mixer"; +import { enumPainterVariants, MetaPainterBuilding } from "./buildings/painter"; +import { MetaReaderBuilding } from "./buildings/reader"; +import { enumRotaterVariants, MetaRotaterBuilding } from "./buildings/rotater"; +import { MetaStackerBuilding } from "./buildings/stacker"; +import { MetaStorageBuilding } from "./buildings/storage"; +import { enumTransistorVariants, MetaTransistorBuilding } from "./buildings/transistor"; +import { MetaTrashBuilding } from "./buildings/trash"; +import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt"; +import { enumVirtualProcessorVariants, MetaVirtualProcessorBuilding } from "./buildings/virtual_processor"; +import { MetaWireBuilding } from "./buildings/wire"; +import { MetaWireTunnelBuilding } from "./buildings/wire_tunnel"; +import { buildBuildingCodeCache, gBuildingVariants, registerBuildingVariant } from "./building_codes"; +import { enumWireVariant } from "./components/wire"; +import { KEYMAPPINGS } from "./key_action_mapper"; +import { defaultBuildingVariant } from "./meta_building"; + +const logger = createLogger("building_registry"); + +export function initMetaBuildingRegistry() { + gMetaBuildingRegistry.register(MetaBalancerBuilding); + gMetaBuildingRegistry.register(MetaMinerBuilding); + gMetaBuildingRegistry.register(MetaCutterBuilding); + gMetaBuildingRegistry.register(MetaRotaterBuilding); + gMetaBuildingRegistry.register(MetaStackerBuilding); + gMetaBuildingRegistry.register(MetaMixerBuilding); + gMetaBuildingRegistry.register(MetaPainterBuilding); + gMetaBuildingRegistry.register(MetaTrashBuilding); + gMetaBuildingRegistry.register(MetaStorageBuilding); + 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); + gMetaBuildingRegistry.register(MetaTransistorBuilding); + gMetaBuildingRegistry.register(MetaAnalyzerBuilding); + gMetaBuildingRegistry.register(MetaComparatorBuilding); + gMetaBuildingRegistry.register(MetaItemProducerBuilding); + + // Belt + registerBuildingVariant(1, MetaBeltBuilding, defaultBuildingVariant, 0); + registerBuildingVariant(2, MetaBeltBuilding, defaultBuildingVariant, 1); + registerBuildingVariant(3, MetaBeltBuilding, defaultBuildingVariant, 2); + + // Balancer + registerBuildingVariant(4, MetaBalancerBuilding); + registerBuildingVariant(5, MetaBalancerBuilding, enumBalancerVariants.merger); + registerBuildingVariant(6, MetaBalancerBuilding, enumBalancerVariants.mergerInverse); + registerBuildingVariant(47, MetaBalancerBuilding, enumBalancerVariants.splitter); + registerBuildingVariant(48, MetaBalancerBuilding, enumBalancerVariants.splitterInverse); + + // 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.rotate180); + + // 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); + + // Storage + registerBuildingVariant(21, MetaStorageBuilding); + + // 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); + + registerBuildingVariant(52, MetaWireBuilding, enumWireVariant.second, 0); + registerBuildingVariant(53, MetaWireBuilding, enumWireVariant.second, 1); + registerBuildingVariant(54, MetaWireBuilding, enumWireVariant.second, 2); + registerBuildingVariant(55, MetaWireBuilding, enumWireVariant.second, 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); + + // Transistor + registerBuildingVariant(38, MetaTransistorBuilding, defaultBuildingVariant); + registerBuildingVariant(60, MetaTransistorBuilding, enumTransistorVariants.mirrored); + + // Lever + registerBuildingVariant(33, MetaLeverBuilding); + + // Filter + registerBuildingVariant(37, MetaFilterBuilding); + + // Wire tunnel + registerBuildingVariant(39, MetaWireTunnelBuilding); + + // Display + registerBuildingVariant(40, MetaDisplayBuilding); + + // Virtual Processor + registerBuildingVariant(42, MetaVirtualProcessorBuilding); + registerBuildingVariant(44, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.rotater); + registerBuildingVariant(45, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.unstacker); + registerBuildingVariant(50, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.stacker); + registerBuildingVariant(51, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.painter); + + // Analyzer + registerBuildingVariant(46, MetaComparatorBuilding); + registerBuildingVariant(43, MetaAnalyzerBuilding); + + // Reader + registerBuildingVariant(49, MetaReaderBuilding); + + // Item producer + registerBuildingVariant(61, MetaItemProducerBuilding); + + // 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; + } + } + + // Check for valid keycodes + if (G_IS_DEV) { + gMetaBuildingRegistry.entries.forEach(metaBuilding => { + const id = metaBuilding.getId(); + if (!["hub"].includes(id)) { + if (!KEYMAPPINGS.buildings[id]) { + assertAlways( + false, + "Building " + id + " has no keybinding assigned! Add it to key_action_mapper.js" + ); + } + + if (!T.buildings[id]) { + assertAlways(false, "Translation for building " + id + " missing!"); + } + + if (!T.buildings[id].default) { + assertAlways(false, "Translation for building " + id + " missing (default variant)!"); + } + } + }); + } + + 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( + variant.variant, + variant.rotationVariant + ); + } + + // Update caches + buildBuildingCodeCache(); +} diff --git a/src/js/game/modes/regular.js b/src/js/game/modes/regular.js new file mode 100644 index 00000000..e99f4a7c --- /dev/null +++ b/src/js/game/modes/regular.js @@ -0,0 +1,480 @@ +import { findNiceIntegerValue } from "../../core/utils"; +import { GameMode } from "../game_mode"; +import { ShapeDefinition } from "../shape_definition"; +import { enumHubGoalRewards } from "../tutorial_goals"; + +const rocketShape = "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw"; +const finalGameShape = "RuCw--Cw:----Ru--"; +const preparementShape = "CpRpCp--:SwSwSwSw"; +const blueprintShape = "CbCbCbRb:CwCwCwCw"; + +// Tiers need % of the previous tier as requirement too +const tierGrowth = 2.5; + +/** + * Generates all upgrades + * @returns {Object} */ +function generateUpgrades(limitedVersion = false) { + const fixedImprovements = [0.5, 0.5, 1, 1, 2, 1, 1]; + const numEndgameUpgrades = limitedVersion ? 0 : 1000 - fixedImprovements.length - 1; + + function generateInfiniteUnlocks() { + return new Array(numEndgameUpgrades).fill(null).map((_, i) => ({ + required: [ + { shape: preparementShape, amount: 30000 + i * 10000 }, + { shape: finalGameShape, amount: 20000 + i * 5000 }, + { shape: rocketShape, amount: 20000 + i * 5000 }, + ], + excludePrevious: true, + })); + } + + // Fill in endgame upgrades + for (let i = 0; i < numEndgameUpgrades; ++i) { + if (i < 20) { + fixedImprovements.push(0.1); + } else if (i < 50) { + fixedImprovements.push(0.05); + } else if (i < 100) { + fixedImprovements.push(0.025); + } else { + fixedImprovements.push(0.0125); + } + } + + const upgrades = { + belt: [ + { + required: [{ shape: "CuCuCuCu", amount: 30 }], + }, + { + required: [{ shape: "--CuCu--", amount: 500 }], + }, + { + required: [{ shape: "CpCpCpCp", amount: 1000 }], + }, + { + required: [{ shape: "SrSrSrSr:CyCyCyCy", amount: 6000 }], + }, + { + required: [{ shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", amount: 25000 }], + }, + { + required: [{ shape: preparementShape, amount: 25000 }], + excludePrevious: true, + }, + { + required: [ + { shape: preparementShape, amount: 25000 }, + { shape: finalGameShape, amount: 50000 }, + ], + excludePrevious: true, + }, + ...generateInfiniteUnlocks(), + ], + + miner: [ + { + required: [{ shape: "RuRuRuRu", amount: 300 }], + }, + { + required: [{ shape: "Cu------", amount: 800 }], + }, + { + required: [{ shape: "ScScScSc", amount: 3500 }], + }, + { + required: [{ shape: "CwCwCwCw:WbWbWbWb", amount: 23000 }], + }, + { + required: [{ shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", amount: 50000 }], + }, + { + required: [{ shape: preparementShape, amount: 25000 }], + excludePrevious: true, + }, + { + required: [ + { shape: preparementShape, amount: 25000 }, + { shape: finalGameShape, amount: 50000 }, + ], + excludePrevious: true, + }, + ...generateInfiniteUnlocks(), + ], + + processors: [ + { + required: [{ shape: "SuSuSuSu", amount: 500 }], + }, + { + required: [{ shape: "RuRu----", amount: 600 }], + }, + { + required: [{ shape: "CgScScCg", amount: 3500 }], + }, + { + required: [{ shape: "CwCrCwCr:SgSgSgSg", amount: 25000 }], + }, + { + required: [{ shape: "WrRgWrRg:CwCrCwCr:SgSgSgSg", amount: 50000 }], + }, + { + required: [{ shape: preparementShape, amount: 25000 }], + excludePrevious: true, + }, + { + required: [ + { shape: preparementShape, amount: 25000 }, + { shape: finalGameShape, amount: 50000 }, + ], + excludePrevious: true, + }, + ...generateInfiniteUnlocks(), + ], + + painting: [ + { + required: [{ shape: "RbRb----", amount: 600 }], + }, + { + required: [{ shape: "WrWrWrWr", amount: 3800 }], + }, + { + required: [{ shape: "RpRpRpRp:CwCwCwCw", amount: 6500 }], + }, + { + required: [{ shape: "WpWpWpWp:CwCwCwCw:WpWpWpWp", amount: 25000 }], + }, + { + required: [{ shape: "WpWpWpWp:CwCwCwCw:WpWpWpWp:CwCwCwCw", amount: 50000 }], + }, + { + required: [{ shape: preparementShape, amount: 25000 }], + excludePrevious: true, + }, + { + required: [ + { shape: preparementShape, amount: 25000 }, + { shape: finalGameShape, amount: 50000 }, + ], + excludePrevious: true, + }, + ...generateInfiniteUnlocks(), + ], + }; + + // Automatically generate tier levels + for (const upgradeId in upgrades) { + const upgradeTiers = upgrades[upgradeId]; + + let currentTierRequirements = []; + for (let i = 0; i < upgradeTiers.length; ++i) { + const tierHandle = upgradeTiers[i]; + tierHandle.improvement = fixedImprovements[i]; + const originalRequired = tierHandle.required.slice(); + + for (let k = currentTierRequirements.length - 1; k >= 0; --k) { + const oldTierRequirement = currentTierRequirements[k]; + if (!tierHandle.excludePrevious) { + tierHandle.required.unshift({ + shape: oldTierRequirement.shape, + amount: oldTierRequirement.amount, + }); + } + } + currentTierRequirements.push( + ...originalRequired.map(req => ({ + amount: req.amount, + shape: req.shape, + })) + ); + currentTierRequirements.forEach(tier => { + tier.amount = findNiceIntegerValue(tier.amount * tierGrowth); + }); + } + } + + // VALIDATE + if (G_IS_DEV) { + for (const upgradeId in upgrades) { + upgrades[upgradeId].forEach(tier => { + tier.required.forEach(({ shape }) => { + try { + ShapeDefinition.fromShortKey(shape); + } catch (ex) { + throw new Error("Invalid upgrade goal: '" + ex + "' for shape" + shape); + } + }); + }); + } + } + + return upgrades; +} + +/** + * Generates the level definitions + * @param {boolean} limitedVersion + */ +export function generateLevelDefinitions(limitedVersion = false) { + const levelDefinitions = [ + // 1 + // Circle + { + shape: "CuCuCuCu", // belts t1 + required: 30, + reward: enumHubGoalRewards.reward_cutter_and_trash, + }, + + // 2 + // Cutter + { + shape: "----CuCu", // + required: 40, + reward: enumHubGoalRewards.no_reward, + }, + + // 3 + // Rectangle + { + shape: "RuRuRuRu", // miners t1 + required: 70, + reward: enumHubGoalRewards.reward_balancer, + }, + + // 4 + { + shape: "RuRu----", // processors t2 + required: 70, + reward: enumHubGoalRewards.reward_rotater, + }, + + // 5 + // Rotater + { + shape: "Cu----Cu", // belts t2 + required: 170, + reward: enumHubGoalRewards.reward_tunnel, + }, + + // 6 + { + shape: "Cu------", // miners t2 + required: 270, + reward: enumHubGoalRewards.reward_painter, + }, + + // 7 + // Painter + { + shape: "CrCrCrCr", // unused + required: 300, + reward: enumHubGoalRewards.reward_rotater_ccw, + }, + + // 8 + { + shape: "RbRb----", // painter t2 + required: 480, + reward: enumHubGoalRewards.reward_mixer, + }, + + // 9 + // Mixing (purple) + { + shape: "CpCpCpCp", // belts t3 + required: 600, + reward: enumHubGoalRewards.reward_merger, + }, + + // 10 + // STACKER: Star shape + cyan + { + shape: "ScScScSc", // miners t3 + required: 800, + reward: enumHubGoalRewards.reward_stacker, + }, + + // 11 + // Chainable miner + { + shape: "CgScScCg", // processors t3 + required: 1000, + reward: enumHubGoalRewards.reward_miner_chainable, + }, + + // 12 + // Blueprints + { + shape: "CbCbCbRb:CwCwCwCw", + required: 1000, + reward: enumHubGoalRewards.reward_blueprints, + }, + + // 13 + // Tunnel Tier 2 + { + shape: "RpRpRpRp:CwCwCwCw", // painting t3 + required: 3800, + reward: enumHubGoalRewards.reward_underground_belt_tier_2, + }, + + // DEMO STOPS HERE + ...(limitedVersion + ? [ + { + shape: "RpRpRpRp:CwCwCwCw", + required: 0, + reward: enumHubGoalRewards.reward_demo_end, + }, + ] + : [ + // 14 + // Belt reader + { + shape: "--Cg----:--Cr----", // unused + required: 8, // Per second! + reward: enumHubGoalRewards.reward_belt_reader, + throughputOnly: true, + }, + + // 15 + // Storage + { + shape: "SrSrSrSr:CyCyCyCy", // unused + required: 10000, + reward: enumHubGoalRewards.reward_storage, + }, + + // 16 + // Quad Cutter + { + shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", // belts t4 (two variants) + required: 6000, + reward: enumHubGoalRewards.reward_cutter_quad, + }, + + // 17 + // Double painter + { + shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants) + required: 20000, + reward: enumHubGoalRewards.reward_painter_double, + }, + + // 18 + // Rotater (180deg) + { + shape: "Sg----Sg:CgCgCgCg:--CyCy--", // unused + required: 20000, + reward: enumHubGoalRewards.reward_rotater_180, + }, + + // 19 + // Compact splitter + { + shape: "CpRpCp--:SwSwSwSw", + required: 25000, + reward: enumHubGoalRewards.reward_splitter, + }, + + // 20 + // WIRES + { + shape: finalGameShape, + required: 25000, + reward: enumHubGoalRewards.reward_wires_painter_and_levers, + }, + + // 21 + // Filter + { + shape: "CrCwCrCw:CwCrCwCr:CrCwCrCw:CwCrCwCr", + required: 25000, + reward: enumHubGoalRewards.reward_filter, + }, + + // 22 + // Constant signal + { + shape: "Cg----Cr:Cw----Cw:Sy------:Cy----Cy", + required: 25000, + reward: enumHubGoalRewards.reward_constant_signal, + }, + + // 23 + // Display + { + shape: "CcSyCcSy:SyCcSyCc:CcSyCcSy", + required: 25000, + reward: enumHubGoalRewards.reward_display, + }, + + // 24 Logic gates + { + shape: "CcRcCcRc:RwCwRwCw:Sr--Sw--:CyCyCyCy", + required: 25000, + reward: enumHubGoalRewards.reward_logic_gates, + }, + + // 25 Virtual Processing + { + shape: "Rg--Rg--:CwRwCwRw:--Rg--Rg", + required: 25000, + reward: enumHubGoalRewards.reward_virtual_processing, + }, + + // 26 Freeplay + { + shape: "CbCuCbCu:Sr------:--CrSrCr:CwCwCwCw", + required: 50000, + reward: enumHubGoalRewards.reward_freeplay, + }, + ]), + ]; + + if (G_IS_DEV) { + levelDefinitions.forEach(({ shape }) => { + try { + ShapeDefinition.fromShortKey(shape); + } catch (ex) { + throw new Error("Invalid tutorial goal: '" + ex + "' for shape" + shape); + } + }); + } + + return levelDefinitions; +} + +const fullVersionUpgrades = generateUpgrades(false); +const demoVersionUpgrades = generateUpgrades(true); + +const fullVersionLevels = generateLevelDefinitions(false); +const demoVersionLevels = generateLevelDefinitions(true); + +export class RegularGameMode extends GameMode { + constructor(root) { + super(root); + } + + getUpgrades() { + return this.root.app.restrictionMgr.getHasExtendedUpgrades() + ? fullVersionUpgrades + : demoVersionUpgrades; + } + + getIsFreeplayAvailable() { + return this.root.app.restrictionMgr.getHasExtendedLevelsAndFreeplay(); + } + + getBlueprintShapeKey() { + return blueprintShape; + } + + getLevelDefinitions() { + return this.root.app.restrictionMgr.getHasExtendedLevelsAndFreeplay() + ? fullVersionLevels + : demoVersionLevels; + } +} 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..6f1e7c36 100644 --- a/src/js/game/root.js +++ b/src/js/game/root.js @@ -1,229 +1,225 @@ -/* eslint-disable no-unused-vars */ - -import { Signal } from "../core/signal"; -import { RandomNumberGenerator } from "../core/rng"; -import { createLogger } from "../core/logging"; - -// Type hints -/* typehints:start */ -import { GameTime } from "./time/game_time"; -import { EntityManager } from "./entity_manager"; -import { GameSystemManager } from "./game_system_manager"; -import { GameHUD } from "./hud/hud"; -import { MapView } from "./map_view"; -import { Camera } from "./camera"; -import { InGameState } from "../states/ingame"; -import { AutomaticSave } from "./automatic_save"; -import { Application } from "../application"; -import { SoundProxy } from "./sound_proxy"; -import { Savegame } from "../savegame/savegame"; -import { GameLogic } from "./logic"; -import { ShapeDefinitionManager } from "./shape_definition_manager"; -import { HubGoals } from "./hub_goals"; -import { BufferMaintainer } from "../core/buffer_maintainer"; -import { ProductionAnalytics } from "./production_analytics"; -import { Entity } from "./entity"; -import { ShapeDefinition } from "./shape_definition"; -import { BaseItem } from "./base_item"; -import { DynamicTickrate } from "./dynamic_tickrate"; -import { KeyActionMapper } from "./key_action_mapper"; -import { Vector } from "../core/vector"; -/* typehints:end */ - -const logger = createLogger("game/root"); - -/** @enum {string} */ -export const enumLayer = { - regular: "regular", - wires: "wires", -}; - -/** @type {Array} */ -export const arrayLayers = [enumLayer.regular, enumLayer.wires]; - -/** - * The game root is basically the whole game state at a given point, - * combining all important classes. We don't have globals, but this - * class is passed to almost all game classes. - */ -export class GameRoot { - /** - * Constructs a new game root - * @param {Application} app - */ - constructor(app) { - this.app = app; - - /** @type {Savegame} */ - this.savegame = null; - - /** @type {InGameState} */ - this.gameState = null; - - /** @type {KeyActionMapper} */ - this.keyMapper = null; - - // Store game dimensions - this.gameWidth = 500; - this.gameHeight = 500; - - // Stores whether the current session is a fresh game (true), or was continued (false) - /** @type {boolean} */ - this.gameIsFresh = true; - - // Stores whether the logic is already initialized - /** @type {boolean} */ - this.logicInitialized = false; - - // Stores whether the game is already initialized, that is, all systems etc have been created - /** @type {boolean} */ - this.gameInitialized = false; - - /** - * Whether a bulk operation is running - */ - this.bulkOperationRunning = false; - - //////// Other properties /////// - - /** @type {Camera} */ - this.camera = null; - - /** @type {HTMLCanvasElement} */ - this.canvas = null; - - /** @type {CanvasRenderingContext2D} */ - this.context = null; - - /** @type {MapView} */ - this.map = null; - - /** @type {GameLogic} */ - this.logic = null; - - /** @type {EntityManager} */ - this.entityMgr = null; - - /** @type {GameHUD} */ - this.hud = null; - - /** @type {GameSystemManager} */ - this.systemMgr = null; - - /** @type {GameTime} */ - this.time = null; - - /** @type {HubGoals} */ - this.hubGoals = null; - - /** @type {BufferMaintainer} */ - this.buffers = null; - - /** @type {AutomaticSave} */ - this.automaticSave = null; - - /** @type {SoundProxy} */ - this.soundProxy = null; - - /** @type {ShapeDefinitionManager} */ - this.shapeDefinitionMgr = null; - - /** @type {ProductionAnalytics} */ - this.productionAnalytics = null; - - /** @type {DynamicTickrate} */ - this.dynamicTickrate = null; - - /** @type {enumLayer} */ - this.currentLayer = enumLayer.regular; - - this.signals = { - // Entities - entityManuallyPlaced: /** @type {TypedSignal<[Entity]>} */ (new Signal()), - entityAdded: /** @type {TypedSignal<[Entity]>} */ (new Signal()), - entityChanged: /** @type {TypedSignal<[Entity]>} */ (new Signal()), - entityGotNewComponent: /** @type {TypedSignal<[Entity]>} */ (new Signal()), - entityComponentRemoved: /** @type {TypedSignal<[Entity]>} */ (new Signal()), - entityQueuedForDestroy: /** @type {TypedSignal<[Entity]>} */ (new Signal()), - entityDestroyed: /** @type {TypedSignal<[Entity]>} */ (new Signal()), - - // Global - resized: /** @type {TypedSignal<[number, number]>} */ (new Signal()), - readyToRender: /** @type {TypedSignal<[]>} */ (new Signal()), - aboutToDestruct: /** @type {TypedSignal<[]>} */ new Signal(), - - // Game Hooks - gameSaved: /** @type {TypedSignal<[]>} */ (new Signal()), // Game got saved - gameRestored: /** @type {TypedSignal<[]>} */ (new Signal()), // Game got restored - - 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()), - - // Called to check if an entity can be placed, second parameter is an additional offset. - // Use to introduce additional placement checks - prePlacementCheck: /** @type {TypedSignal<[Entity, Vector]>} */ (new Signal()), - - // Called before actually placing an entity, use to perform additional logic - // for freeing space before actually placing. - freeEntityAreaBeforeBuild: /** @type {TypedSignal<[Entity]>} */ (new Signal()), - }; - - // RNG's - /** @type {Object.>} */ - this.rngs = {}; - - // Work queue - this.queue = { - requireRedraw: false, - }; - } - - /** - * Destructs the game root - */ - destruct() { - logger.log("destructing root"); - this.signals.aboutToDestruct.dispatch(); - - this.reset(); - } - - /** - * Resets the whole root and removes all properties - */ - reset() { - if (this.signals) { - // Destruct all signals - for (let i = 0; i < this.signals.length; ++i) { - this.signals[i].removeAll(); - } - } - - if (this.hud) { - this.hud.cleanup(); - } - if (this.camera) { - this.camera.cleanup(); - } - - // Finally free all properties - for (let prop in this) { - if (this.hasOwnProperty(prop)) { - delete this[prop]; - } - } - } -} +/* eslint-disable no-unused-vars */ +import { Signal } from "../core/signal"; +import { RandomNumberGenerator } from "../core/rng"; +import { createLogger } from "../core/logging"; + +// Type hints +/* typehints:start */ +import { GameTime } from "./time/game_time"; +import { EntityManager } from "./entity_manager"; +import { GameSystemManager } from "./game_system_manager"; +import { GameHUD } from "./hud/hud"; +import { MapView } from "./map_view"; +import { Camera } from "./camera"; +import { InGameState } from "../states/ingame"; +import { AutomaticSave } from "./automatic_save"; +import { Application } from "../application"; +import { SoundProxy } from "./sound_proxy"; +import { Savegame } from "../savegame/savegame"; +import { GameLogic } from "./logic"; +import { ShapeDefinitionManager } from "./shape_definition_manager"; +import { HubGoals } from "./hub_goals"; +import { BufferMaintainer } from "../core/buffer_maintainer"; +import { ProductionAnalytics } from "./production_analytics"; +import { Entity } from "./entity"; +import { ShapeDefinition } from "./shape_definition"; +import { BaseItem } from "./base_item"; +import { DynamicTickrate } from "./dynamic_tickrate"; +import { KeyActionMapper } from "./key_action_mapper"; +import { Vector } from "../core/vector"; +import { GameMode } from "./game_mode"; +/* typehints:end */ + +const logger = createLogger("game/root"); + +/** @type {Array} */ +export const layers = ["regular", "wires"]; + +/** + * The game root is basically the whole game state at a given point, + * combining all important classes. We don't have globals, but this + * class is passed to almost all game classes. + */ +export class GameRoot { + /** + * Constructs a new game root + * @param {Application} app + */ + constructor(app) { + this.app = app; + + /** @type {Savegame} */ + this.savegame = null; + + /** @type {InGameState} */ + this.gameState = null; + + /** @type {KeyActionMapper} */ + this.keyMapper = null; + + // Store game dimensions + this.gameWidth = 500; + this.gameHeight = 500; + + // Stores whether the current session is a fresh game (true), or was continued (false) + /** @type {boolean} */ + this.gameIsFresh = true; + + // Stores whether the logic is already initialized + /** @type {boolean} */ + this.logicInitialized = false; + + // Stores whether the game is already initialized, that is, all systems etc have been created + /** @type {boolean} */ + this.gameInitialized = false; + + /** + * Whether a bulk operation is running + */ + this.bulkOperationRunning = false; + + //////// Other properties /////// + + /** @type {Camera} */ + this.camera = null; + + /** @type {HTMLCanvasElement} */ + this.canvas = null; + + /** @type {CanvasRenderingContext2D} */ + this.context = null; + + /** @type {MapView} */ + this.map = null; + + /** @type {GameLogic} */ + this.logic = null; + + /** @type {EntityManager} */ + this.entityMgr = null; + + /** @type {GameHUD} */ + this.hud = null; + + /** @type {GameSystemManager} */ + this.systemMgr = null; + + /** @type {GameTime} */ + this.time = null; + + /** @type {HubGoals} */ + this.hubGoals = null; + + /** @type {BufferMaintainer} */ + this.buffers = null; + + /** @type {AutomaticSave} */ + this.automaticSave = null; + + /** @type {SoundProxy} */ + this.soundProxy = null; + + /** @type {ShapeDefinitionManager} */ + this.shapeDefinitionMgr = null; + + /** @type {ProductionAnalytics} */ + this.productionAnalytics = null; + + /** @type {DynamicTickrate} */ + this.dynamicTickrate = null; + + /** @type {Layer} */ + this.currentLayer = "regular"; + + /** @type {GameMode} */ + this.gameMode = null; + + this.signals = { + // Entities + entityManuallyPlaced: /** @type {TypedSignal<[Entity]>} */ (new Signal()), + entityAdded: /** @type {TypedSignal<[Entity]>} */ (new Signal()), + entityChanged: /** @type {TypedSignal<[Entity]>} */ (new Signal()), + entityGotNewComponent: /** @type {TypedSignal<[Entity]>} */ (new Signal()), + entityComponentRemoved: /** @type {TypedSignal<[Entity]>} */ (new Signal()), + entityQueuedForDestroy: /** @type {TypedSignal<[Entity]>} */ (new Signal()), + entityDestroyed: /** @type {TypedSignal<[Entity]>} */ (new Signal()), + + // Global + resized: /** @type {TypedSignal<[number, number]>} */ (new Signal()), + readyToRender: /** @type {TypedSignal<[]>} */ (new Signal()), + aboutToDestruct: /** @type {TypedSignal<[]>} */ new Signal(), + + // Game Hooks + 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()), + + shapeDelivered: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()), + itemProduced: /** @type {TypedSignal<[BaseItem]>} */ (new Signal()), + + bulkOperationFinished: /** @type {TypedSignal<[]>} */ (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 + prePlacementCheck: /** @type {TypedSignal<[Entity, Vector]>} */ (new Signal()), + + // Called before actually placing an entity, use to perform additional logic + // for freeing space before actually placing. + freeEntityAreaBeforeBuild: /** @type {TypedSignal<[Entity]>} */ (new Signal()), + }; + + // RNG's + /** @type {Object.>} */ + this.rngs = {}; + + // Work queue + this.queue = { + requireRedraw: false, + }; + } + + /** + * Destructs the game root + */ + destruct() { + logger.log("destructing root"); + this.signals.aboutToDestruct.dispatch(); + + this.reset(); + } + + /** + * Resets the whole root and removes all properties + */ + reset() { + if (this.signals) { + // Destruct all signals + for (let i = 0; i < this.signals.length; ++i) { + this.signals[i].removeAll(); + } + } + + if (this.hud) { + this.hud.cleanup(); + } + if (this.camera) { + this.camera.cleanup(); + } + + // Finally free all properties + for (let prop in this) { + if (this.hasOwnProperty(prop)) { + delete this[prop]; + } + } + } +} diff --git a/src/js/game/shape_definition.js b/src/js/game/shape_definition.js index af2214e3..b09d73c5 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,34 @@ 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); + } + + /** + * Draws the item to a canvas + * @param {CanvasRenderingContext2D} context + * @param {number} size + */ + drawFullSizeOnCanvas(context, size) { + this.internalGenerateShapeBuffer(null, context, size, size, 1); } /** @@ -495,62 +495,88 @@ export class ShapeDefinition extends BasicSerializableObject { return new ShapeDefinition({ layers: newLayers }); } + /** + * Returns a definition which was rotated 180 degrees + * @returns {ShapeDefinition} + */ + cloneRotate180() { + 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 +598,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 +610,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..5bcfcc4b 100644 --- a/src/js/game/shape_definition_manager.js +++ b/src/js/game/shape_definition_manager.js @@ -1,224 +1,259 @@ -import { BasicSerializableObject } from "../savegame/serialization"; -import { GameRoot } from "./root"; -import { ShapeDefinition, enumSubShape } from "./shape_definition"; -import { createLogger } from "../core/logging"; -import { enumColors } from "./colors"; - -const logger = createLogger("shape_definition_manager"); - -export class ShapeDefinitionManager extends BasicSerializableObject { - static getId() { - return "ShapeDefinitionManager"; - } - - /** - * - * @param {GameRoot} root - */ - constructor(root) { - super(); - this.root = root; - - this.shapeKeyToDefinition = {}; - - // Caches operations in the form of 'operation:def1[:def2]' - /** @type {Object.|ShapeDefinition>} */ - this.operationCache = {}; - } - - /** - * - * @param {string} hash - * @returns {ShapeDefinition} - */ - getShapeFromShortKey(hash) { - const cached = this.shapeKeyToDefinition[hash]; - if (cached) { - return cached; - } - return (this.shapeKeyToDefinition[hash] = ShapeDefinition.fromShortKey(hash)); - } - - /** - * Registers a new shape definition - * @param {ShapeDefinition} definition - */ - registerShapeDefinition(definition) { - const id = definition.getHash(); - assert(!this.shapeKeyToDefinition[id], "Shape Definition " + id + " already exists"); - this.shapeKeyToDefinition[id] = definition; - // logger.log("Registered shape with key", id); - } - - /** - * Generates a definition for splitting a shape definition in two halfs - * @param {ShapeDefinition} definition - * @returns {[ShapeDefinition, ShapeDefinition]} - */ - shapeActionCutHalf(definition) { - const key = "cut:" + definition.getHash(); - if (this.operationCache[key]) { - return /** @type {[ShapeDefinition, ShapeDefinition]} */ (this.operationCache[key]); - } - const rightSide = definition.cloneFilteredByQuadrants([2, 3]); - const leftSide = definition.cloneFilteredByQuadrants([0, 1]); - - return /** @type {[ShapeDefinition, ShapeDefinition]} */ (this.operationCache[key] = [ - this.registerOrReturnHandle(rightSide), - this.registerOrReturnHandle(leftSide), - ]); - } - - /** - * Generates a definition for splitting a shape definition in four quads - * @param {ShapeDefinition} definition - * @returns {[ShapeDefinition, ShapeDefinition, ShapeDefinition, ShapeDefinition]} - */ - shapeActionCutQuad(definition) { - const key = "cut-quad:" + definition.getHash(); - if (this.operationCache[key]) { - return /** @type {[ShapeDefinition, ShapeDefinition, ShapeDefinition, ShapeDefinition]} */ (this - .operationCache[key]); - } - - return /** @type {[ShapeDefinition, ShapeDefinition, ShapeDefinition, ShapeDefinition]} */ (this.operationCache[ - key - ] = [ - this.registerOrReturnHandle(definition.cloneFilteredByQuadrants([0])), - this.registerOrReturnHandle(definition.cloneFilteredByQuadrants([1])), - this.registerOrReturnHandle(definition.cloneFilteredByQuadrants([2])), - this.registerOrReturnHandle(definition.cloneFilteredByQuadrants([3])), - ]); - } - - /** - * Generates a definition for rotating a shape clockwise - * @param {ShapeDefinition} definition - * @returns {ShapeDefinition} - */ - shapeActionRotateCW(definition) { - const key = "rotate-cw:" + definition.getHash(); - if (this.operationCache[key]) { - return /** @type {ShapeDefinition} */ (this.operationCache[key]); - } - - const rotated = definition.cloneRotateCW(); - - return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( - rotated - )); - } - - /** - * Generates a definition for rotating a shape counter clockwise - * @param {ShapeDefinition} definition - * @returns {ShapeDefinition} - */ - shapeActionRotateCCW(definition) { - const key = "rotate-ccw:" + definition.getHash(); - if (this.operationCache[key]) { - return /** @type {ShapeDefinition} */ (this.operationCache[key]); - } - - const rotated = definition.cloneRotateCCW(); - - return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( - rotated - )); - } - - /** - * Generates a definition for stacking the upper definition onto the lower one - * @param {ShapeDefinition} lowerDefinition - * @param {ShapeDefinition} upperDefinition - * @returns {ShapeDefinition} - */ - shapeActionStack(lowerDefinition, upperDefinition) { - const key = "stack:" + lowerDefinition.getHash() + ":" + upperDefinition.getHash(); - if (this.operationCache[key]) { - return /** @type {ShapeDefinition} */ (this.operationCache[key]); - } - const stacked = lowerDefinition.cloneAndStackWith(upperDefinition); - return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( - stacked - )); - } - - /** - * Generates a definition for painting it with the given color - * @param {ShapeDefinition} definition - * @param {enumColors} color - * @returns {ShapeDefinition} - */ - shapeActionPaintWith(definition, color) { - const key = "paint:" + definition.getHash() + ":" + color; - if (this.operationCache[key]) { - return /** @type {ShapeDefinition} */ (this.operationCache[key]); - } - const colorized = definition.cloneAndPaintWith(color); - return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( - colorized - )); - } - - /** - * 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 - * @param {[enumColors, enumColors, enumColors, enumColors]} colors - * @returns {ShapeDefinition} - */ - shapeActionPaintWith4Colors(definition, colors) { - const key = "paint4:" + definition.getHash() + ":" + colors.join(","); - if (this.operationCache[key]) { - return /** @type {ShapeDefinition} */ (this.operationCache[key]); - } - const colorized = definition.cloneAndPaintWith4Colors(colors); - return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( - colorized - )); - } - - /** - * Checks if we already have cached this definition, and if so throws it away and returns the already - * cached variant - * @param {ShapeDefinition} definition - */ - registerOrReturnHandle(definition) { - const id = definition.getHash(); - if (this.shapeKeyToDefinition[id]) { - return this.shapeKeyToDefinition[id]; - } - this.shapeKeyToDefinition[id] = definition; - // logger.log("Registered shape with key (2)", id); - return definition; - } - - /** - * - * @param {[enumSubShape, enumSubShape, enumSubShape, enumSubShape]} subShapes - * @returns {ShapeDefinition} - */ - getDefinitionFromSimpleShapes(subShapes, color = enumColors.uncolored) { - const shapeLayer = /** @type {import("./shape_definition").ShapeLayer} */ (subShapes.map( - subShape => ({ subShape, color }) - )); - - return this.registerOrReturnHandle(new ShapeDefinition({ layers: [shapeLayer] })); - } -} +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"); + +export class ShapeDefinitionManager extends BasicSerializableObject { + static getId() { + return "ShapeDefinitionManager"; + } + + /** + * + * @param {GameRoot} root + */ + constructor(root) { + 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} + */ + getShapeFromShortKey(hash) { + const cached = this.shapeKeyToDefinition[hash]; + if (cached) { + return cached; + } + 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 + */ + registerShapeDefinition(definition) { + const id = definition.getHash(); + assert(!this.shapeKeyToDefinition[id], "Shape Definition " + id + " already exists"); + this.shapeKeyToDefinition[id] = definition; + // logger.log("Registered shape with key", id); + } + + /** + * Generates a definition for splitting a shape definition in two halfs + * @param {ShapeDefinition} definition + * @returns {[ShapeDefinition, ShapeDefinition]} + */ + shapeActionCutHalf(definition) { + const key = "cut/" + definition.getHash(); + if (this.operationCache[key]) { + return /** @type {[ShapeDefinition, ShapeDefinition]} */ (this.operationCache[key]); + } + const rightSide = definition.cloneFilteredByQuadrants([2, 3]); + const leftSide = definition.cloneFilteredByQuadrants([0, 1]); + + return /** @type {[ShapeDefinition, ShapeDefinition]} */ (this.operationCache[key] = [ + this.registerOrReturnHandle(rightSide), + this.registerOrReturnHandle(leftSide), + ]); + } + + /** + * Generates a definition for splitting a shape definition in four quads + * @param {ShapeDefinition} definition + * @returns {[ShapeDefinition, ShapeDefinition, ShapeDefinition, ShapeDefinition]} + */ + shapeActionCutQuad(definition) { + const key = "cut-quad/" + definition.getHash(); + if (this.operationCache[key]) { + return /** @type {[ShapeDefinition, ShapeDefinition, ShapeDefinition, ShapeDefinition]} */ (this + .operationCache[key]); + } + + return /** @type {[ShapeDefinition, ShapeDefinition, ShapeDefinition, ShapeDefinition]} */ (this.operationCache[ + key + ] = [ + this.registerOrReturnHandle(definition.cloneFilteredByQuadrants([0])), + this.registerOrReturnHandle(definition.cloneFilteredByQuadrants([1])), + this.registerOrReturnHandle(definition.cloneFilteredByQuadrants([2])), + this.registerOrReturnHandle(definition.cloneFilteredByQuadrants([3])), + ]); + } + + /** + * Generates a definition for rotating a shape clockwise + * @param {ShapeDefinition} definition + * @returns {ShapeDefinition} + */ + shapeActionRotateCW(definition) { + const key = "rotate-cw/" + definition.getHash(); + if (this.operationCache[key]) { + return /** @type {ShapeDefinition} */ (this.operationCache[key]); + } + + const rotated = definition.cloneRotateCW(); + + return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( + rotated + )); + } + + /** + * Generates a definition for rotating a shape counter clockwise + * @param {ShapeDefinition} definition + * @returns {ShapeDefinition} + */ + shapeActionRotateCCW(definition) { + const key = "rotate-ccw/" + definition.getHash(); + if (this.operationCache[key]) { + return /** @type {ShapeDefinition} */ (this.operationCache[key]); + } + + const rotated = definition.cloneRotateCCW(); + + return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( + rotated + )); + } + + /** + * Generates a definition for rotating a shape FL + * @param {ShapeDefinition} definition + * @returns {ShapeDefinition} + */ + shapeActionRotate180(definition) { + const key = "rotate-fl/" + definition.getHash(); + if (this.operationCache[key]) { + return /** @type {ShapeDefinition} */ (this.operationCache[key]); + } + + const rotated = definition.cloneRotate180(); + + return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( + rotated + )); + } + + /** + * Generates a definition for stacking the upper definition onto the lower one + * @param {ShapeDefinition} lowerDefinition + * @param {ShapeDefinition} upperDefinition + * @returns {ShapeDefinition} + */ + shapeActionStack(lowerDefinition, upperDefinition) { + const key = "stack/" + lowerDefinition.getHash() + "/" + upperDefinition.getHash(); + if (this.operationCache[key]) { + return /** @type {ShapeDefinition} */ (this.operationCache[key]); + } + const stacked = lowerDefinition.cloneAndStackWith(upperDefinition); + return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( + stacked + )); + } + + /** + * Generates a definition for painting it with the given color + * @param {ShapeDefinition} definition + * @param {enumColors} color + * @returns {ShapeDefinition} + */ + shapeActionPaintWith(definition, color) { + const key = "paint/" + definition.getHash() + "/" + color; + if (this.operationCache[key]) { + return /** @type {ShapeDefinition} */ (this.operationCache[key]); + } + const colorized = definition.cloneAndPaintWith(color); + return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( + colorized + )); + } + + /** + * Generates a definition for painting it with the 4 colors + * @param {ShapeDefinition} definition + * @param {[enumColors, enumColors, enumColors, enumColors]} colors + * @returns {ShapeDefinition} + */ + shapeActionPaintWith4Colors(definition, colors) { + const key = "paint4/" + definition.getHash() + "/" + colors.join(","); + if (this.operationCache[key]) { + return /** @type {ShapeDefinition} */ (this.operationCache[key]); + } + const colorized = definition.cloneAndPaintWith4Colors(colors); + return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( + colorized + )); + } + + /** + * Checks if we already have cached this definition, and if so throws it away and returns the already + * cached variant + * @param {ShapeDefinition} definition + */ + registerOrReturnHandle(definition) { + const id = definition.getHash(); + if (this.shapeKeyToDefinition[id]) { + return this.shapeKeyToDefinition[id]; + } + this.shapeKeyToDefinition[id] = definition; + // logger.log("Registered shape with key (2)", id); + return definition; + } + + /** + * + * @param {[enumSubShape, enumSubShape, enumSubShape, enumSubShape]} subShapes + * @returns {ShapeDefinition} + */ + getDefinitionFromSimpleShapes(subShapes, color = enumColors.uncolored) { + const shapeLayer = /** @type {import("./shape_definition").ShapeLayer} */ (subShapes.map( + subShape => ({ subShape, color }) + )); + + return this.registerOrReturnHandle(new ShapeDefinition({ layers: [shapeLayer] })); + } +} diff --git a/src/js/game/systems/belt.js b/src/js/game/systems/belt.js index db538a56..10543e6c 100644 --- a/src/js/game/systems/belt.js +++ b/src/js/game/systems/belt.js @@ -1,580 +1,554 @@ -import { globalConfig } from "../../core/config"; -import { DrawParameters } from "../../core/draw_parameters"; -import { gMetaBuildingRegistry } from "../../core/global_registries"; -import { Loader } from "../../core/loader"; -import { createLogger } from "../../core/logging"; -import { AtlasSprite } from "../../core/sprites"; -import { fastArrayDeleteValue } from "../../core/utils"; -import { enumDirection, enumDirectionToVector, enumInvertedDirections, Vector } from "../../core/vector"; -import { BeltPath } from "../belt_path"; -import { arrayBeltVariantToRotation, MetaBeltBaseBuilding } from "../buildings/belt_base"; -import { BeltComponent } from "../components/belt"; -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"; - -export const BELT_ANIM_COUNT = 28; - -const logger = createLogger("belt"); - -/** - * Manages all belts - */ -export class BeltSystem extends GameSystemWithFilter { - constructor(root) { - super(root, [BeltComponent]); - /** - * @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"), - }; - - /** - * @type {Object.>} - */ - this.beltAnimations = { - [enumDirection.top]: [], - [enumDirection.left]: [], - [enumDirection.right]: [], - }; - - for (let i = 0; i < BELT_ANIM_COUNT; ++i) { - this.beltAnimations[enumDirection.top].push( - Loader.getSprite("sprites/belt/forward_" + 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") - ); - } - - this.root.signals.entityDestroyed.add(this.onEntityDestroyed, this); - this.root.signals.entityDestroyed.add(this.updateSurroundingBeltPlacement, this); - - // Notice: These must come *after* the entity destroyed signals - this.root.signals.entityAdded.add(this.onEntityAdded, this); - this.root.signals.entityAdded.add(this.updateSurroundingBeltPlacement, this); - - /** @type {Array} */ - this.beltPaths = []; - } - - /** - * Serializes all belt paths - * @returns {Array} - */ - serializePaths() { - let data = []; - for (let i = 0; i < this.beltPaths.length; ++i) { - data.push(this.beltPaths[i].serialize()); - } - return data; - } - - /** - * Deserializes all belt paths - * @param {Array} data - */ - deserializePaths(data) { - if (!Array.isArray(data)) { - return "Belt paths are not an array: " + typeof data; - } - - for (let i = 0; i < data.length; ++i) { - const path = BeltPath.fromSerialized(this.root, data[i]); - // If path is a string, that means its an error - if (!(path instanceof BeltPath)) { - return "Failed to create path from belt data: " + path; - } - this.beltPaths.push(path); - } - - if (this.beltPaths.length === 0) { - // Old savegames might not have paths yet - logger.warn("Recomputing belt paths (most likely the savegame is old or empty)"); - this.recomputeAllBeltPaths(); - } else { - logger.warn("Restored", this.beltPaths.length, "belt paths"); - } - - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_verifyBeltPaths(); - } - } - - /** - * Updates the belt placement after an entity has been added / deleted - * @param {Entity} entity - */ - updateSurroundingBeltPlacement(entity) { - if (!this.root.gameInitialized) { - return; - } - - const staticComp = entity.components.StaticMapEntity; - if (!staticComp) { - return; - } - - const metaBelt = gMetaBuildingRegistry.findByClass(MetaBeltBaseBuilding); - // Compute affected area - const originalRect = staticComp.getTileSpaceBounds(); - const affectedArea = originalRect.expandedInAllDirections(1); - - for (let x = affectedArea.x; x < affectedArea.right(); ++x) { - for (let y = affectedArea.y; y < affectedArea.bottom(); ++y) { - if (originalRect.containsPoint(x, y)) { - // Make sure we don't update the original entity - continue; - } - - const targetEntities = this.root.map.getLayersContentsMultipleXY(x, y); - for (let i = 0; i < targetEntities.length; ++i) { - const targetEntity = targetEntities[i]; - - const targetBeltComp = targetEntity.components.Belt; - const targetStaticComp = targetEntity.components.StaticMapEntity; - - if (!targetBeltComp) { - // Not a belt - continue; - } - - const { - rotation, - rotationVariant, - } = metaBelt.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 newDirection = arrayBeltVariantToRotation[rotationVariant]; - - if (targetStaticComp.rotation !== rotation || newDirection !== targetBeltComp.direction) { - // Ok, first remove it from its current path - this.deleteEntityFromPath(targetBeltComp.assignedPath, targetEntity); - - // Change stuff - targetStaticComp.rotation = rotation; - metaBelt.updateVariants(targetEntity, rotationVariant, defaultBuildingVariant); - - // Now add it again - this.addEntityToPaths(targetEntity); - - // Sanity - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_verifyBeltPaths(); - } - - // Make sure the chunks know about the update - this.root.signals.entityChanged.dispatch(targetEntity); - } - } - } - } - - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_verifyBeltPaths(); - } - } - - /** - * Called when an entity got destroyed - * @param {Entity} entity - */ - onEntityDestroyed(entity) { - if (!this.root.gameInitialized) { - return; - } - - if (!entity.components.Belt) { - return; - } - - const assignedPath = entity.components.Belt.assignedPath; - assert(assignedPath, "Entity has no belt path assigned"); - this.deleteEntityFromPath(assignedPath, entity); - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_verifyBeltPaths(); - } - } - - /** - * Attempts to delete the belt from its current path - * @param {BeltPath} path - * @param {Entity} entity - */ - deleteEntityFromPath(path, entity) { - if (path.entityPath.length === 1) { - // This is a single entity path, easy to do, simply erase whole path - fastArrayDeleteValue(this.beltPaths, path); - return; - } - - // Notice: Since there might be circular references, it is important to check - // which role the entity has - if (path.isStartEntity(entity)) { - // We tried to delete the start - path.deleteEntityOnStart(entity); - } else if (path.isEndEntity(entity)) { - // We tried to delete the end - path.deleteEntityOnEnd(entity); - } else { - // We tried to delete something inbetween - const newPath = path.deleteEntityOnPathSplitIntoTwo(entity); - this.beltPaths.push(newPath); - } - - // Sanity - entity.components.Belt.assignedPath = null; - } - - /** - * Adds the given entity to the appropriate paths - * @param {Entity} entity - */ - addEntityToPaths(entity) { - const fromEntity = this.findSupplyingEntity(entity); - const toEntity = this.findFollowUpEntity(entity); - - // Check if we can add the entity to the previous path - if (fromEntity) { - const fromPath = fromEntity.components.Belt.assignedPath; - fromPath.extendOnEnd(entity); - - // Check if we now can extend the current path by the next path - if (toEntity) { - const toPath = toEntity.components.Belt.assignedPath; - - if (fromPath === toPath) { - // This is a circular dependency -> Ignore - } else { - fromPath.extendByPath(toPath); - - // Delete now obsolete path - fastArrayDeleteValue(this.beltPaths, toPath); - } - } - } else { - if (toEntity) { - // Prepend it to the other path - const toPath = toEntity.components.Belt.assignedPath; - toPath.extendOnBeginning(entity); - } else { - // This is an empty belt path - const path = new BeltPath(this.root, [entity]); - this.beltPaths.push(path); - } - } - } - - /** - * Called when an entity got added - * @param {Entity} entity - */ - onEntityAdded(entity) { - if (!this.root.gameInitialized) { - return; - } - - if (!entity.components.Belt) { - return; - } - - this.addEntityToPaths(entity); - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_verifyBeltPaths(); - } - } - - /** - * Draws all belt paths - * @param {DrawParameters} parameters - * @param {enumLayer} layer - */ - drawLayerBeltItems(parameters, layer) { - for (let i = 0; i < this.beltPaths.length; ++i) { - const path = this.beltPaths[i]; - if (path.layer === layer) { - path.draw(parameters); - } - } - } - - /** - * Verifies all belt paths - */ - debug_verifyBeltPaths() { - for (let i = 0; i < this.beltPaths.length; ++i) { - this.beltPaths[i].debug_checkIntegrity("general-verify"); - } - - const belts = this.root.entityMgr.getAllWithComponent(BeltComponent); - for (let i = 0; i < belts.length; ++i) { - const path = belts[i].components.Belt.assignedPath; - if (!path) { - throw new Error("Belt has no path: " + belts[i].uid); - } - if (this.beltPaths.indexOf(path) < 0) { - throw new Error("Path of entity not contained: " + belts[i].uid); - } - } - } - - /** - * Finds the follow up entity for a given belt. Used for building the dependencies - * @param {Entity} entity - * @returns {Entity|null} - */ - findFollowUpEntity(entity) { - const staticComp = entity.components.StaticMapEntity; - const beltComp = entity.components.Belt; - - const followUpDirection = staticComp.localDirectionToWorld(beltComp.direction); - const followUpVector = enumDirectionToVector[followUpDirection]; - - const followUpTile = staticComp.origin.add(followUpVector); - const followUpEntity = this.root.map.getLayerContentXY(followUpTile.x, followUpTile.y, entity.layer); - - // Check if theres a belt at the tile we point to - if (followUpEntity) { - 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; - } - } - } - } - } - - return null; - } - - /** - * Finds the supplying belt for a given belt. Used for building the dependencies - * @param {Entity} entity - * @returns {Entity|null} - */ - findSupplyingEntity(entity) { - const staticComp = entity.components.StaticMapEntity; - - const supplyDirection = staticComp.localDirectionToWorld(enumDirection.bottom); - const supplyVector = enumDirectionToVector[supplyDirection]; - - const supplyTile = staticComp.origin.add(supplyVector); - const supplyEntity = this.root.map.getLayerContentXY(supplyTile.x, supplyTile.y, entity.layer); - - // Check if theres a belt at the tile we point to - if (supplyEntity) { - const supplyBeltComp = supplyEntity.components.Belt; - if (supplyBeltComp) { - const supplyStatic = supplyEntity.components.StaticMapEntity; - const supplyEjector = supplyEntity.components.ItemEjector; - - // 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; - } - } - } - } - - return null; - } - - /** - * Recomputes the belt path network. Only required for old savegames - */ - recomputeAllBeltPaths() { - logger.warn("Recomputing all belt paths"); - const visitedUids = new Set(); - - const result = []; - - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - if (visitedUids.has(entity.uid)) { - continue; - } - - // Mark entity as visited - visitedUids.add(entity.uid); - - // Compute path, start with entity and find precedors / successors - const path = [entity]; - - // Prevent infinite loops - let maxIter = 99999; - - // Find precedors - let prevEntity = this.findSupplyingEntity(entity); - while (prevEntity && --maxIter > 0) { - if (visitedUids.has(prevEntity.uid)) { - break; - } - path.unshift(prevEntity); - visitedUids.add(prevEntity.uid); - prevEntity = this.findSupplyingEntity(prevEntity); - } - - // Find succedors - let nextEntity = this.findFollowUpEntity(entity); - while (nextEntity && --maxIter > 0) { - if (visitedUids.has(nextEntity.uid)) { - break; - } - - path.push(nextEntity); - visitedUids.add(nextEntity.uid); - nextEntity = this.findFollowUpEntity(nextEntity); - } - - assert(maxIter > 1, "Ran out of iterations"); - result.push(new BeltPath(this.root, path)); - } - - logger.log("Found", this.beltPaths.length, "belt paths"); - this.beltPaths = result; - } - - /** - * Updates all belts - */ - update() { - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_verifyBeltPaths(); - } - - for (let i = 0; i < this.beltPaths.length; ++i) { - this.beltPaths[i].update(); - } - - if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { - this.debug_verifyBeltPaths(); - } - } - - /** - * Draws a given chunk - * @param {DrawParameters} parameters - * @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); - - // 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] - ); - 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.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 - ); - } - } - } - } - - /** - * Draws the belt path debug overlays - * @param {DrawParameters} parameters - */ - drawBeltPathDebug(parameters) { - for (let i = 0; i < this.beltPaths.length; ++i) { - this.beltPaths[i].drawDebug(parameters); - } - } -} +import { globalConfig } from "../../core/config"; +import { DrawParameters } from "../../core/draw_parameters"; +import { gMetaBuildingRegistry } from "../../core/global_registries"; +import { Loader } from "../../core/loader"; +import { createLogger } from "../../core/logging"; +import { AtlasSprite } from "../../core/sprites"; +import { fastArrayDeleteValue } from "../../core/utils"; +import { enumDirection, enumDirectionToVector, enumInvertedDirections, Vector } from "../../core/vector"; +import { BeltPath } from "../belt_path"; +import { arrayBeltVariantToRotation, MetaBeltBuilding } from "../buildings/belt"; +import { getCodeFromBuildingData } from "../building_codes"; +import { BeltComponent } from "../components/belt"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { MapChunkView } from "../map_chunk_view"; +import { defaultBuildingVariant } from "../meta_building"; + +export const BELT_ANIM_COUNT = 14; + +const logger = createLogger("belt"); + +/** + * Manages all belts + */ +export class BeltSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [BeltComponent]); + /** + * @type {Object.>} + */ + this.beltSprites = { + [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"), + }; + + /** + * @type {Object.>} + */ + this.beltAnimations = { + [enumDirection.top]: [], + [enumDirection.left]: [], + [enumDirection.right]: [], + }; + + for (let i = 0; i < BELT_ANIM_COUNT; ++i) { + this.beltAnimations[enumDirection.top].push( + Loader.getSprite("sprites/belt/built/forward_" + i + ".png") + ); + this.beltAnimations[enumDirection.left].push( + Loader.getSprite("sprites/belt/built/left_" + i + ".png") + ); + this.beltAnimations[enumDirection.right].push( + Loader.getSprite("sprites/belt/built/right_" + i + ".png") + ); + } + + this.root.signals.entityDestroyed.add(this.onEntityDestroyed, this); + this.root.signals.entityDestroyed.add(this.updateSurroundingBeltPlacement, this); + + // Notice: These must come *after* the entity destroyed signals + this.root.signals.entityAdded.add(this.onEntityAdded, this); + this.root.signals.entityAdded.add(this.updateSurroundingBeltPlacement, this); + + /** @type {Array} */ + this.beltPaths = []; + } + + /** + * Serializes all belt paths + * @returns {Array} + */ + serializePaths() { + let data = []; + for (let i = 0; i < this.beltPaths.length; ++i) { + data.push(this.beltPaths[i].serialize()); + } + return data; + } + + /** + * Deserializes all belt paths + * @param {Array} data + */ + deserializePaths(data) { + if (!Array.isArray(data)) { + return "Belt paths are not an array: " + typeof data; + } + + for (let i = 0; i < data.length; ++i) { + const path = BeltPath.fromSerialized(this.root, data[i]); + // If path is a string, that means its an error + if (!(path instanceof BeltPath)) { + return "Failed to create path from belt data: " + path; + } + this.beltPaths.push(path); + } + + if (this.beltPaths.length === 0) { + // Old savegames might not have paths yet + logger.warn("Recomputing belt paths (most likely the savegame is old or empty)"); + this.recomputeAllBeltPaths(); + } else { + logger.warn("Restored", this.beltPaths.length, "belt paths"); + } + + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_verifyBeltPaths(); + } + } + + /** + * Updates the belt placement after an entity has been added / deleted + * @param {Entity} entity + */ + updateSurroundingBeltPlacement(entity) { + if (!this.root.gameInitialized) { + return; + } + + const staticComp = entity.components.StaticMapEntity; + if (!staticComp) { + return; + } + + const metaBelt = gMetaBuildingRegistry.findByClass(MetaBeltBuilding); + // Compute affected area + 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)) { + // Make sure we don't update the original entity + continue; + } + + const targetEntities = this.root.map.getLayersContentsMultipleXY(x, y); + for (let i = 0; i < targetEntities.length; ++i) { + const targetEntity = targetEntities[i]; + + const targetBeltComp = targetEntity.components.Belt; + const targetStaticComp = targetEntity.components.StaticMapEntity; + + if (!targetBeltComp) { + // Not a belt + continue; + } + + const { + rotation, + rotationVariant, + } = metaBelt.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 newDirection = arrayBeltVariantToRotation[rotationVariant]; + + if (targetStaticComp.rotation !== rotation || newDirection !== targetBeltComp.direction) { + const originalPath = targetBeltComp.assignedPath; + + // Ok, first remove it from its current path + this.deleteEntityFromPath(targetBeltComp.assignedPath, targetEntity); + + // Change stuff + targetStaticComp.rotation = rotation; + metaBelt.updateVariants(targetEntity, rotationVariant, defaultBuildingVariant); + + // Update code as well + targetStaticComp.code = getCodeFromBuildingData( + metaBelt, + defaultBuildingVariant, + rotationVariant + ); + + // Update the original path since it might have picked up the entit1y + originalPath.onPathChanged(); + + // Now add it again + this.addEntityToPaths(targetEntity); + + // Sanity + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_verifyBeltPaths(); + } + + // 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(); + } + } + + /** + * Called when an entity got destroyed + * @param {Entity} entity + */ + onEntityDestroyed(entity) { + if (!this.root.gameInitialized) { + return; + } + + if (!entity.components.Belt) { + return; + } + + const assignedPath = entity.components.Belt.assignedPath; + assert(assignedPath, "Entity has no belt path assigned"); + this.deleteEntityFromPath(assignedPath, entity); + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_verifyBeltPaths(); + } + } + + /** + * Attempts to delete the belt from its current path + * @param {BeltPath} path + * @param {Entity} entity + */ + deleteEntityFromPath(path, entity) { + if (path.entityPath.length === 1) { + // This is a single entity path, easy to do, simply erase whole path + fastArrayDeleteValue(this.beltPaths, path); + return; + } + + // Notice: Since there might be circular references, it is important to check + // which role the entity has + if (path.isStartEntity(entity)) { + // We tried to delete the start + path.deleteEntityOnStart(entity); + } else if (path.isEndEntity(entity)) { + // We tried to delete the end + path.deleteEntityOnEnd(entity); + } else { + // We tried to delete something inbetween + const newPath = path.deleteEntityOnPathSplitIntoTwo(entity); + this.beltPaths.push(newPath); + } + + // Sanity + entity.components.Belt.assignedPath = null; + } + + /** + * Adds the given entity to the appropriate paths + * @param {Entity} entity + */ + addEntityToPaths(entity) { + const fromEntity = this.findSupplyingEntity(entity); + const toEntity = this.findFollowUpEntity(entity); + + // Check if we can add the entity to the previous path + if (fromEntity) { + const fromPath = fromEntity.components.Belt.assignedPath; + fromPath.extendOnEnd(entity); + + // Check if we now can extend the current path by the next path + if (toEntity) { + const toPath = toEntity.components.Belt.assignedPath; + + if (fromPath === toPath) { + // This is a circular dependency -> Ignore + } else { + fromPath.extendByPath(toPath); + + // Delete now obsolete path + fastArrayDeleteValue(this.beltPaths, toPath); + } + } + } else { + if (toEntity) { + // Prepend it to the other path + const toPath = toEntity.components.Belt.assignedPath; + toPath.extendOnBeginning(entity); + } else { + // This is an empty belt path + const path = new BeltPath(this.root, [entity]); + this.beltPaths.push(path); + } + } + } + + /** + * Called when an entity got added + * @param {Entity} entity + */ + onEntityAdded(entity) { + if (!this.root.gameInitialized) { + return; + } + + if (!entity.components.Belt) { + return; + } + + this.addEntityToPaths(entity); + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_verifyBeltPaths(); + } + } + + /** + * Draws all belt paths + * @param {DrawParameters} parameters + */ + drawBeltItems(parameters) { + for (let i = 0; i < this.beltPaths.length; ++i) { + this.beltPaths[i].draw(parameters); + } + } + + /** + * Verifies all belt paths + */ + debug_verifyBeltPaths() { + for (let i = 0; i < this.beltPaths.length; ++i) { + this.beltPaths[i].debug_checkIntegrity("general-verify"); + } + + const belts = this.root.entityMgr.getAllWithComponent(BeltComponent); + for (let i = 0; i < belts.length; ++i) { + const path = belts[i].components.Belt.assignedPath; + if (!path) { + throw new Error("Belt has no path: " + belts[i].uid); + } + if (this.beltPaths.indexOf(path) < 0) { + throw new Error("Path of entity not contained: " + belts[i].uid); + } + } + } + + /** + * Finds the follow up entity for a given belt. Used for building the dependencies + * @param {Entity} entity + * @returns {Entity|null} + */ + findFollowUpEntity(entity) { + const staticComp = entity.components.StaticMapEntity; + const beltComp = entity.components.Belt; + + const followUpDirection = staticComp.localDirectionToWorld(beltComp.direction); + const followUpVector = enumDirectionToVector[followUpDirection]; + + const followUpTile = staticComp.origin.add(followUpVector); + const followUpEntity = this.root.map.getLayerContentXY(followUpTile.x, followUpTile.y, entity.layer); + + // Check if there's a belt at the tile we point to + if (followUpEntity) { + const followUpBeltComp = followUpEntity.components.Belt; + if (followUpBeltComp) { + const followUpStatic = followUpEntity.components.StaticMapEntity; + + const acceptedDirection = followUpStatic.localDirectionToWorld(enumDirection.top); + if (acceptedDirection === followUpDirection) { + return followUpEntity; + } + } + } + + return null; + } + + /** + * Finds the supplying belt for a given belt. Used for building the dependencies + * @param {Entity} entity + * @returns {Entity|null} + */ + findSupplyingEntity(entity) { + const staticComp = entity.components.StaticMapEntity; + + const supplyDirection = staticComp.localDirectionToWorld(enumDirection.bottom); + const supplyVector = enumDirectionToVector[supplyDirection]; + + const supplyTile = staticComp.origin.add(supplyVector); + const supplyEntity = this.root.map.getLayerContentXY(supplyTile.x, supplyTile.y, entity.layer); + + // Check if there's a belt at the tile we point to + if (supplyEntity) { + const supplyBeltComp = supplyEntity.components.Belt; + if (supplyBeltComp) { + const supplyStatic = supplyEntity.components.StaticMapEntity; + const otherDirection = supplyStatic.localDirectionToWorld( + enumInvertedDirections[supplyBeltComp.direction] + ); + + if (otherDirection === supplyDirection) { + return supplyEntity; + } + } + } + + return null; + } + + /** + * Recomputes the belt path network. Only required for old savegames + */ + recomputeAllBeltPaths() { + logger.warn("Recomputing all belt paths"); + const visitedUids = new Set(); + + const result = []; + + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + if (visitedUids.has(entity.uid)) { + continue; + } + + // Mark entity as visited + visitedUids.add(entity.uid); + + // Compute path, start with entity and find precedors / successors + const path = [entity]; + + // Prevent infinite loops + let maxIter = 99999; + + // Find precedors + let prevEntity = this.findSupplyingEntity(entity); + while (prevEntity && --maxIter > 0) { + if (visitedUids.has(prevEntity.uid)) { + break; + } + path.unshift(prevEntity); + visitedUids.add(prevEntity.uid); + prevEntity = this.findSupplyingEntity(prevEntity); + } + + // Find succedors + let nextEntity = this.findFollowUpEntity(entity); + while (nextEntity && --maxIter > 0) { + if (visitedUids.has(nextEntity.uid)) { + break; + } + + path.push(nextEntity); + visitedUids.add(nextEntity.uid); + nextEntity = this.findFollowUpEntity(nextEntity); + } + + assert(maxIter > 1, "Ran out of iterations"); + result.push(new BeltPath(this.root, path)); + } + + logger.log("Found", this.beltPaths.length, "belt paths"); + this.beltPaths = result; + } + + /** + * Updates all belts + */ + update() { + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_verifyBeltPaths(); + } + + for (let i = 0; i < this.beltPaths.length; ++i) { + this.beltPaths[i].update(); + } + + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { + this.debug_verifyBeltPaths(); + } + } + + /** + * 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); + + // 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.itemSpacingOnBelts + ); + const contents = chunk.containedEntitiesByLayer.regular; + + if (this.root.app.settings.getAllSettings().simplifiedBelts) { + // POTATO Mode: Only show items when belt is hovered + let hoveredBeltPath = null; + const mousePos = this.root.app.mousePosition; + if (mousePos && this.root.currentLayer === "regular") { + const tile = this.root.camera.screenToWorld(mousePos).toTileSpace(); + const contents = this.root.map.getLayerContentXY(tile.x, tile.y, "regular"); + if (contents && contents.components.Belt) { + hoveredBeltPath = contents.components.Belt.assignedPath; + } + } + + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + if (entity.components.Belt) { + const direction = entity.components.Belt.direction; + let sprite = this.beltAnimations[direction][0]; + + if (entity.components.Belt.assignedPath === hoveredBeltPath) { + sprite = this.beltAnimations[direction][animationIndex % BELT_ANIM_COUNT]; + } + + // Culling happens within the static map entity component + entity.components.StaticMapEntity.drawSpriteOnBoundsClipped(parameters, sprite, 0); + } + } + } else { + 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]; + + // Culling happens within the static map entity component + entity.components.StaticMapEntity.drawSpriteOnBoundsClipped(parameters, sprite, 0); + } + } + } + } + + /** + * Draws the belt path debug overlays + * @param {DrawParameters} parameters + */ + drawBeltPathDebug(parameters) { + for (let i = 0; i < this.beltPaths.length; ++i) { + this.beltPaths[i].drawDebug(parameters); + } + } +} diff --git a/src/js/game/systems/belt_reader.js b/src/js/game/systems/belt_reader.js new file mode 100644 index 00000000..fbd00b6c --- /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 = Math.min(globalConfig.beltSpeedItemsPerSecond * 23.9, 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..c5c69d26 --- /dev/null +++ b/src/js/game/systems/belt_underlays.js @@ -0,0 +1,300 @@ +import { globalConfig } from "../../core/config"; +import { DrawParameters } from "../../core/draw_parameters"; +import { Loader } from "../../core/loader"; +import { Rectangle } from "../../core/rectangle"; +import { FULL_CLIP_RECT } from "../../core/sprites"; +import { StaleAreaDetector } from "../../core/stale_area_detector"; +import { + enumDirection, + enumDirectionToAngle, + enumDirectionToVector, + enumInvertedDirections, + Vector, +} from "../../core/vector"; +import { BeltComponent } from "../components/belt"; +import { BeltUnderlaysComponent, enumClippedBeltUnderlayType } from "../components/belt_underlays"; +import { ItemAcceptorComponent } from "../components/item_acceptor"; +import { ItemEjectorComponent } from "../components/item_ejector"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { MapChunkView } from "../map_chunk_view"; +import { BELT_ANIM_COUNT } from "./belt"; + +/** + * Mapping from underlay type to clip rect + * @type {Object} + */ +const enumUnderlayTypeToClipRect = { + [enumClippedBeltUnderlayType.none]: null, + [enumClippedBeltUnderlayType.full]: FULL_CLIP_RECT, + [enumClippedBeltUnderlayType.topOnly]: new Rectangle(0, 0, 1, 0.5), + [enumClippedBeltUnderlayType.bottomOnly]: new Rectangle(0, 0.5, 1, 0.5), +}; + +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")); + } + + // Automatically recompute areas + this.staleArea = new StaleAreaDetector({ + root, + name: "belt-underlay", + recomputeMethod: this.recomputeStaleArea.bind(this), + }); + + this.staleArea.recomputeOnComponentsChanged( + [BeltUnderlaysComponent, BeltComponent, ItemAcceptorComponent, ItemEjectorComponent], + 1 + ); + } + + update() { + this.staleArea.update(); + } + + /** + * Called when an area changed - Resets all caches in the given area + * @param {Rectangle} area + */ + recomputeStaleArea(area) { + for (let x = 0; x < area.w; ++x) { + for (let y = 0; y < area.h; ++y) { + const tileX = area.x + x; + const tileY = area.y + y; + const entity = this.root.map.getLayerContentXY(tileX, tileY, "regular"); + if (entity) { + const underlayComp = entity.components.BeltUnderlays; + if (underlayComp) { + for (let i = 0; i < underlayComp.underlays.length; ++i) { + underlayComp.underlays[i].cachedType = null; + } + } + } + } + } + } + + /** + * Checks if a given tile is connected and has an acceptor + * @param {Vector} tile + * @param {enumDirection} fromDirection + * @returns {boolean} + */ + checkIsAcceptorConnected(tile, fromDirection) { + const contents = this.root.map.getLayerContentXY(tile.x, tile.y, "regular"); + if (!contents) { + return false; + } + + const staticComp = contents.components.StaticMapEntity; + + // Check if its a belt, since then its simple + const beltComp = contents.components.Belt; + if (beltComp) { + return staticComp.localDirectionToWorld(enumDirection.bottom) === fromDirection; + } + + // Check if there's an item acceptor + const acceptorComp = contents.components.ItemAcceptor; + if (acceptorComp) { + // Check each slot to see if its connected + for (let i = 0; i < acceptorComp.slots.length; ++i) { + const slot = acceptorComp.slots[i]; + const slotTile = staticComp.localTileToWorld(slot.pos); + + // Step 1: Check if the tile matches + if (!slotTile.equals(tile)) { + continue; + } + + // Step 2: Check if any of the directions matches + for (let j = 0; j < slot.directions.length; ++j) { + const slotDirection = staticComp.localDirectionToWorld(slot.directions[j]); + if (slotDirection === fromDirection) { + return true; + } + } + } + } + + return false; + } + + /** + * Checks if a given tile is connected and has an ejector + * @param {Vector} tile + * @param {enumDirection} toDirection + * @returns {boolean} + */ + checkIsEjectorConnected(tile, toDirection) { + const contents = this.root.map.getLayerContentXY(tile.x, tile.y, "regular"); + if (!contents) { + return false; + } + + const staticComp = contents.components.StaticMapEntity; + + // Check if its a belt, since then its simple + const beltComp = contents.components.Belt; + if (beltComp) { + return staticComp.localDirectionToWorld(beltComp.direction) === toDirection; + } + + // Check for an ejector + const ejectorComp = contents.components.ItemEjector; + if (ejectorComp) { + // Check each slot to see if its connected + for (let i = 0; i < ejectorComp.slots.length; ++i) { + const slot = ejectorComp.slots[i]; + const slotTile = staticComp.localTileToWorld(slot.pos); + + // Step 1: Check if the tile matches + if (!slotTile.equals(tile)) { + continue; + } + + // Step 2: Check if the direction matches + const slotDirection = staticComp.localDirectionToWorld(slot.direction); + if (slotDirection === toDirection) { + return true; + } + } + } + + return false; + } + + /** + * Computes the flag for a given tile + * @param {Entity} entity + * @param {import("../components/belt_underlays").BeltUnderlayTile} underlayTile + * @returns {enumClippedBeltUnderlayType} The type of the underlay + */ + computeBeltUnderlayType(entity, underlayTile) { + if (underlayTile.cachedType) { + return underlayTile.cachedType; + } + + const staticComp = entity.components.StaticMapEntity; + + const transformedPos = staticComp.localTileToWorld(underlayTile.pos); + const destX = transformedPos.x * globalConfig.tileSize; + const destY = transformedPos.y * globalConfig.tileSize; + + // Extract direction and angle + const worldDirection = staticComp.localDirectionToWorld(underlayTile.direction); + const worldDirectionVector = enumDirectionToVector[worldDirection]; + + // Figure out if there is anything connected at the top + const connectedTop = this.checkIsAcceptorConnected( + transformedPos.add(worldDirectionVector), + enumInvertedDirections[worldDirection] + ); + + // Figure out if there is anything connected at the bottom + const connectedBottom = this.checkIsEjectorConnected( + transformedPos.sub(worldDirectionVector), + worldDirection + ); + + let flag = enumClippedBeltUnderlayType.none; + + if (connectedTop && connectedBottom) { + flag = enumClippedBeltUnderlayType.full; + } else if (connectedTop) { + flag = enumClippedBeltUnderlayType.topOnly; + } else if (connectedBottom) { + flag = enumClippedBeltUnderlayType.bottomOnly; + } + + return (underlayTile.cachedType = flag); + } + + /** + * 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) { + // Extract underlay parameters + const { pos, direction } = underlays[i]; + const transformedPos = staticComp.localTileToWorld(pos); + const destX = transformedPos.x * globalConfig.tileSize; + const destY = transformedPos.y * globalConfig.tileSize; + + // Culling, Part 1: Check if the chunk contains the tile + if (!chunk.tileSpaceRectangle.containsPoint(transformedPos.x, transformedPos.y)) { + continue; + } + + // Culling, Part 2: Check if the overlay is visible + if ( + !parameters.visibleRect.containsRect4Params( + destX, + destY, + globalConfig.tileSize, + globalConfig.tileSize + ) + ) { + continue; + } + + // Extract direction and angle + const worldDirection = staticComp.localDirectionToWorld(direction); + const angle = enumDirectionToAngle[worldDirection]; + + const underlayType = this.computeBeltUnderlayType(entity, underlays[i]); + const clipRect = enumUnderlayTypeToClipRect[underlayType]; + if (!clipRect) { + // Empty + continue; + } + + // Actually draw the sprite + const x = destX + globalConfig.halfTileSize; + const y = destY + globalConfig.halfTileSize; + const angleRadians = Math.radians(angle); + + // SYNC with systems/belt.js:drawSingleEntity! + const animationIndex = Math.floor( + ((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) * + globalConfig.itemSpacingOnBelts + ); + parameters.context.translate(x, y); + parameters.context.rotate(angleRadians); + this.underlayBeltSprites[ + animationIndex % this.underlayBeltSprites.length + ].drawCachedWithClipRect( + parameters, + -globalConfig.halfTileSize, + -globalConfig.halfTileSize, + globalConfig.tileSize, + globalConfig.tileSize, + clipRect + ); + parameters.context.rotate(-angleRadians); + parameters.context.translate(-x, -y); + } + } + } +} diff --git a/src/js/game/systems/constant_signal.js b/src/js/game/systems/constant_signal.js new file mode 100644 index 00000000..aaf31a19 --- /dev/null +++ b/src/js/game/systems/constant_signal.js @@ -0,0 +1,166 @@ +import trim from "trim"; +import { THIRDPARTY_URLS } from "../../core/config"; +import { DialogWithForm } from "../../core/modal_dialog_elements"; +import { FormElementInput, FormElementItemChooser } from "../../core/modal_dialog_forms"; +import { fillInLinkIntoTranslation } from "../../core/utils"; +import { T } from "../../translations"; +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: fillInLinkIntoTranslation(T.dialogs.editSignal.descShortKey, THIRDPARTY_URLS.shapeViewer), + placeholder: "", + defaultValue: "", + validator: val => this.parseSignalCode(val), + }); + + const itemInput = new FormElementItemChooser({ + id: "signalItem", + label: null, + items: [ + BOOL_FALSE_SINGLETON, + BOOL_TRUE_SINGLETON, + ...Object.values(COLOR_ITEM_SINGLETONS), + this.root.shapeDefinitionMgr.getShapeItemFromDefinition( + this.root.hubGoals.currentGoal.definition + ), + this.root.shapeDefinitionMgr.getShapeItemFromShortKey( + this.root.gameMode.getBlueprintShapeKey() + ), + ...this.root.hud.parts.pinnedShapes.pinnedShapes.map(key => + this.root.shapeDefinitionMgr.getShapeItemFromShortKey(key) + ), + ], + }); + + const dialog = new DialogWithForm({ + app: this.root.app, + title: T.dialogs.editSignal.title, + desc: T.dialogs.editSignal.descItems, + formElements: [itemInput, signalValueInput], + buttons: ["cancel:bad:escape", "ok:good:enter"], + closeButton: false, + }); + this.root.hud.parts.dialogs.internalShowDialog(dialog); + + // When confirmed, set the signal + const closeHandler = () => { + 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; + } + + if (itemInput.chosenItem) { + console.log(itemInput.chosenItem); + constantComp.signal = itemInput.chosenItem; + } else { + constantComp.signal = this.parseSignalCode(signalValueInput.getValue()); + } + }; + + dialog.buttonSignals.ok.add(closeHandler); + dialog.valueChosen.add(closeHandler); + + // 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..f11091b9 --- /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.hasValue()) { + 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/filter.js b/src/js/game/systems/filter.js new file mode 100644 index 00000000..a6442b41 --- /dev/null +++ b/src/js/game/systems/filter.js @@ -0,0 +1,85 @@ +import { globalConfig } from "../../core/config"; +import { BaseItem } from "../base_item"; +import { FilterComponent } from "../components/filter"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { BOOL_TRUE_SINGLETON } from "../items/boolean_item"; + +const MAX_ITEMS_IN_QUEUE = 2; + +export class FilterSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [FilterComponent]); + } + + update() { + const progress = + this.root.dynamicTickrate.deltaSeconds * + this.root.hubGoals.getBeltBaseSpeed() * + globalConfig.itemSpacingOnBelts; + + const requiredProgress = 1 - progress; + + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + const filterComp = entity.components.Filter; + const ejectorComp = entity.components.ItemEjector; + + // Process payloads + const slotsAndLists = [filterComp.pendingItemsToLeaveThrough, filterComp.pendingItemsToReject]; + for (let slotIndex = 0; slotIndex < slotsAndLists.length; ++slotIndex) { + const pendingItems = slotsAndLists[slotIndex]; + + for (let j = 0; j < pendingItems.length; ++j) { + const nextItem = pendingItems[j]; + // Advance next item + nextItem.progress = Math.min(requiredProgress, nextItem.progress + progress); + // Check if it's ready to eject + if (nextItem.progress >= requiredProgress - 1e-5) { + if (ejectorComp.tryEject(slotIndex, nextItem.item)) { + pendingItems.shift(); + } + } + } + } + } + } + + /** + * + * @param {Entity} entity + * @param {number} slot + * @param {BaseItem} item + */ + tryAcceptItem(entity, slot, item) { + const network = entity.components.WiredPins.slots[0].linkedNetwork; + if (!network || !network.hasValue()) { + // Filter is not connected + return false; + } + + const value = network.currentValue; + const filterComp = entity.components.Filter; + assert(filterComp, "entity is no filter"); + + // Figure out which list we have to check + let listToCheck; + if (value.equals(BOOL_TRUE_SINGLETON) || value.equals(item)) { + listToCheck = filterComp.pendingItemsToLeaveThrough; + } else { + listToCheck = filterComp.pendingItemsToReject; + } + + if (listToCheck.length >= MAX_ITEMS_IN_QUEUE) { + // Busy + return false; + } + + // Actually accept item + listToCheck.push({ + item, + progress: 0.0, + }); + return true; + } +} diff --git a/src/js/game/systems/hub.js b/src/js/game/systems/hub.js index f1d4ee28..2002b66e 100644 --- a/src/js/game/systems/hub.js +++ b/src/js/game/systems/hub.js @@ -1,122 +1,196 @@ -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 { T } from "../../translations"; - -export class HubSystem extends GameSystemWithFilter { - constructor(root) { - super(root, [HubComponent]); - - this.hubSprite = Loader.getSprite("sprites/buildings/hub.png"); - } - - draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this)); - } - - update() { - for (let i = 0; i < this.allEntities.length; ++i) { - 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 = []; - } - } - - /** - * @param {DrawParameters} parameters - * @param {Entity} entity - */ - drawEntity(parameters, entity) { - const context = parameters.context; - const staticComp = entity.components.StaticMapEntity; - - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } - - const pos = staticComp.getTileSpaceBounds().getCenter().toWorldSpace(); - - // Background - staticComp.drawSpriteOnFullEntityBounds(parameters, this.hubSprite, 2.2); - - const definition = this.root.hubGoals.currentGoal.definition; - - definition.draw(pos.x - 25, pos.y - 10, parameters, 40); - - const goals = this.root.hubGoals.currentGoal; - - const textOffsetX = 2; - const textOffsetY = -6; - - // Deliver count - const delivered = this.root.hubGoals.getCurrentGoalDelivered(); - - if (delivered > 9999) { - context.font = "bold 16px GameFont"; - } else if (delivered > 999) { - context.font = "bold 20px GameFont"; - } else { - context.font = "bold 25px GameFont"; - } - context.fillStyle = "#64666e"; - context.textAlign = "left"; - context.fillText("" + formatBigNumber(delivered), pos.x + textOffsetX, pos.y + textOffsetY); - - // Required - context.font = "13px GameFont"; - context.fillStyle = "#a4a6b0"; - context.fillText( - "/ " + formatBigNumber(goals.required), - pos.x + textOffsetX, - pos.y + textOffsetY + 13 - ); - - // Reward - const rewardText = T.storyRewards[goals.reward].title.toUpperCase(); - if (rewardText.length > 12) { - context.font = "bold 9px GameFont"; - } else { - context.font = "bold 11px GameFont"; - } - context.fillStyle = "#fd0752"; - context.textAlign = "center"; - - context.fillText(rewardText, pos.x, pos.y + 46); - - // Level - context.font = "bold 11px GameFont"; - context.fillStyle = "#fff"; - context.fillText("" + this.root.hubGoals.level, pos.x - 42, pos.y - 36); - - // Texts - context.textAlign = "center"; - context.fillStyle = "#fff"; - context.font = "bold 7px GameFont"; - context.fillText(T.buildings.hub.levelShortcut, pos.x - 42, pos.y - 47); - - context.fillStyle = "#64666e"; - context.font = "bold 11px GameFont"; - context.fillText(T.buildings.hub.deliver.toUpperCase(), pos.x, pos.y - 40); - - const unlockText = T.buildings.hub.toUnlock.toUpperCase(); - if (unlockText.length > 15) { - context.font = "bold 8px GameFont"; - } else { - context.font = "bold 11px GameFont"; - } - context.fillText(T.buildings.hub.toUnlock.toUpperCase(), pos.x, pos.y + 30); - - context.textAlign = "left"; - } -} +import { globalConfig } from "../../core/config"; +import { smoothenDpi } from "../../core/dpi_manager"; +import { DrawParameters } from "../../core/draw_parameters"; +import { drawSpriteClipped } from "../../core/draw_utils"; +import { Loader } from "../../core/loader"; +import { Rectangle } from "../../core/rectangle"; +import { ORIGINAL_SPRITE_SCALE } from "../../core/sprites"; +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"; + +const HUB_SIZE_TILES = 4; +const HUB_SIZE_PIXELS = HUB_SIZE_TILES * globalConfig.tileSize; + +export class HubSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [HubComponent]); + + this.hubSprite = Loader.getSprite("sprites/buildings/hub.png"); + } + + /** + * @param {DrawParameters} parameters + */ + draw(parameters) { + 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 pinsComp = entity.components.WiredPins; + pinsComp.slots[0].value = this.root.shapeDefinitionMgr.getShapeItemFromDefinition( + this.root.hubGoals.currentGoal.definition + ); + } + } + /** + * + * @param {HTMLCanvasElement} canvas + * @param {CanvasRenderingContext2D} context + * @param {number} w + * @param {number} h + * @param {number} dpi + */ + redrawHubBaseTexture(canvas, context, w, h, dpi) { + // This method is quite ugly, please ignore it! + + context.scale(dpi, dpi); + + const parameters = new DrawParameters({ + context, + visibleRect: new Rectangle(0, 0, w, h), + desiredAtlasScale: ORIGINAL_SPRITE_SCALE, + zoomLevel: dpi * 0.75, + root: this.root, + }); + + context.clearRect(0, 0, w, h); + + this.hubSprite.draw(context, 0, 0, w, h); + + if (this.root.hubGoals.isEndOfDemoReached()) { + // End of demo + context.font = "bold 12px GameFont"; + context.fillStyle = "#fd0752"; + context.textAlign = "center"; + context.fillText(T.buildings.hub.endOfDemo.toUpperCase(), w / 2, h / 2 + 6); + context.textAlign = "left"; + + return; + } + + const definition = this.root.hubGoals.currentGoal.definition; + definition.drawCentered(45, 58, parameters, 36); + + const goals = this.root.hubGoals.currentGoal; + + const textOffsetX = 70; + const textOffsetY = 61; + + if (goals.throughputOnly) { + // Throughput + const deliveredText = T.ingame.statistics.shapesDisplayUnits.second.replace( + "", + formatBigNumber(goals.required) + ); + + context.font = "bold 12px GameFont"; + context.fillStyle = "#64666e"; + context.textAlign = "left"; + context.fillText(deliveredText, textOffsetX, textOffsetY); + } else { + // Deliver count + const delivered = this.root.hubGoals.getCurrentGoalDelivered(); + const deliveredText = "" + formatBigNumber(delivered); + + if (delivered > 9999) { + context.font = "bold 16px GameFont"; + } else if (delivered > 999) { + context.font = "bold 20px GameFont"; + } else { + context.font = "bold 25px GameFont"; + } + context.fillStyle = "#64666e"; + context.textAlign = "left"; + context.fillText(deliveredText, textOffsetX, textOffsetY); + + // Required + context.font = "13px GameFont"; + context.fillStyle = "#a4a6b0"; + context.fillText("/ " + formatBigNumber(goals.required), textOffsetX, textOffsetY + 13); + } + + // Reward + const rewardText = T.storyRewards[goals.reward].title.toUpperCase(); + if (rewardText.length > 12) { + context.font = "bold 8px GameFont"; + } else { + context.font = "bold 10px GameFont"; + } + context.fillStyle = "#fd0752"; + context.textAlign = "center"; + + context.fillText(rewardText, HUB_SIZE_PIXELS / 2, 105); + + // Level "8" + context.font = "bold 10px GameFont"; + context.fillStyle = "#fff"; + context.fillText("" + this.root.hubGoals.level, 27, 32); + + // "LVL" + context.textAlign = "center"; + context.fillStyle = "#fff"; + context.font = "bold 6px GameFont"; + context.fillText(T.buildings.hub.levelShortcut, 27, 22); + + // "Deliver" + context.fillStyle = "#64666e"; + 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 10px GameFont"; + } + 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..780b4abd 100644 --- a/src/js/game/systems/item_acceptor.js +++ b/src/js/game/systems/item_acceptor.js @@ -1,152 +1,106 @@ -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]); + + // Well ... it's better to be verbose I guess? + this.accumulatedTicksWhileInMapOverview = 0; + } + + update() { + if (this.root.app.settings.getAllSettings().simplifiedBelts) { + // Disabled in potato mode + return; + } + + // This system doesn't render anything while in map overview, + // so simply accumulate ticks + if (this.root.camera.getIsMapOverlayActive()) { + ++this.accumulatedTicksWhileInMapOverview; + return; + } + + // Compute how much ticks we missed + const numTicks = 1 + this.accumulatedTicksWhileInMapOverview; + const progress = + this.root.dynamicTickrate.deltaSeconds * + 2 * + this.root.hubGoals.getBeltBaseSpeed() * + globalConfig.itemSpacingOnBelts * // * 2 because its only a half tile + numTicks; + + // Reset accumulated ticks + this.accumulatedTicksWhileInMapOverview = 0; + + 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) { + if (this.root.app.settings.getAllSettings().simplifiedBelts) { + // Disabled in potato mode + return; + } + + 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..56535111 100644 --- a/src/js/game/systems/item_ejector.js +++ b/src/js/game/systems/item_ejector.js @@ -1,392 +1,355 @@ -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 { StaleAreaDetector } from "../../core/stale_area_detector"; +import { enumDirection, enumDirectionToVector } from "../../core/vector"; +import { BaseItem } from "../base_item"; +import { BeltComponent } from "../components/belt"; +import { ItemAcceptorComponent } from "../components/item_acceptor"; +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.staleAreaDetector = new StaleAreaDetector({ + root: this.root, + name: "item-ejector", + recomputeMethod: this.recomputeArea.bind(this), + }); + + this.staleAreaDetector.recomputeOnComponentsChanged( + [ItemEjectorComponent, ItemAcceptorComponent, BeltComponent], + 1 + ); + + this.root.signals.postLoadHook.add(this.recomputeCacheFull, this); + } + + /** + * Recomputes an area after it changed + * @param {Rectangle} area + */ + recomputeArea(area) { + /** @type {Set} */ + const seenUids = new Set(); + for (let x = 0; x < area.w; ++x) { + for (let y = 0; y < area.h; ++y) { + const tileX = area.x + x; + const tileY = area.y + y; + // @NOTICE: Item ejector currently only supports regular layer + const contents = this.root.map.getLayerContentXY(tileX, tileY, "regular"); + if (contents && contents.components.ItemEjector) { + if (!seenUids.has(contents.uid)) { + seenUids.add(contents.uid); + this.recomputeSingleEntityCache(contents); + } + } + } + } + } + + /** + * Recomputes the whole cache after the game has loaded + */ + recomputeCacheFull() { + logger.log("Full cache recompute in post load hook"); + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + this.recomputeSingleEntityCache(entity); + } + } + + /** + * @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() { + this.staleAreaDetector.update(); + + // 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; + + 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; + } + + // 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 destEntity = sourceSlot.cachedTargetEntity; + const destSlot = sourceSlot.cachedDestSlot; + if (destSlot) { + const targetAcceptorComp = destEntity.components.ItemAcceptor; + if (!targetAcceptorComp.canAcceptItem(destSlot.index, item)) { + continue; + } + + // Try to hand over the item + if (this.tryPassOverItem(item, destEntity, destSlot.index)) { + // Handover successful, clear slot + if (!this.root.app.settings.getAllSettings().simplifiedBelts) { + 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. + + 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; + } + + const filterComp = receiver.components.Filter; + if (filterComp) { + // It's a filter! Unfortunately the filter has to know a lot about it's + // surrounding state and components, so it can't be within the component itself. + if (this.root.systemMgr.systems.filter.tryAcceptItem(receiver, slotIndex, item)) { + return true; + } + } + + return false; + } + + /** + * @param {DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + if (this.root.app.settings.getAllSettings().simplifiedBelts) { + // Disabled in potato mode + return; + } + + 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; + } + + if (!ejectorComp.renderFloatingItems && !slot.cachedTargetEntity) { + // Not connected to any building + 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..9775afde 100644 --- a/src/js/game/systems/item_processor.js +++ b/src/js/game/systems/item_processor.js @@ -1,15 +1,70 @@ -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; + +/** + * Whole data for a produced item + * + * @typedef {{ + * item: BaseItem, + * preferredSlot?: number, + * requiredSlot?: number, + * doNotTrack?: boolean + * }} ProducedItem + */ + +/** + * Type of a processor implementation + * @typedef {{ + * entity: Entity, + * items: Array<{ item: BaseItem, sourceSlot: number }>, + * itemsBySlot: Object, + * outItems: Array + * }} ProcessorImplementationPayload + */ + export class ItemProcessorSystem extends GameSystemWithFilter { constructor(root) { super(root, [ItemProcessorComponent]); + + /** + * @type {Object} + */ + this.handlers = { + [enumItemProcessorTypes.balancer]: this.process_BALANCER, + [enumItemProcessorTypes.cutter]: this.process_CUTTER, + [enumItemProcessorTypes.cutterQuad]: this.process_CUTTER_QUAD, + [enumItemProcessorTypes.rotater]: this.process_ROTATER, + [enumItemProcessorTypes.rotaterCCW]: this.process_ROTATER_CCW, + [enumItemProcessorTypes.rotater180]: this.process_ROTATER_180, + [enumItemProcessorTypes.stacker]: this.process_STACKER, + [enumItemProcessorTypes.trash]: this.process_TRASH, + [enumItemProcessorTypes.mixer]: this.process_MIXER, + [enumItemProcessorTypes.painter]: this.process_PAINTER, + [enumItemProcessorTypes.painterDouble]: this.process_PAINTER_DOUBLE, + [enumItemProcessorTypes.painterQuad]: this.process_PAINTER_QUAD, + [enumItemProcessorTypes.hub]: this.process_HUB, + [enumItemProcessorTypes.reader]: this.process_READER, + }; + + // Bind all handlers + for (const key in this.handlers) { + this.handlers[key] = this.handlers[key].bind(this); + } } update() { @@ -19,72 +74,183 @@ 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]; + + assert(ejectorComp, "To eject items, the building needs to have an ejector"); + + 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 && network.hasValue() && isTruthyItem(network.currentValue); + if (!slotIsEnabled) { + return false; + } + 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 network = pinsComp.slots[i].linkedNetwork; + const networkValue = network && network.hasValue() ? network.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; + } + + default: + assertAlways(false, "Unknown requirement for " + processorComp.processingRequirement); + } + } + /** * Starts a new charge for the entity * @param {Entity} entity @@ -96,291 +262,304 @@ export class ItemProcessorSystem extends GameSystemWithFilter { const items = processorComp.inputSlots; processorComp.inputSlots = []; - /** @type {Object.} */ + /** @type {Object} */ const itemsBySlot = {}; for (let i = 0; i < items.length; ++i) { - itemsBySlot[items[i].sourceSlot] = items[i]; + itemsBySlot[items[i].sourceSlot] = items[i].item; } - const baseSpeed = this.root.hubGoals.getProcessorBaseSpeed(processorComp.type); - processorComp.secondsUntilEject = 1 / baseSpeed; - - /** @type {Array<{item: BaseItem, requiredSlot?: number, preferredSlot?: number}>} */ + /** @type {Array} */ const outItems = []; - // Whether to track the production towards the analytics - let trackProduction = true; + /** @type {function(ProcessorImplementationPayload) : void} */ + const handler = this.handlers[processorComp.type]; + assert(handler, "No handler for processor type defined: " + processorComp.type); - // DO SOME MAGIC - - switch (processorComp.type) { - // SPLITTER - case enumItemProcessorTypes.splitterWires: - case enumItemProcessorTypes.splitter: { - trackProduction = false; - const availableSlots = entity.components.ItemEjector.slots.length; - - let nextSlot = processorComp.nextOutputSlot++ % availableSlots; - for (let i = 0; i < items.length; ++i) { - outItems.push({ - item: items[i].item, - preferredSlot: (nextSlot + i) % availableSlots, - }); - } - break; - } - - // CUTTER - case enumItemProcessorTypes.cutter: { - const inputItem = /** @type {ShapeItem} */ (items[0].item); - assert(inputItem instanceof ShapeItem, "Input for cut is not a shape"); - const inputDefinition = inputItem.definition; - - const cutDefinitions = this.root.shapeDefinitionMgr.shapeActionCutHalf(inputDefinition); - - for (let i = 0; i < cutDefinitions.length; ++i) { - const definition = cutDefinitions[i]; - if (!definition.isEntirelyEmpty()) { - outItems.push({ - item: new ShapeItem(definition), - requiredSlot: i, - }); - } - } - - break; - } - - // CUTTER (Quad) - case enumItemProcessorTypes.cutterQuad: { - const inputItem = /** @type {ShapeItem} */ (items[0].item); - assert(inputItem instanceof ShapeItem, "Input for cut is not a shape"); - const inputDefinition = inputItem.definition; - - const cutDefinitions = this.root.shapeDefinitionMgr.shapeActionCutQuad(inputDefinition); - - for (let i = 0; i < cutDefinitions.length; ++i) { - const definition = cutDefinitions[i]; - if (!definition.isEntirelyEmpty()) { - outItems.push({ - item: new ShapeItem(definition), - requiredSlot: i, - }); - } - } - - break; - } - - // ROTATER - case enumItemProcessorTypes.rotater: { - 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.shapeActionRotateCW(inputDefinition); - outItems.push({ - item: new ShapeItem(rotatedDefinition), - }); - break; - } - - // ROTATER ( CCW) - case enumItemProcessorTypes.rotaterCCW: { - 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.shapeActionRotateCCW(inputDefinition); - outItems.push({ - item: new ShapeItem(rotatedDefinition), - }); - break; - } - - // STACKER - - case enumItemProcessorTypes.stacker: { - const lowerItem = /** @type {ShapeItem} */ (itemsBySlot[0].item); - const upperItem = /** @type {ShapeItem} */ (itemsBySlot[1].item); - - assert(lowerItem instanceof ShapeItem, "Input for lower stack is not a shape"); - assert(upperItem instanceof ShapeItem, "Input for upper stack is not a shape"); - - const stackedDefinition = this.root.shapeDefinitionMgr.shapeActionStack( - lowerItem.definition, - upperItem.definition - ); - outItems.push({ - item: new ShapeItem(stackedDefinition), - }); - break; - } - - // TRASH - - case enumItemProcessorTypes.trash: { - // Well this one is easy .. simply do nothing with the item - break; - } - - // MIXER - - case enumItemProcessorTypes.mixer: { - // Find both colors and combine them - const item1 = /** @type {ColorItem} */ (items[0].item); - const item2 = /** @type {ColorItem} */ (items[1].item); - assert(item1 instanceof ColorItem, "Input for color mixer is not a color"); - assert(item2 instanceof ColorItem, "Input for color mixer is not a color"); - - const color1 = item1.color; - const color2 = item2.color; - - // Try finding mixer color, and if we can't mix it we simply return the same color - const mixedColor = enumColorMixingResults[color1][color2]; - let resultColor = color1; - if (mixedColor) { - resultColor = mixedColor; - } - outItems.push({ - item: new ColorItem(resultColor), - }); - - break; - } - - // PAINTER - - case enumItemProcessorTypes.painter: { - const shapeItem = /** @type {ShapeItem} */ (itemsBySlot[0].item); - const colorItem = /** @type {ColorItem} */ (itemsBySlot[1].item); - - const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith( - shapeItem.definition, - colorItem.color - ); - - outItems.push({ - item: new ShapeItem(colorizedDefinition), - }); - - break; - } - - // PAINTER (DOUBLE) - - case enumItemProcessorTypes.painterDouble: { - const shapeItem1 = /** @type {ShapeItem} */ (itemsBySlot[0].item); - const shapeItem2 = /** @type {ShapeItem} */ (itemsBySlot[1].item); - const colorItem = /** @type {ColorItem} */ (itemsBySlot[2].item); - - assert(shapeItem1 instanceof ShapeItem, "Input for painter is not a shape"); - assert(shapeItem2 instanceof ShapeItem, "Input for painter is not a shape"); - assert(colorItem instanceof ColorItem, "Input for painter is not a color"); - - const colorizedDefinition1 = this.root.shapeDefinitionMgr.shapeActionPaintWith( - shapeItem1.definition, - colorItem.color - ); - - const colorizedDefinition2 = this.root.shapeDefinitionMgr.shapeActionPaintWith( - shapeItem2.definition, - colorItem.color - ); - outItems.push({ - item: new ShapeItem(colorizedDefinition1), - }); - - outItems.push({ - item: new ShapeItem(colorizedDefinition2), - }); - - break; - } - - // PAINTER (QUAD) - - 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"); - - const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith4Colors( - shapeItem.definition, - [colorItem2.color, colorItem3.color, colorItem4.color, colorItem1.color] - ); - - outItems.push({ - item: new ShapeItem(colorizedDefinition), - }); - - break; - } - - // HUB - - case enumItemProcessorTypes.hub: { - trackProduction = false; - - const hubComponent = entity.components.Hub; - 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."); - } - - break; - } - - default: - assertAlways(false, "Unkown item processor type: " + processorComp.type); - } + // Call implementation + handler({ + entity, + items, + itemsBySlot, + outItems, + }); // Track produced items - if (trackProduction) { - for (let i = 0; i < outItems.length; ++i) { + for (let i = 0; i < outItems.length; ++i) { + if (!outItems[i].doNotTrack) { this.root.signals.itemProduced.dispatch(outItems[i].item); } } - 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; + + processorComp.bonusTime -= bonusTimeToApply; + processorComp.ongoingCharges.push({ + items: outItems, + remainingTime: timeToProcess, + }); + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_BALANCER(payload) { + assert( + payload.entity.components.ItemEjector, + "To be a balancer, the building needs to have an ejector" + ); + const availableSlots = payload.entity.components.ItemEjector.slots.length; + const processorComp = payload.entity.components.ItemProcessor; + + const nextSlot = processorComp.nextOutputSlot++ % availableSlots; + + for (let i = 0; i < payload.items.length; ++i) { + payload.outItems.push({ + item: payload.items[i].item, + preferredSlot: (nextSlot + i) % availableSlots, + doNotTrack: true, + }); + } + return true; + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_CUTTER(payload) { + const inputItem = /** @type {ShapeItem} */ (payload.items[0].item); + assert(inputItem instanceof ShapeItem, "Input for cut is not a shape"); + const inputDefinition = inputItem.definition; + + const cutDefinitions = this.root.shapeDefinitionMgr.shapeActionCutHalf(inputDefinition); + + for (let i = 0; i < cutDefinitions.length; ++i) { + const definition = cutDefinitions[i]; + if (!definition.isEntirelyEmpty()) { + payload.outItems.push({ + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(definition), + requiredSlot: i, + }); + } + } + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_CUTTER_QUAD(payload) { + const inputItem = /** @type {ShapeItem} */ (payload.items[0].item); + assert(inputItem instanceof ShapeItem, "Input for cut is not a shape"); + const inputDefinition = inputItem.definition; + + const cutDefinitions = this.root.shapeDefinitionMgr.shapeActionCutQuad(inputDefinition); + + for (let i = 0; i < cutDefinitions.length; ++i) { + const definition = cutDefinitions[i]; + if (!definition.isEntirelyEmpty()) { + payload.outItems.push({ + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(definition), + requiredSlot: i, + }); + } + } + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_ROTATER(payload) { + const inputItem = /** @type {ShapeItem} */ (payload.items[0].item); + assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape"); + const inputDefinition = inputItem.definition; + + const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateCW(inputDefinition); + payload.outItems.push({ + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinition), + }); + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_ROTATER_CCW(payload) { + const inputItem = /** @type {ShapeItem} */ (payload.items[0].item); + assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape"); + const inputDefinition = inputItem.definition; + + const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateCCW(inputDefinition); + payload.outItems.push({ + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinition), + }); + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_ROTATER_180(payload) { + const inputItem = /** @type {ShapeItem} */ (payload.items[0].item); + assert(inputItem instanceof ShapeItem, "Input for rotation is not a shape"); + const inputDefinition = inputItem.definition; + + const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotate180(inputDefinition); + payload.outItems.push({ + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinition), + }); + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_STACKER(payload) { + const lowerItem = /** @type {ShapeItem} */ (payload.itemsBySlot[0]); + const upperItem = /** @type {ShapeItem} */ (payload.itemsBySlot[1]); + + assert(lowerItem instanceof ShapeItem, "Input for lower stack is not a shape"); + assert(upperItem instanceof ShapeItem, "Input for upper stack is not a shape"); + + const stackedDefinition = this.root.shapeDefinitionMgr.shapeActionStack( + lowerItem.definition, + upperItem.definition + ); + payload.outItems.push({ + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(stackedDefinition), + }); + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_TRASH(payload) { + // Do nothing .. + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_MIXER(payload) { + // Find both colors and combine them + const item1 = /** @type {ColorItem} */ (payload.items[0].item); + const item2 = /** @type {ColorItem} */ (payload.items[1].item); + assert(item1 instanceof ColorItem, "Input for color mixer is not a color"); + assert(item2 instanceof ColorItem, "Input for color mixer is not a color"); + + const color1 = item1.color; + const color2 = item2.color; + + // Try finding mixer color, and if we can't mix it we simply return the same color + const mixedColor = enumColorMixingResults[color1][color2]; + let resultColor = color1; + if (mixedColor) { + resultColor = mixedColor; + } + payload.outItems.push({ + item: COLOR_ITEM_SINGLETONS[resultColor], + }); + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_PAINTER(payload) { + const shapeItem = /** @type {ShapeItem} */ (payload.itemsBySlot[0]); + const colorItem = /** @type {ColorItem} */ (payload.itemsBySlot[1]); + + const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith( + shapeItem.definition, + colorItem.color + ); + + payload.outItems.push({ + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(colorizedDefinition), + }); + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_PAINTER_DOUBLE(payload) { + const shapeItem1 = /** @type {ShapeItem} */ (payload.itemsBySlot[0]); + const shapeItem2 = /** @type {ShapeItem} */ (payload.itemsBySlot[1]); + const colorItem = /** @type {ColorItem} */ (payload.itemsBySlot[2]); + + assert(shapeItem1 instanceof ShapeItem, "Input for painter is not a shape"); + assert(shapeItem2 instanceof ShapeItem, "Input for painter is not a shape"); + assert(colorItem instanceof ColorItem, "Input for painter is not a color"); + + const colorizedDefinition1 = this.root.shapeDefinitionMgr.shapeActionPaintWith( + shapeItem1.definition, + colorItem.color + ); + + const colorizedDefinition2 = this.root.shapeDefinitionMgr.shapeActionPaintWith( + shapeItem2.definition, + colorItem.color + ); + payload.outItems.push({ + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(colorizedDefinition1), + }); + + payload.outItems.push({ + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(colorizedDefinition2), + }); + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_PAINTER_QUAD(payload) { + const shapeItem = /** @type {ShapeItem} */ (payload.itemsBySlot[0]); + assert(shapeItem instanceof ShapeItem, "Input for painter is not a shape"); + + /** @type {Array} */ + const colors = [null, null, null, null]; + for (let i = 0; i < 4; ++i) { + if (payload.itemsBySlot[i + 1]) { + colors[i] = /** @type {ColorItem} */ (payload.itemsBySlot[i + 1]).color; + } + } + + const colorizedDefinition = this.root.shapeDefinitionMgr.shapeActionPaintWith4Colors( + shapeItem.definition, + /** @type {[string, string, string, string]} */ (colors) + ); + + payload.outItems.push({ + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(colorizedDefinition), + }); + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_READER(payload) { + // Pass through the item + const item = payload.itemsBySlot[0]; + payload.outItems.push({ + item, + doNotTrack: true, + }); + + // Track the item + const readerComp = payload.entity.components.BeltReader; + readerComp.lastItemTimes.push(this.root.time.now()); + readerComp.lastItem = item; + } + + /** + * @param {ProcessorImplementationPayload} payload + */ + process_HUB(payload) { + const hubComponent = payload.entity.components.Hub; + assert(hubComponent, "Hub item processor has no hub component"); + + for (let i = 0; i < payload.items.length; ++i) { + const item = /** @type {ShapeItem} */ (payload.items[i].item); + this.root.hubGoals.handleDefinitionDelivered(item.definition); + } } } 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..3ba44c7b --- /dev/null +++ b/src/js/game/systems/item_processor_overlays.js @@ -0,0 +1,142 @@ +import { globalConfig } from "../../core/config"; +import { Loader } from "../../core/loader"; +import { smoothPulse } 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; + const filterComp = entity.components.Filter; + + // Draw processor overlays + if (processorComp) { + 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; + } + } + + if (processorComp.type === enumItemProcessorTypes.reader) { + this.drawReaderOverlays(parameters, entity); + } + } + + // Draw filter overlays + else if (filterComp) { + if (this.drawnUids.has(entity.uid)) { + continue; + } + this.drawnUids.add(entity.uid); + + this.drawConnectedSlotRequirement(parameters, entity, { drawIfFalse: false }); + } + } + } + + /** + * + * @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.hasValue()) { + 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/item_producer.js b/src/js/game/systems/item_producer.js new file mode 100644 index 00000000..52edf5d1 --- /dev/null +++ b/src/js/game/systems/item_producer.js @@ -0,0 +1,24 @@ +import { ItemProducerComponent } from "../components/item_producer"; +import { GameSystemWithFilter } from "../game_system_with_filter"; + +export class ItemProducerSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [ItemProducerComponent]); + } + + update() { + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + const pinsComp = entity.components.WiredPins; + const pin = pinsComp.slots[0]; + const network = pin.linkedNetwork; + + if (!network || !network.hasValue()) { + continue; + } + + const ejectorComp = entity.components.ItemEjector; + ejectorComp.tryEject(0, network.currentValue); + } + } +} 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..4545a331 --- /dev/null +++ b/src/js/game/systems/logic_gate.js @@ -0,0 +1,358 @@ +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, BooleanItem, isTruthyItem } from "../items/boolean_item"; +import { ColorItem, COLOR_ITEM_SINGLETONS } from "../items/color_item"; +import { ShapeItem } from "../items/shape_item"; +import { ShapeDefinition } from "../shape_definition"; + +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.compare]: this.compute_COMPARE.bind(this), + [enumLogicGateType.stacker]: this.compute_STACKER.bind(this), + [enumLogicGateType.painter]: this.compute_PAINTER.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; + } + const network = slot.linkedNetwork; + if (network) { + if (network.valueConflict) { + anyConflict = true; + break; + } + slotValues.push(network.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 rotatedDefinitionCW = this.root.shapeDefinitionMgr.shapeActionRotateCW(definition); + return this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinitionCW); + } + + /** + * @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_STACKER(parameters) { + const lowerItem = parameters[0]; + const upperItem = parameters[1]; + + if (!lowerItem || !upperItem) { + // Empty + return null; + } + + if (lowerItem.getItemType() !== "shape" || upperItem.getItemType() !== "shape") { + // Bad type + return null; + } + + const stackedShape = this.root.shapeDefinitionMgr.shapeActionStack( + /** @type {ShapeItem} */ (lowerItem).definition, + /** @type {ShapeItem} */ (upperItem).definition + ); + + return this.root.shapeDefinitionMgr.getShapeItemFromDefinition(stackedShape); + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_PAINTER(parameters) { + const shape = parameters[0]; + const color = parameters[1]; + + if (!shape || !color) { + // Empty + return null; + } + + if (shape.getItemType() !== "shape" || color.getItemType() !== "color") { + // Bad type + return null; + } + + const coloredShape = this.root.shapeDefinitionMgr.shapeActionPaintWith( + /** @type {ShapeItem} */ (shape).definition, + /** @type {ColorItem} */ (color).color + ); + + return this.root.shapeDefinitionMgr.getShapeItemFromDefinition(coloredShape); + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_COMPARE(parameters) { + const itemA = parameters[0]; + const itemB = parameters[1]; + + if (!itemA || !itemB) { + // Empty + return null; + } + + 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..807afb36 100644 --- a/src/js/game/systems/map_resources.js +++ b/src/js/game/systems/map_resources.js @@ -1,67 +1,122 @@ -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; + const layerEntities = chunk.contents; + for (let x = 0; x < globalConfig.mapChunkSize; ++x) { + const row = layer[x]; + const rowEntities = layerEntities[x]; + const worldX = (chunk.tileX + x) * globalConfig.tileSize; + for (let y = 0; y < globalConfig.mapChunkSize; ++y) { + const lowerItem = row[y]; + + const entity = rowEntities[y]; + if (entity) { + // Don't draw if there is an entity above + continue; + } + + 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..cd478be3 100644 --- a/src/js/game/systems/miner.js +++ b/src/js/game/systems/miner.js @@ -1,143 +1,201 @@ -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 contentsBelow = this.root.map.getLowerLayerContentXY(staticComp.origin.x, staticComp.origin.y); + if (!contentsBelow) { + // This miner has no contents + return null; + } + + 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) { + const targetLowerLayer = this.root.map.getLowerLayerContentXY(targetTile.x, targetTile.y); + if (targetLowerLayer) { + 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 ejector + + 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..80affac9 100644 --- a/src/js/game/systems/storage.js +++ b/src/js/game/systems/storage.js @@ -1,78 +1,101 @@ -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"; - -export class StorageSystem extends GameSystemWithFilter { - constructor(root) { - super(root, [StorageComponent]); - - this.storageOverlaySprite = Loader.getSprite("sprites/misc/storage_overlay.png"); - } - - update() { - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - const storageComp = entity.components.Storage; - - // Eject from storage - if (storageComp.storedItem && storageComp.storedCount > 0) { - const ejectorComp = entity.components.ItemEjector; - - /* FIXME: WIRES */ - const nextSlot = ejectorComp.getFirstFreeSlot(enumLayer.regular); - if (nextSlot !== null) { - if (ejectorComp.tryEject(nextSlot, storageComp.storedItem)) { - storageComp.storedCount--; - - if (storageComp.storedCount === 0) { - storageComp.storedItem = null; - } - } - } - } - - let targetAlpha = storageComp.storedCount > 0 ? 1 : 0; - storageComp.overlayOpacity = lerp(storageComp.overlayOpacity, targetAlpha, 0.05); - } - } - - draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this)); - } - - /** - * @param {DrawParameters} parameters - * @param {Entity} entity - */ - drawEntity(parameters, entity) { - const context = parameters.context; - const staticComp = entity.components.StaticMapEntity; - - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } - - const storageComp = entity.components.Storage; - - const storedItem = storageComp.storedItem; - if (storedItem !== null) { - context.globalAlpha = storageComp.overlayOpacity; - const center = staticComp.getTileSpaceBounds().getCenter().toWorldSpace(); - storedItem.draw(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"; - context.globalAlpha = 1; - } - } -} +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { StorageComponent } from "../components/storage"; +import { DrawParameters } from "../../core/draw_parameters"; +import { formatBigNumber, lerp } from "../../core/utils"; +import { Loader } from "../../core/loader"; +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; + + const nextSlot = ejectorComp.getFirstFreeSlot(); + if (nextSlot !== null) { + if (ejectorComp.tryEject(nextSlot, storageComp.storedItem)) { + storageComp.storedCount--; + + if (storageComp.storedCount === 0) { + storageComp.storedItem = null; + } + } + } + } + + let targetAlpha = storageComp.storedCount > 0 ? 1 : 0; + storageComp.overlayOpacity = lerp(storageComp.overlayOpacity, targetAlpha, 0.05); + + pinsComp.slots[0].value = storageComp.storedItem; + pinsComp.slots[1].value = storageComp.getIsFull() ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON; + } + } + + /** + * @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 storageComp = entity.components.Storage; + if (!storageComp) { + continue; + } + + const storedItem = storageComp.storedItem; + if (!storedItem) { + continue; + } + + if (this.drawnUids.has(entity.uid)) { + continue; + } + + 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.drawItemCenteredClipped(center.x, center.y, parameters, 30); + + this.storageOverlaySprite.drawCached(parameters, center.x - 15, center.y + 15, 30, 15); + + 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..7a7609f8 100644 --- a/src/js/game/systems/underground_belt.js +++ b/src/js/game/systems/underground_belt.js @@ -1,407 +1,349 @@ -import { globalConfig } from "../../core/config"; -import { Loader } from "../../core/loader"; -import { createLogger } from "../../core/logging"; -import { Rectangle } from "../../core/rectangle"; -import { - enumAngleToDirection, - enumDirection, - enumDirectionToAngle, - enumDirectionToVector, - enumInvertedDirections, -} from "../../core/vector"; -import { enumUndergroundBeltMode, UndergroundBeltComponent } from "../components/underground_belt"; -import { Entity } from "../entity"; -import { GameSystemWithFilter } from "../game_system_with_filter"; -import { fastArrayDelete } from "../../core/utils"; -import { enumLayer } from "../root"; - -const logger = createLogger("tunnels"); - -export class UndergroundBeltSystem extends GameSystemWithFilter { - constructor(root) { - super(root, [UndergroundBeltComponent]); - - this.beltSprites = { - [enumUndergroundBeltMode.sender]: Loader.getSprite( - "sprites/buildings/underground_belt_entry.png" - ), - [enumUndergroundBeltMode.receiver]: Loader.getSprite( - "sprites/buildings/underground_belt_exit.png" - ), - }; - - this.root.signals.entityManuallyPlaced.add(this.onEntityManuallyPlaced, this); - - /** - * @type {Rectangle} - */ - this.areaToRecompute = null; - - this.root.signals.entityAdded.add(this.onEntityChanged, this); - this.root.signals.entityDestroyed.add(this.onEntityChanged, this); - } - - /** - * Called when an entity got added or removed - * @param {Entity} entity - */ - onEntityChanged(entity) { - if (!this.root.gameInitialized) { - return; - } - const undergroundComp = entity.components.UndergroundBelt; - if (!undergroundComp) { - return; - } - - const affectedArea = entity.components.StaticMapEntity.getTileSpaceBounds().expandedInAllDirections( - globalConfig.undergroundBeltMaxTilesByTier[ - globalConfig.undergroundBeltMaxTilesByTier.length - 1 - ] + 1 - ); - - if (this.areaToRecompute) { - this.areaToRecompute = this.areaToRecompute.getUnion(affectedArea); - } else { - this.areaToRecompute = affectedArea; - } - } - - /** - * Callback when an entity got placed, used to remove belts between underground belts - * @param {Entity} entity - */ - onEntityManuallyPlaced(entity) { - if (!this.root.app.settings.getAllSettings().enableTunnelSmartplace) { - // Smart-place disabled - return; - } - - const undergroundComp = entity.components.UndergroundBelt; - if (undergroundComp && undergroundComp.mode === enumUndergroundBeltMode.receiver) { - const staticComp = entity.components.StaticMapEntity; - const tile = staticComp.origin; - - const direction = enumAngleToDirection[staticComp.rotation]; - const inverseDirection = enumInvertedDirections[direction]; - const offset = enumDirectionToVector[inverseDirection]; - - let currentPos = tile.copy(); - - const tier = undergroundComp.tier; - const range = globalConfig.undergroundBeltMaxTilesByTier[tier]; - - // FIND ENTRANCE - // Search for the entrance which is furthes apart (this is why we can't reuse logic here) - let matchingEntrance = null; - for (let i = 0; i < range; ++i) { - currentPos.addInplace(offset); - const contents = this.root.map.getTileContent(currentPos, entity.layer); - if (!contents) { - continue; - } - - const contentsUndergroundComp = contents.components.UndergroundBelt; - const contentsStaticComp = contents.components.StaticMapEntity; - if ( - contentsUndergroundComp && - contentsUndergroundComp.tier === undergroundComp.tier && - contentsUndergroundComp.mode === enumUndergroundBeltMode.sender && - enumAngleToDirection[contentsStaticComp.rotation] === direction - ) { - matchingEntrance = { - entity: contents, - range: i, - }; - } - } - - if (!matchingEntrance) { - // Nothing found - return; - } - - // DETECT OBSOLETE BELTS BETWEEN - // Remove any belts between entrance and exit which have the same direction, - // but only if they *all* have the right direction - currentPos = tile.copy(); - let allBeltsMatch = true; - for (let i = 0; i < matchingEntrance.range; ++i) { - currentPos.addInplace(offset); - - const contents = this.root.map.getTileContent(currentPos, entity.layer); - if (!contents) { - allBeltsMatch = false; - break; - } - - const contentsStaticComp = contents.components.StaticMapEntity; - const contentsBeltComp = contents.components.Belt; - if (!contentsBeltComp) { - allBeltsMatch = false; - break; - } - - // It's a belt - if ( - contentsBeltComp.direction !== enumDirection.top || - enumAngleToDirection[contentsStaticComp.rotation] !== direction - ) { - allBeltsMatch = false; - break; - } - } - - currentPos = tile.copy(); - if (allBeltsMatch) { - // All belts between this are obsolete, so drop them - for (let i = 0; i < matchingEntrance.range; ++i) { - currentPos.addInplace(offset); - const contents = this.root.map.getTileContent(currentPos, entity.layer); - assert(contents, "Invalid smart underground belt logic"); - this.root.logic.tryDeleteBuilding(contents); - } - } - - // REMOVE OBSOLETE TUNNELS - // Remove any double tunnels, by checking the tile plus the tile above - currentPos = tile.copy().add(offset); - for (let i = 0; i < matchingEntrance.range - 1; ++i) { - const posBefore = currentPos.copy(); - currentPos.addInplace(offset); - - const entityBefore = this.root.map.getTileContent(posBefore, entity.layer); - const entityAfter = this.root.map.getTileContent(currentPos, entity.layer); - - if (!entityBefore || !entityAfter) { - continue; - } - - const undergroundBefore = entityBefore.components.UndergroundBelt; - const undergroundAfter = entityAfter.components.UndergroundBelt; - - if (!undergroundBefore || !undergroundAfter) { - // Not an underground belt - continue; - } - - if ( - // Both same tier - undergroundBefore.tier !== undergroundAfter.tier || - // And same tier as our original entity - undergroundBefore.tier !== undergroundComp.tier - ) { - // Mismatching tier - continue; - } - - if ( - undergroundBefore.mode !== enumUndergroundBeltMode.sender || - undergroundAfter.mode !== enumUndergroundBeltMode.receiver - ) { - // Not the right mode - continue; - } - - // Check rotations - const staticBefore = entityBefore.components.StaticMapEntity; - const staticAfter = entityAfter.components.StaticMapEntity; - - if ( - enumAngleToDirection[staticBefore.rotation] !== direction || - enumAngleToDirection[staticAfter.rotation] !== direction - ) { - // Wrong rotation - continue; - } - - // All good, can remove - this.root.logic.tryDeleteBuilding(entityBefore); - this.root.logic.tryDeleteBuilding(entityAfter); - } - } - } - - /** - * Recomputes the cache in the given area, invalidating all entries there - */ - recomputeArea() { - const area = this.areaToRecompute; - logger.log("Recomputing area:", area.x, area.y, "/", area.w, area.h); - if (G_IS_DEV && globalConfig.debug.renderChanges) { - this.root.hud.parts.changesDebugger.renderChange("tunnels", this.areaToRecompute, "#fc03be"); - } - - 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]; - const undergroundComp = entity.components.UndergroundBelt; - if (!undergroundComp) { - continue; - } - - undergroundComp.cachedLinkedEntity = null; - } - } - } - } - - update() { - if (this.areaToRecompute) { - this.recomputeArea(); - this.areaToRecompute = null; - } - - const delta = this.root.dynamicTickrate.deltaSeconds; - - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - const undergroundComp = entity.components.UndergroundBelt; - const pendingItems = undergroundComp.pendingItems; - - // Decrease remaining time of all items in belt - for (let k = 0; k < pendingItems.length; ++k) { - const item = pendingItems[k]; - item[1] = Math.max(0, item[1] - delta); - if (G_IS_DEV && globalConfig.debug.instantBelts) { - item[1] = 0; - } - } - if (undergroundComp.mode === enumUndergroundBeltMode.sender) { - this.handleSender(entity); - } else { - this.handleReceiver(entity); - } - } - } - - /** - * Finds the receiver for a given sender - * @param {Entity} entity - * @returns {import("../components/underground_belt").LinkedUndergroundBelt} - */ - findRecieverForSender(entity) { - const staticComp = entity.components.StaticMapEntity; - const undergroundComp = entity.components.UndergroundBelt; - const searchDirection = staticComp.localDirectionToWorld(enumDirection.top); - const searchVector = enumDirectionToVector[searchDirection]; - const targetRotation = enumDirectionToAngle[searchDirection]; - let currentTile = staticComp.origin; - - // Search in the direction of the tunnel - for ( - let searchOffset = 0; - searchOffset < globalConfig.undergroundBeltMaxTilesByTier[undergroundComp.tier]; - ++searchOffset - ) { - currentTile = currentTile.add(searchVector); - - const potentialReceiver = this.root.map.getTileContent(currentTile, enumLayer.regular); - if (!potentialReceiver) { - // Empty tile - continue; - } - const receiverUndergroundComp = potentialReceiver.components.UndergroundBelt; - if (!receiverUndergroundComp || receiverUndergroundComp.tier !== undergroundComp.tier) { - // Not a tunnel, or not on the same tier - continue; - } - - const receiverStaticComp = potentialReceiver.components.StaticMapEntity; - if (receiverStaticComp.rotation !== targetRotation) { - // Wrong rotation - continue; - } - - if (receiverUndergroundComp.mode !== enumUndergroundBeltMode.receiver) { - // Not a receiver, but a sender -> Abort to make sure we don't deliver double - break; - } - - return { entity: potentialReceiver, distance: searchOffset }; - } - - // None found - return { entity: null, distance: 0 }; - } - - /** - * - * @param {Entity} entity - */ - handleSender(entity) { - const undergroundComp = entity.components.UndergroundBelt; - - // Find the current receiver - let receiver = undergroundComp.cachedLinkedEntity; - if (!receiver) { - // We don't have a receiver, compute it - receiver = undergroundComp.cachedLinkedEntity = this.findRecieverForSender(entity); - - if (G_IS_DEV && globalConfig.debug.renderChanges) { - this.root.hud.parts.changesDebugger.renderChange( - "sender", - entity.components.StaticMapEntity.getTileSpaceBounds(), - "#fc03be" - ); - } - } - - if (!receiver.entity) { - // If there is no connection to a receiver, ignore this one - return; - } - - // Check if we have any item - if (undergroundComp.pendingItems.length > 0) { - assert(undergroundComp.pendingItems.length === 1, "more than 1 pending"); - const nextItemAndDuration = undergroundComp.pendingItems[0]; - const remainingTime = nextItemAndDuration[1]; - const nextItem = nextItemAndDuration[0]; - - // Check if the item is ready to be emitted - if (remainingTime === 0) { - // Check if the receiver can accept it - if ( - receiver.entity.components.UndergroundBelt.tryAcceptTunneledItem( - nextItem, - receiver.distance, - this.root.hubGoals.getUndergroundBeltBaseSpeed() - ) - ) { - // Drop this item - fastArrayDelete(undergroundComp.pendingItems, 0); - } - } - } - } - - /** - * - * @param {Entity} entity - */ - handleReceiver(entity) { - const undergroundComp = entity.components.UndergroundBelt; - - // Try to eject items, we only check the first one because it is sorted by remaining time - const items = undergroundComp.pendingItems; - if (items.length > 0) { - const nextItemAndDuration = undergroundComp.pendingItems[0]; - const remainingTime = nextItemAndDuration[1]; - const nextItem = nextItemAndDuration[0]; - - if (remainingTime <= 0) { - const ejectorComp = entity.components.ItemEjector; - - const nextSlotIndex = ejectorComp.getFirstFreeSlot(entity.layer); - if (nextSlotIndex !== null) { - if (ejectorComp.tryEject(nextSlotIndex, nextItem)) { - items.shift(); - } - } - } - } - } -} +import { globalConfig } from "../../core/config"; +import { Loader } from "../../core/loader"; +import { createLogger } from "../../core/logging"; +import { Rectangle } from "../../core/rectangle"; +import { StaleAreaDetector } from "../../core/stale_area_detector"; +import { fastArrayDelete } from "../../core/utils"; +import { + enumAngleToDirection, + enumDirection, + enumDirectionToAngle, + enumDirectionToVector, + enumInvertedDirections, +} from "../../core/vector"; +import { enumUndergroundBeltMode, UndergroundBeltComponent } from "../components/underground_belt"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; + +const logger = createLogger("tunnels"); + +export class UndergroundBeltSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [UndergroundBeltComponent]); + + this.beltSprites = { + [enumUndergroundBeltMode.sender]: Loader.getSprite( + "sprites/buildings/underground_belt_entry.png" + ), + [enumUndergroundBeltMode.receiver]: Loader.getSprite( + "sprites/buildings/underground_belt_exit.png" + ), + }; + + this.staleAreaWatcher = new StaleAreaDetector({ + root: this.root, + name: "underground-belt", + recomputeMethod: this.recomputeArea.bind(this), + }); + + this.root.signals.entityManuallyPlaced.add(this.onEntityManuallyPlaced, this); + + // NOTICE: Once we remove a tunnel, we need to update the whole area to + // clear outdated handles + this.staleAreaWatcher.recomputeOnComponentsChanged( + [UndergroundBeltComponent], + globalConfig.undergroundBeltMaxTilesByTier[globalConfig.undergroundBeltMaxTilesByTier.length - 1] + ); + } + + /** + * Callback when an entity got placed, used to remove belts between underground belts + * @param {Entity} entity + */ + onEntityManuallyPlaced(entity) { + if (!this.root.app.settings.getAllSettings().enableTunnelSmartplace) { + // Smart-place disabled + return; + } + + const undergroundComp = entity.components.UndergroundBelt; + if (undergroundComp && undergroundComp.mode === enumUndergroundBeltMode.receiver) { + const staticComp = entity.components.StaticMapEntity; + const tile = staticComp.origin; + + const direction = enumAngleToDirection[staticComp.rotation]; + const inverseDirection = enumInvertedDirections[direction]; + const offset = enumDirectionToVector[inverseDirection]; + + let currentPos = tile.copy(); + + const tier = undergroundComp.tier; + const range = globalConfig.undergroundBeltMaxTilesByTier[tier]; + + // FIND ENTRANCE + // Search for the entrance which is farthest apart (this is why we can't reuse logic here) + let matchingEntrance = null; + for (let i = 0; i < range; ++i) { + currentPos.addInplace(offset); + const contents = this.root.map.getTileContent(currentPos, entity.layer); + if (!contents) { + continue; + } + + const contentsUndergroundComp = contents.components.UndergroundBelt; + const contentsStaticComp = contents.components.StaticMapEntity; + if ( + contentsUndergroundComp && + contentsUndergroundComp.tier === undergroundComp.tier && + contentsUndergroundComp.mode === enumUndergroundBeltMode.sender && + enumAngleToDirection[contentsStaticComp.rotation] === direction + ) { + matchingEntrance = { + entity: contents, + range: i, + }; + } + } + + if (!matchingEntrance) { + // Nothing found + return; + } + + // DETECT OBSOLETE BELTS BETWEEN + // Remove any belts between entrance and exit which have the same direction, + // but only if they *all* have the right direction + currentPos = tile.copy(); + let allBeltsMatch = true; + for (let i = 0; i < matchingEntrance.range; ++i) { + currentPos.addInplace(offset); + + const contents = this.root.map.getTileContent(currentPos, entity.layer); + if (!contents) { + allBeltsMatch = false; + break; + } + + const contentsStaticComp = contents.components.StaticMapEntity; + const contentsBeltComp = contents.components.Belt; + if (!contentsBeltComp) { + allBeltsMatch = false; + break; + } + + // It's a belt + if ( + contentsBeltComp.direction !== enumDirection.top || + enumAngleToDirection[contentsStaticComp.rotation] !== direction + ) { + allBeltsMatch = false; + break; + } + } + + currentPos = tile.copy(); + if (allBeltsMatch) { + // All belts between this are obsolete, so drop them + for (let i = 0; i < matchingEntrance.range; ++i) { + currentPos.addInplace(offset); + const contents = this.root.map.getTileContent(currentPos, entity.layer); + assert(contents, "Invalid smart underground belt logic"); + this.root.logic.tryDeleteBuilding(contents); + } + } + + // REMOVE OBSOLETE TUNNELS + // Remove any double tunnels, by checking the tile plus the tile above + currentPos = tile.copy().add(offset); + for (let i = 0; i < matchingEntrance.range - 1; ++i) { + const posBefore = currentPos.copy(); + currentPos.addInplace(offset); + + const entityBefore = this.root.map.getTileContent(posBefore, entity.layer); + const entityAfter = this.root.map.getTileContent(currentPos, entity.layer); + + if (!entityBefore || !entityAfter) { + continue; + } + + const undergroundBefore = entityBefore.components.UndergroundBelt; + const undergroundAfter = entityAfter.components.UndergroundBelt; + + if (!undergroundBefore || !undergroundAfter) { + // Not an underground belt + continue; + } + + if ( + // Both same tier + undergroundBefore.tier !== undergroundAfter.tier || + // And same tier as our original entity + undergroundBefore.tier !== undergroundComp.tier + ) { + // Mismatching tier + continue; + } + + if ( + undergroundBefore.mode !== enumUndergroundBeltMode.sender || + undergroundAfter.mode !== enumUndergroundBeltMode.receiver + ) { + // Not the right mode + continue; + } + + // Check rotations + const staticBefore = entityBefore.components.StaticMapEntity; + const staticAfter = entityAfter.components.StaticMapEntity; + + if ( + enumAngleToDirection[staticBefore.rotation] !== direction || + enumAngleToDirection[staticAfter.rotation] !== direction + ) { + // Wrong rotation + continue; + } + + // All good, can remove + this.root.logic.tryDeleteBuilding(entityBefore); + this.root.logic.tryDeleteBuilding(entityAfter); + } + } + } + + /** + * Recomputes the cache in the given area, invalidating all entries there + * @param {Rectangle} area + */ + recomputeArea(area) { + 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]; + const undergroundComp = entity.components.UndergroundBelt; + if (!undergroundComp) { + continue; + } + undergroundComp.cachedLinkedEntity = null; + } + } + } + } + + update() { + this.staleAreaWatcher.update(); + + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + const undergroundComp = entity.components.UndergroundBelt; + if (undergroundComp.mode === enumUndergroundBeltMode.sender) { + this.handleSender(entity); + } else { + this.handleReceiver(entity); + } + } + } + + /** + * Finds the receiver for a given sender + * @param {Entity} entity + * @returns {import("../components/underground_belt").LinkedUndergroundBelt} + */ + findRecieverForSender(entity) { + const staticComp = entity.components.StaticMapEntity; + const undergroundComp = entity.components.UndergroundBelt; + const searchDirection = staticComp.localDirectionToWorld(enumDirection.top); + const searchVector = enumDirectionToVector[searchDirection]; + const targetRotation = enumDirectionToAngle[searchDirection]; + let currentTile = staticComp.origin; + + // Search in the direction of the tunnel + for ( + let searchOffset = 0; + searchOffset < globalConfig.undergroundBeltMaxTilesByTier[undergroundComp.tier]; + ++searchOffset + ) { + currentTile = currentTile.add(searchVector); + + const potentialReceiver = this.root.map.getTileContent(currentTile, "regular"); + if (!potentialReceiver) { + // Empty tile + continue; + } + const receiverUndergroundComp = potentialReceiver.components.UndergroundBelt; + if (!receiverUndergroundComp || receiverUndergroundComp.tier !== undergroundComp.tier) { + // Not a tunnel, or not on the same tier + continue; + } + + const receiverStaticComp = potentialReceiver.components.StaticMapEntity; + if (receiverStaticComp.rotation !== targetRotation) { + // Wrong rotation + continue; + } + + if (receiverUndergroundComp.mode !== enumUndergroundBeltMode.receiver) { + // Not a receiver, but a sender -> Abort to make sure we don't deliver double + break; + } + + return { entity: potentialReceiver, distance: searchOffset }; + } + + // None found + return { entity: null, distance: 0 }; + } + + /** + * + * @param {Entity} entity + */ + handleSender(entity) { + const undergroundComp = entity.components.UndergroundBelt; + + // Find the current receiver + let cacheEntry = undergroundComp.cachedLinkedEntity; + if (!cacheEntry) { + // Need to recompute cache + cacheEntry = undergroundComp.cachedLinkedEntity = this.findRecieverForSender(entity); + } + + if (!cacheEntry.entity) { + // If there is no connection to a receiver, ignore this one + return; + } + + // Check if we have any items to eject + const nextItemAndDuration = undergroundComp.pendingItems[0]; + if (nextItemAndDuration) { + assert(undergroundComp.pendingItems.length === 1, "more than 1 pending"); + + // Check if the receiver can accept it + if ( + cacheEntry.entity.components.UndergroundBelt.tryAcceptTunneledItem( + nextItemAndDuration[0], + cacheEntry.distance, + this.root.hubGoals.getUndergroundBeltBaseSpeed(), + this.root.time.now() + ) + ) { + // Drop this item + fastArrayDelete(undergroundComp.pendingItems, 0); + } + } + } + + /** + * + * @param {Entity} entity + */ + handleReceiver(entity) { + const undergroundComp = entity.components.UndergroundBelt; + + // Try to eject items, we only check the first one because it is sorted by remaining time + const nextItemAndDuration = undergroundComp.pendingItems[0]; + if (nextItemAndDuration) { + if (this.root.time.now() > nextItemAndDuration[1]) { + const ejectorComp = entity.components.ItemEjector; + + const nextSlotIndex = ejectorComp.getFirstFreeSlot(); + if (nextSlotIndex !== null) { + if (ejectorComp.tryEject(nextSlotIndex, nextItemAndDuration[0])) { + undergroundComp.pendingItems.shift(); + } + } + } + } + } +} diff --git a/src/js/game/systems/wire.js b/src/js/game/systems/wire.js new file mode 100644 index 00000000..4d0e6de4 --- /dev/null +++ b/src/js/game/systems/wire.js @@ -0,0 +1,758 @@ +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 { AtlasSprite } from "../../core/sprites"; +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 { arrayWireRotationVariantToType, MetaWireBuilding } from "../buildings/wire"; +import { getCodeFromBuildingData } from "../building_codes"; +import { enumWireType, enumWireVariant, 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 { isTruthyItem } from "../items/boolean_item"; +import { MapChunkView } from "../map_chunk_view"; + +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; + } + + /** + * Returns whether this network currently has a value + * @returns {boolean} + */ + hasValue() { + return !!this.currentValue && !this.valueConflict; + } +} + +export class WireSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [WireComponent]); + + /** + * @type {Object>} + */ + this.wireSprites = {}; + + const variants = ["conflict", ...Object.keys(enumWireVariant)]; + for (let i = 0; i < variants.length; ++i) { + const wireVariant = variants[i]; + const sprites = {}; + for (const wireType in enumWireType) { + sprites[wireType] = Loader.getSprite( + "sprites/wires/sets/" + wireVariant + "_" + wireType + ".png" + ); + } + this.wireSprites[wireVariant] = sprites; + } + + 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 that's 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, + }, + ]; + + /** + * Once we occur a wire, we store its variant so we don't connect to + * mismatching ones + * @type {enumWireVariant} + */ + let variantMask = null; + + 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) { + if (variantMask && wireComp.variant !== variantMask) { + // Mismatching variant + } else { + // 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; + variantMask = wireComp.variant; + } + } + } + + //// 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, + variantMask + ); + + 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 + * @param {enumWireVariant=} variantMask Only accept connections to this mask + * @returns {Array} + */ + findSurroundingWireTargets(initialTile, directions, network, variantMask = null) { + let result = []; + + VERBOSE_WIRES && + logger.log( + " Searching for new targets at", + initialTile.toString(), + "and d=", + directions, + "with mask=", + variantMask + ); + + // 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 && + (!variantMask || wireComp.variant === variantMask) + ) { + // 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 it's 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; + + // 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[wireComp.variant], + opacity: 0.5, + }; + } + + const network = wireComp.linkedNetwork; + if (network.valueConflict) { + // There is a conflict + return { + spriteSet: this.wireSprites.conflict, + opacity: 1, + }; + } + + return { + spriteSet: this.wireSprites[wireComp.variant], + opacity: isTruthyItem(network.currentValue) ? 1 : 0.5, + }; + } + + /** + * 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); + + // DEBUG Rendering + if (G_IS_DEV && globalConfig.debug.renderWireRotations) { + parameters.context.globalAlpha = 1; + 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 + ); + } + } + } + } + } + + parameters.context.globalAlpha = 1; + } + + /** + * 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 variant = targetStaticComp.getVariant(); + + const { + rotation, + rotationVariant, + } = metaWire.computeOptimalDirectionAndRotationVariantAtTile({ + root: this.root, + tile: new Vector(x, y), + rotation: targetStaticComp.originalRotation, + variant, + 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, variant); + + // Update code as well + targetStaticComp.code = getCodeFromBuildingData(metaWire, variant, 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..e8bc1882 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,86 @@ export class WiredPinsSystem extends GameSystemWithFilter { } } - update() { - // TODO - } - - /** - * Draws the pins - * @param {DrawParameters} parameters - */ - draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawSingleEntity.bind(this)); - } - /** * 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..733b7682 100644 --- a/src/js/game/themes/dark.json +++ b/src/js/game/themes/dark.json @@ -1,48 +1,58 @@ -{ - "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": "#3e3f47", + "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(74, 237, 134)", + "background": "rgba(74, 237, 134, 0.2)" + } + }, + + "colorBlindPickerTile": "rgba(255, 255, 255, 0.5)", + + "resources": { + "shape": "#5d5f6a", + "red": "#854f56", + "green": "#667964", + "blue": "#5e7ca4" + }, + "chunkOverview": { + "empty": "#444856", + "filled": "#646b7d", + "beltColor": "#9096a3" + }, + + "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..0c793c26 100644 --- a/src/js/game/themes/light.json +++ b/src/js/game/themes/light.json @@ -1,49 +1,59 @@ -{ - "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(74, 237, 134)", + "background": "rgba(74, 237, 134, 0.2)" + } + }, + + "colorBlindPickerTile": "rgba(50, 50, 50, 0.4)", + + "resources": { + "shape": "#eaebec", + "red": "#ffbfc1", + "green": "#cbffc4", + "blue": "#bfdaff" + }, + + "chunkOverview": { + "empty": "#a6afbb", + "filled": "#c5ccd6", + "beltColor": "#777" + }, + + "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..84634b0a 100644 --- a/src/js/game/tutorial_goals.js +++ b/src/js/game/tutorial_goals.js @@ -1,178 +1,38 @@ -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); - } - }); -} +/** + * 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_balancer: "reward_balancer", + reward_tunnel: "reward_tunnel", + + reward_rotater_ccw: "reward_rotater_ccw", + reward_rotater_180: "reward_rotater_180", + reward_miner_chainable: "reward_miner_chainable", + reward_underground_belt_tier_2: "reward_underground_belt_tier_2", + reward_belt_reader: "reward_belt_reader", + reward_splitter: "reward_splitter", + reward_cutter_quad: "reward_cutter_quad", + reward_painter_double: "reward_painter_double", + reward_storage: "reward_storage", + reward_merger: "reward_merger", + reward_wires_painter_and_levers: "reward_wires_painter_and_levers", + reward_display: "reward_display", + reward_constant_signal: "reward_constant_signal", + reward_logic_gates: "reward_logic_gates", + reward_virtual_processing: "reward_virtual_processing", + reward_filter: "reward_filter", + + reward_demo_end: "reward_demo_end", + + reward_blueprints: "reward_blueprints", + reward_freeplay: "reward_freeplay", + + no_reward: "no_reward", + no_reward_freeplay: "no_reward_freeplay", +}; diff --git a/src/js/game/tutorial_goals_mappings.js b/src/js/game/tutorial_goals_mappings.js index 905a623a..e0d17cbc 100644 --- a/src/js/game/tutorial_goals_mappings.js +++ b/src/js/game/tutorial_goals_mappings.js @@ -1,51 +1,87 @@ -import { MetaBuilding, defaultBuildingVariant } from "./meta_building"; -import { MetaCutterBuilding, enumCutterVariants } from "./buildings/cutter"; -import { MetaRotaterBuilding, enumRotaterVariants } from "./buildings/rotater"; -import { MetaPainterBuilding, enumPainterVariants } from "./buildings/painter"; -import { MetaMixerBuilding } from "./buildings/mixer"; -import { MetaStackerBuilding } from "./buildings/stacker"; -import { MetaSplitterBuilding, enumSplitterVariants } from "./buildings/splitter"; -import { MetaUndergroundBeltBuilding, enumUndergroundBeltVariants } from "./buildings/underground_belt"; -import { MetaMinerBuilding, enumMinerVariants } from "./buildings/miner"; -import { MetaTrashBuilding, enumTrashVariants } from "./buildings/trash"; - -/** @typedef {Array<[typeof MetaBuilding, string]>} TutorialGoalReward */ - -import { enumHubGoalRewards } from "./tutorial_goals"; - -/** - * Helper method for proper types - * @returns {TutorialGoalReward} - */ -const typed = x => x; - -/** - * Stores which reward unlocks what - * @enum {TutorialGoalReward?} - */ -export const enumHubGoalRewardsToContentUnlocked = { - [enumHubGoalRewards.reward_cutter_and_trash]: typed([[MetaCutterBuilding, defaultBuildingVariant]]), - [enumHubGoalRewards.reward_rotater]: typed([[MetaRotaterBuilding, defaultBuildingVariant]]), - [enumHubGoalRewards.reward_painter]: typed([[MetaPainterBuilding, defaultBuildingVariant]]), - [enumHubGoalRewards.reward_mixer]: typed([[MetaMixerBuilding, defaultBuildingVariant]]), - [enumHubGoalRewards.reward_stacker]: typed([[MetaStackerBuilding, defaultBuildingVariant]]), - [enumHubGoalRewards.reward_splitter]: typed([[MetaSplitterBuilding, defaultBuildingVariant]]), - [enumHubGoalRewards.reward_tunnel]: typed([[MetaUndergroundBeltBuilding, defaultBuildingVariant]]), - - [enumHubGoalRewards.reward_rotater_ccw]: typed([[MetaRotaterBuilding, enumRotaterVariants.ccw]]), - [enumHubGoalRewards.reward_miner_chainable]: typed([[MetaMinerBuilding, enumMinerVariants.chainable]]), - [enumHubGoalRewards.reward_underground_belt_tier_2]: typed([ - [MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2], - ]), - [enumHubGoalRewards.reward_splitter_compact]: typed([ - [MetaSplitterBuilding, enumSplitterVariants.compact], - ]), - [enumHubGoalRewards.reward_cutter_quad]: typed([[MetaCutterBuilding, enumCutterVariants.quad]]), - [enumHubGoalRewards.reward_painter_double]: typed([[MetaPainterBuilding, enumPainterVariants.double]]), - [enumHubGoalRewards.reward_painter_quad]: typed([[MetaPainterBuilding, enumPainterVariants.quad]]), - [enumHubGoalRewards.reward_storage]: typed([[MetaTrashBuilding, enumTrashVariants.storage]]), - - [enumHubGoalRewards.reward_freeplay]: null, - [enumHubGoalRewards.no_reward]: null, - [enumHubGoalRewards.no_reward_freeplay]: null, -}; +import { T } from "../translations"; +import { enumBalancerVariants, MetaBalancerBuilding } from "./buildings/balancer"; +import { MetaConstantSignalBuilding } from "./buildings/constant_signal"; +import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter"; +import { MetaDisplayBuilding } from "./buildings/display"; +import { MetaFilterBuilding } from "./buildings/filter"; +import { MetaLogicGateBuilding } from "./buildings/logic_gate"; +import { enumMinerVariants, MetaMinerBuilding } from "./buildings/miner"; +import { MetaMixerBuilding } from "./buildings/mixer"; +import { enumPainterVariants, MetaPainterBuilding } from "./buildings/painter"; +import { MetaReaderBuilding } from "./buildings/reader"; +import { enumRotaterVariants, MetaRotaterBuilding } from "./buildings/rotater"; +import { MetaStackerBuilding } from "./buildings/stacker"; +import { MetaStorageBuilding } from "./buildings/storage"; +import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt"; +import { defaultBuildingVariant, MetaBuilding } from "./meta_building"; +/** @typedef {Array<[typeof MetaBuilding, string]>} TutorialGoalReward */ +import { enumHubGoalRewards } from "./tutorial_goals"; + +/** + * Helper method for proper types + * @returns {TutorialGoalReward} + */ +const typed = x => x; + +/** + * Stores which reward unlocks what + * @enum {TutorialGoalReward?} + */ +export const enumHubGoalRewardsToContentUnlocked = { + [enumHubGoalRewards.reward_cutter_and_trash]: typed([[MetaCutterBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_rotater]: typed([[MetaRotaterBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_painter]: typed([[MetaPainterBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_mixer]: typed([[MetaMixerBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_stacker]: typed([[MetaStackerBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_balancer]: typed([[MetaBalancerBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_tunnel]: typed([[MetaUndergroundBeltBuilding, defaultBuildingVariant]]), + + [enumHubGoalRewards.reward_rotater_ccw]: typed([[MetaRotaterBuilding, enumRotaterVariants.ccw]]), + [enumHubGoalRewards.reward_rotater_180]: typed([[MetaRotaterBuilding, enumRotaterVariants.rotate180]]), + [enumHubGoalRewards.reward_miner_chainable]: typed([[MetaMinerBuilding, enumMinerVariants.chainable]]), + [enumHubGoalRewards.reward_underground_belt_tier_2]: typed([ + [MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2], + ]), + [enumHubGoalRewards.reward_splitter]: typed([[MetaBalancerBuilding, enumBalancerVariants.splitter]]), + [enumHubGoalRewards.reward_merger]: typed([[MetaBalancerBuilding, enumBalancerVariants.merger]]), + [enumHubGoalRewards.reward_cutter_quad]: typed([[MetaCutterBuilding, enumCutterVariants.quad]]), + [enumHubGoalRewards.reward_painter_double]: typed([[MetaPainterBuilding, enumPainterVariants.double]]), + [enumHubGoalRewards.reward_storage]: typed([[MetaStorageBuilding, defaultBuildingVariant]]), + + [enumHubGoalRewards.reward_belt_reader]: typed([[MetaReaderBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_display]: typed([[MetaDisplayBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_constant_signal]: typed([ + [MetaConstantSignalBuilding, defaultBuildingVariant], + ]), + [enumHubGoalRewards.reward_logic_gates]: typed([[MetaLogicGateBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_filter]: typed([[MetaFilterBuilding, defaultBuildingVariant]]), + [enumHubGoalRewards.reward_virtual_processing]: null, + + [enumHubGoalRewards.reward_wires_painter_and_levers]: typed([ + [MetaPainterBuilding, enumPainterVariants.quad], + ]), + [enumHubGoalRewards.reward_freeplay]: null, + [enumHubGoalRewards.reward_blueprints]: null, + [enumHubGoalRewards.no_reward]: null, + [enumHubGoalRewards.no_reward_freeplay]: null, + [enumHubGoalRewards.reward_demo_end]: null, +}; + +if (G_IS_DEV) { + // Sanity check + for (const rewardId in enumHubGoalRewards) { + const mapping = enumHubGoalRewardsToContentUnlocked[rewardId]; + + if (typeof mapping === "undefined") { + assertAlways( + false, + "Please define a mapping for the reward " + rewardId + " in tutorial_goals_mappings.js" + ); + } + + const translation = T.storyRewards[rewardId]; + if (!translation || !translation.title || !translation.desc) { + assertAlways(false, "Translation for reward " + rewardId + "missing"); + } + } +} diff --git a/src/js/game/upgrades.js b/src/js/game/upgrades.js deleted file mode 100644 index 6e0c7c64..00000000 --- a/src/js/game/upgrades.js +++ /dev/null @@ -1,175 +0,0 @@ -import { findNiceIntegerValue } from "../core/utils"; -import { ShapeDefinition } from "./shape_definition"; - -export const finalGameShape = "RuCw--Cw:----Ru--"; -export const blueprintShape = "CbCbCbRb:CwCwCwCw"; - -export const UPGRADES = { - belt: { - tiers: [ - { - required: [{ shape: "CuCuCuCu", amount: 150 }], - improvement: 1, - }, - { - required: [{ shape: "--CuCu--", amount: 1200 }], - improvement: 2, - }, - { - required: [{ shape: "CpCpCpCp", amount: 15000 }], - improvement: 2, - }, - { - required: [{ shape: "SrSrSrSr:CyCyCyCy", amount: 40000 }], - improvement: 2, - }, - { - required: [{ shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", amount: 40000 }], - improvement: 2, - }, - { - required: [{ shape: finalGameShape, amount: 150000 }], - improvement: 5, - excludePrevious: true, - }, - ], - }, - - miner: { - tiers: [ - { - required: [{ shape: "RuRuRuRu", amount: 400 }], - improvement: 1, - }, - { - required: [{ shape: "Cu------", amount: 4000 }], - improvement: 2, - }, - { - required: [{ shape: "ScScScSc", amount: 20000 }], - improvement: 2, - }, - { - required: [{ shape: "CwCwCwCw:WbWbWbWb", amount: 40000 }], - improvement: 2, - }, - { - required: [{ shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", amount: 40000 }], - improvement: 2, - }, - { - required: [{ shape: finalGameShape, amount: 150000 }], - improvement: 5, - excludePrevious: true, - }, - ], - }, - - processors: { - tiers: [ - { - required: [{ shape: "SuSuSuSu", amount: 1000 }], - improvement: 1, - }, - { - required: [{ shape: "RuRu----", amount: 2000 }], - improvement: 2, - }, - { - required: [{ shape: "CgScScCg", amount: 25000 }], - improvement: 2, - }, - { - required: [{ shape: "CwCrCwCr:SgSgSgSg", amount: 40000 }], - improvement: 2, - }, - { - required: [{ shape: "WrRgWrRg:CwCrCwCr:SgSgSgSg", amount: 40000 }], - improvement: 2, - }, - { - required: [{ shape: finalGameShape, amount: 150000 }], - improvement: 5, - excludePrevious: true, - }, - ], - }, - - painting: { - tiers: [ - { - required: [{ shape: "RbRb----", amount: 1500 }], - improvement: 2, - }, - { - required: [{ shape: "WrWrWrWr", amount: 4000 }], - improvement: 1, - }, - { - required: [{ shape: "RpRpRpRp:CwCwCwCw", amount: 30000 }], - improvement: 2, - }, - { - required: [{ shape: "WpWpWpWp:CwCwCwCw:WpWpWpWp", amount: 40000 }], - improvement: 2, - }, - { - required: [{ shape: "WpWpWpWp:CwCwCwCw:WpWpWpWp:CwCwCwCw", amount: 40000 }], - improvement: 2, - }, - { - required: [{ shape: finalGameShape, amount: 150000 }], - improvement: 5, - excludePrevious: true, - }, - ], - }, -}; - -// Tiers need % of the previous tier as requirement too -const tierGrowth = 2.5; - -// Automatically generate tier levels -for (const upgradeId in UPGRADES) { - const upgrade = UPGRADES[upgradeId]; - - let currentTierRequirements = []; - for (let i = 0; i < upgrade.tiers.length; ++i) { - const tierHandle = upgrade.tiers[i]; - const originalRequired = tierHandle.required.slice(); - - for (let k = currentTierRequirements.length - 1; k >= 0; --k) { - const oldTierRequirement = currentTierRequirements[k]; - if (!tierHandle.excludePrevious) { - tierHandle.required.unshift({ - shape: oldTierRequirement.shape, - amount: oldTierRequirement.amount, - }); - } - } - currentTierRequirements.push( - ...originalRequired.map(req => ({ - amount: req.amount, - shape: req.shape, - })) - ); - currentTierRequirements.forEach(tier => { - tier.amount = findNiceIntegerValue(tier.amount * tierGrowth); - }); - } -} - -if (G_IS_DEV) { - for (const upgradeId in UPGRADES) { - const upgrade = UPGRADES[upgradeId]; - upgrade.tiers.forEach(tier => { - tier.required.forEach(({ shape }) => { - try { - ShapeDefinition.fromShortKey(shape); - } catch (ex) { - throw new Error("Invalid upgrade goal: '" + ex + "' for shape" + shape); - } - }); - }); - } -} diff --git a/src/js/globals.d.ts b/src/js/globals.d.ts index bc99d55e..642745ca 100644 --- a/src/js/globals.d.ts +++ b/src/js/globals.d.ts @@ -19,9 +19,6 @@ declare const G_BUILD_VERSION: string; declare const G_ALL_UI_IMAGES: Array; declare const G_IS_RELEASE: boolean; -// Node require -declare function require(...args): any; - // Polyfills declare interface String { replaceAll(search: string, replacement: string): string; @@ -36,11 +33,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 +119,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 +128,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 +155,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 +189,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/jsconfig.json b/src/js/jsconfig.json index e28a1c04..99d65145 100644 --- a/src/js/jsconfig.json +++ b/src/js/jsconfig.json @@ -2,5 +2,6 @@ "compilerOptions": { "target": "es6", "checkJs": true - } + }, + "include": ["./**/*.js"] } diff --git a/src/js/languages.js b/src/js/languages.js index cac22bcf..46ff8af9 100644 --- a/src/js/languages.js +++ b/src/js/languages.js @@ -1,106 +1,120 @@ -/** - * @type {Object} - */ -export const LANGUAGES = { - "en": { - name: "English", - data: null, - code: "en", - region: "", - }, - "de": { - name: "Deutsch", - data: require("./built-temp/base-de.json"), - code: "de", - region: "", - }, - "fr": { - name: "Français", - data: require("./built-temp/base-fr.json"), - code: "fr", - region: "", - }, - "ja": { - name: "日本語", - data: require("./built-temp/base-ja.json"), - code: "ja", - region: "", - }, - "pt-PT": { - name: "Português (Portugal)", - data: require("./built-temp/base-pt-PT.json"), - code: "pt", - region: "PT", - }, - "pt-BR": { - name: "Português (Brasil)", - data: require("./built-temp/base-pt-BR.json"), - code: "pt", - region: "BR", - }, - "ru": { - name: "Русский", - data: require("./built-temp/base-ru.json"), - code: "ru", - region: "", - }, - "cs": { - name: "Čeština", - data: require("./built-temp/base-cz.json"), - code: "cs", - region: "", - }, - "es-419": { - name: "Español", - data: require("./built-temp/base-es.json"), - code: "es", - region: "", - }, - "pl": { - name: "Polski", - data: require("./built-temp/base-pl.json"), - code: "pl", - region: "", - }, - "kor": { - name: "한국어", - data: require("./built-temp/base-kor.json"), - code: "kor", - region: "", - }, - "nl": { - name: "Nederlands", - data: require("./built-temp/base-nl.json"), - code: "nl", - region: "", - }, - "no": { - name: "Norsk", - data: require("./built-temp/base-no.json"), - code: "no", - region: "", - }, - - "zh-CN": { - // simplified - name: "中文简体", - data: require("./built-temp/base-zh-CN.json"), - code: "zh", - region: "CN", - }, - - "zh-TW": { - // traditional - name: "中文繁體", - data: require("./built-temp/base-zh-TW.json"), - code: "zh", - region: "TW", - }, - - "sv": { - name: "Svenska", - data: require("./built-temp/base-sv.json"), - code: "sv", - region: "", - }, -}; +/** + * @type {Object} + */ +export const LANGUAGES = { + "en": { + name: "English", + data: null, + code: "en", + region: "", + }, + "de": { + name: "Deutsch", + data: require("./built-temp/base-de.json"), + code: "de", + region: "", + }, + "fr": { + name: "Français", + data: require("./built-temp/base-fr.json"), + code: "fr", + region: "", + }, + "ja": { + name: "日本語", + data: require("./built-temp/base-ja.json"), + code: "ja", + region: "", + }, + "pt-PT": { + name: "Português (Portugal)", + data: require("./built-temp/base-pt-PT.json"), + code: "pt", + region: "PT", + }, + "pt-BR": { + name: "Português (Brasil)", + data: require("./built-temp/base-pt-BR.json"), + code: "pt", + region: "BR", + }, + "ru": { + name: "Русский", + data: require("./built-temp/base-ru.json"), + code: "ru", + region: "", + }, + "cs": { + name: "Čeština", + data: require("./built-temp/base-cz.json"), + code: "cs", + region: "", + }, + "es-419": { + name: "Español", + data: require("./built-temp/base-es.json"), + code: "es", + region: "", + }, + "pl": { + name: "Polski", + data: require("./built-temp/base-pl.json"), + code: "pl", + region: "", + }, + "kor": { + name: "한국어", + data: require("./built-temp/base-kor.json"), + code: "kor", + region: "", + }, + "nl": { + name: "Nederlands", + data: require("./built-temp/base-nl.json"), + code: "nl", + region: "", + }, + "no": { + name: "Norsk", + data: require("./built-temp/base-no.json"), + code: "no", + region: "", + }, + + "tr": { + name: "Türkçe", + data: require("./built-temp/base-tr.json"), + code: "tr", + region: "", + }, + + "zh-CN": { + // simplified + name: "中文简体", + data: require("./built-temp/base-zh-CN.json"), + code: "zh", + region: "CN", + }, + + "zh-TW": { + // traditional + name: "中文繁體", + data: require("./built-temp/base-zh-TW.json"), + code: "zh", + region: "TW", + }, + + "sv": { + name: "Svenska", + data: require("./built-temp/base-sv.json"), + code: "sv", + region: "", + }, + + "da": { + name: "Dansk", + data: require("./built-temp/base-da.json"), + code: "da", + region: "", + }, +}; 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..a3947be6 100644 --- a/src/js/platform/browser/game_analytics.js +++ b/src/js/platform/browser/game_analytics.js @@ -1,256 +1,277 @@ -import { globalConfig } from "../../core/config"; -import { createLogger } from "../../core/logging"; -import { GameRoot } from "../../game/root"; -import { InGameState } from "../../states/ingame"; -import { GameAnalyticsInterface } from "../game_analytics"; -import { FILE_NOT_FOUND } from "../storage"; -import { blueprintShape, UPGRADES } from "../../game/upgrades"; -import { tutorialGoals } from "../../game/tutorial_goals"; -import { BeltComponent } from "../../game/components/belt"; -import { StaticMapEntityComponent } from "../../game/components/static_map_entity"; - -const logger = createLogger("game_analytics"); - -const analyticsUrl = G_IS_DEV ? "http://localhost:8001" : "https://analytics.shapez.io"; - -// Be sure to increment the ID whenever it changes to make sure all -// users are tracked -const analyticsLocalFile = "shapez_token_123.bin"; - -export class ShapezGameAnalytics extends GameAnalyticsInterface { - get environment() { - if (G_IS_DEV) { - return "dev"; - } - - if (G_IS_STANDALONE) { - return "steam"; - } - - if (G_IS_RELEASE) { - return "prod"; - } - - return "beta"; - } - - /** - * @returns {Promise} - */ - initialize() { - this.syncKey = null; - - setInterval(() => this.sendTimePoints(), 60 * 1000); - - // Retrieve sync key from player - return this.app.storage.readFileAsync(analyticsLocalFile).then( - syncKey => { - this.syncKey = syncKey; - logger.log("Player sync key read:", this.syncKey); - }, - error => { - // File was not found, retrieve new key - if (error === FILE_NOT_FOUND) { - logger.log("Retrieving new player key"); - - // Perform call to get a new key from the API - this.sendToApi("/v1/register", { - environment: this.environment, - }) - .then(res => { - // Try to read and parse the key from the api - if (res.key && typeof res.key === "string" && res.key.length === 40) { - this.syncKey = res.key; - logger.log("Key retrieved:", this.syncKey); - this.app.storage.writeFileAsync(analyticsLocalFile, res.key); - } else { - throw new Error("Bad response from analytics server: " + res); - } - }) - .catch(err => { - logger.error("Failed to register on analytics api:", err); - }); - } else { - logger.error("Failed to read ga key:", error); - } - return; - } - ); - } - - /** - * Sends a request to the api - * @param {string} endpoint Endpoint without base url - * @param {object} data payload - * @returns {Promise} - */ - sendToApi(endpoint, data) { - return Promise.race([ - new Promise((resolve, reject) => { - setTimeout(() => reject("Request to " + endpoint + " timed out"), 20000); - }), - fetch(analyticsUrl + endpoint, { - method: "POST", - mode: "cors", - cache: "no-cache", - referrer: "no-referrer", - credentials: "omit", - headers: { - "Content-Type": "application/json", - "Accept": "application/json", - "x-api-key": globalConfig.info.analyticsApiKey, - }, - body: JSON.stringify(data), - }) - .then(res => { - if (!res.ok || res.status !== 200) { - throw new Error("Fetch error: Bad status " + res.status); - } - return res; - }) - .then(res => res.json()), - ]); - } - - /** - * Sends a game event to the analytics - * @param {string} category - * @param {string} value - */ - sendGameEvent(category, value) { - if (!this.syncKey) { - logger.warn("Can not send event due to missing sync key"); - return; - } - - const gameState = this.app.stateMgr.currentState; - if (!(gameState instanceof InGameState)) { - logger.warn("Trying to send analytics event outside of ingame state"); - return; - } - - const savegame = gameState.savegame; - if (!savegame) { - logger.warn("Ingame state has empty savegame"); - return; - } - - const savegameId = savegame.internalId; - if (!gameState.core) { - logger.warn("Game state has no core"); - return; - } - const root = gameState.core.root; - if (!root) { - logger.warn("Root is not initialized"); - return; - } - - logger.log("Sending event", category, value); - - this.sendToApi("/v1/game-event", { - playerKey: this.syncKey, - gameKey: savegameId, - ingameTime: root.time.now(), - environment: this.environment, - category, - value, - version: G_BUILD_VERSION, - level: root.hubGoals.level, - gameDump: this.generateGameDump(root), - }); - } - - sendTimePoints() { - const gameState = this.app.stateMgr.currentState; - if (gameState instanceof InGameState) { - logger.log("Syncing analytics"); - this.sendGameEvent("sync", ""); - } - } - - /** - * Returns true if the shape is interesting - * @param {string} key - */ - isInterestingShape(key) { - if (key === blueprintShape) { - return true; - } - - // Check if its a story goal - for (let i = 0; i < tutorialGoals.length; ++i) { - if (key === tutorialGoals[i].shape) { - return true; - } - } - - // Check if its required to unlock an upgrade - for (const upgradeKey in UPGRADES) { - const handle = UPGRADES[upgradeKey]; - const tiers = handle.tiers; - for (let i = 0; i < tiers.length; ++i) { - const tier = tiers[i]; - const required = tier.required; - for (let k = 0; k < required.length; ++k) { - if (required[k].shape === key) { - return true; - } - } - } - } - - return false; - } - - /** - * Generates a game dump - * @param {GameRoot} root - */ - generateGameDump(root) { - const shapeIds = Object.keys(root.hubGoals.storedShapes).filter(this.isInterestingShape.bind(this)); - let shapes = {}; - for (let i = 0; i < shapeIds.length; ++i) { - shapes[shapeIds[i]] = root.hubGoals.storedShapes[shapeIds[i]]; - } - return { - shapes, - upgrades: root.hubGoals.upgradeLevels, - belts: root.entityMgr.getAllWithComponent(BeltComponent).length, - buildings: - root.entityMgr.getAllWithComponent(StaticMapEntityComponent).length - - root.entityMgr.getAllWithComponent(BeltComponent).length, - }; - } - - /** - */ - handleGameStarted() { - this.sendGameEvent("game_start", ""); - } - - /** - */ - handleGameResumed() { - this.sendTimePoints(); - } - - /** - * Handles the given level completed - * @param {number} level - */ - handleLevelCompleted(level) { - logger.log("Complete level", level); - this.sendGameEvent("level_complete", "" + level); - } - - /** - * Handles the given upgrade completed - * @param {string} id - * @param {number} level - */ - handleUpgradeUnlocked(id, level) { - logger.log("Unlock upgrade", id, level); - this.sendGameEvent("upgrade_unlock", id + "@" + level); - } -} +import { globalConfig } from "../../core/config"; +import { createLogger } from "../../core/logging"; +import { queryParamOptions } from "../../core/query_parameters"; +import { BeltComponent } from "../../game/components/belt"; +import { StaticMapEntityComponent } from "../../game/components/static_map_entity"; +import { GameRoot } from "../../game/root"; +import { InGameState } from "../../states/ingame"; +import { GameAnalyticsInterface } from "../game_analytics"; +import { FILE_NOT_FOUND } from "../storage"; + +const logger = createLogger("game_analytics"); + +const analyticsUrl = G_IS_DEV ? "http://localhost:8001" : "https://analytics.shapez.io"; + +// Be sure to increment the ID whenever it changes to make sure all +// users are tracked +const analyticsLocalFile = "shapez_token_123.bin"; + +export class ShapezGameAnalytics extends GameAnalyticsInterface { + get environment() { + if (G_IS_DEV) { + return "dev"; + } + + if (G_IS_STANDALONE) { + if (queryParamOptions.sandboxMode) { + return "steam-sandbox"; + } + return "steam"; + } + + if (G_IS_RELEASE) { + return "prod"; + } + + if (window.location.host.indexOf("alpha") >= 0) { + if (queryParamOptions.sandboxMode) { + return "alpha-sandbox"; + } + return "alpha"; + } else { + if (queryParamOptions.sandboxMode) { + return "beta-sandbox"; + } + return "beta"; + } + } + + /** + * @returns {Promise} + */ + initialize() { + this.syncKey = null; + + setInterval(() => this.sendTimePoints(), 60 * 1000); + + // Retrieve sync key from player + return this.app.storage.readFileAsync(analyticsLocalFile).then( + syncKey => { + this.syncKey = syncKey; + logger.log("Player sync key read:", this.syncKey); + }, + error => { + // File was not found, retrieve new key + if (error === FILE_NOT_FOUND) { + logger.log("Retrieving new player key"); + + // Perform call to get a new key from the API + this.sendToApi("/v1/register", { + environment: this.environment, + }) + .then(res => { + // Try to read and parse the key from the api + if (res.key && typeof res.key === "string" && res.key.length === 40) { + this.syncKey = res.key; + logger.log("Key retrieved:", this.syncKey); + this.app.storage.writeFileAsync(analyticsLocalFile, res.key); + } else { + throw new Error("Bad response from analytics server: " + res); + } + }) + .catch(err => { + logger.error("Failed to register on analytics api:", err); + }); + } else { + logger.error("Failed to read ga key:", error); + } + return; + } + ); + } + + /** + * Sends a request to the api + * @param {string} endpoint Endpoint without base url + * @param {object} data payload + * @returns {Promise} + */ + sendToApi(endpoint, data) { + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => reject("Request to " + endpoint + " timed out"), 20000); + + fetch(analyticsUrl + endpoint, { + method: "POST", + mode: "cors", + cache: "no-cache", + referrer: "no-referrer", + credentials: "omit", + headers: { + "Content-Type": "application/json", + "Accept": "application/json", + "x-api-key": globalConfig.info.analyticsApiKey, + }, + body: JSON.stringify(data), + }) + .then(res => { + clearTimeout(timeout); + if (!res.ok || res.status !== 200) { + reject("Fetch error: Bad status " + res.status); + } else { + return res.json(); + } + }) + .then(resolve) + .catch(reason => { + clearTimeout(timeout); + reject(reason); + }); + }); + } + + /** + * Sends a game event to the analytics + * @param {string} category + * @param {string} value + */ + sendGameEvent(category, value) { + if (!this.syncKey) { + logger.warn("Can not send event due to missing sync key"); + return; + } + + const gameState = this.app.stateMgr.currentState; + if (!(gameState instanceof InGameState)) { + logger.warn("Trying to send analytics event outside of ingame state"); + return; + } + + const savegame = gameState.savegame; + if (!savegame) { + logger.warn("Ingame state has empty savegame"); + return; + } + + const savegameId = savegame.internalId; + if (!gameState.core) { + logger.warn("Game state has no core"); + return; + } + const root = gameState.core.root; + if (!root) { + logger.warn("Root is not initialized"); + return; + } + + logger.log("Sending event", category, value); + + this.sendToApi("/v1/game-event", { + playerKey: this.syncKey, + gameKey: savegameId, + ingameTime: root.time.now(), + environment: this.environment, + category, + value, + version: G_BUILD_VERSION, + level: root.hubGoals.level, + gameDump: this.generateGameDump(root), + }); + } + + sendTimePoints() { + const gameState = this.app.stateMgr.currentState; + if (gameState instanceof InGameState) { + logger.log("Syncing analytics"); + this.sendGameEvent("sync", ""); + } + } + + /** + * Returns true if the shape is interesting + * @param {GameRoot} root + * @param {string} key + */ + isInterestingShape(root, key) { + if (key === root.gameMode.getBlueprintShapeKey()) { + return true; + } + + // Check if its a story goal + const levels = root.gameMode.getLevelDefinitions(); + for (let i = 0; i < levels.length; ++i) { + if (key === levels[i].shape) { + return true; + } + } + + // Check if its required to unlock an upgrade + const upgrades = root.gameMode.getUpgrades(); + for (const upgradeKey in upgrades) { + const upgradeTiers = upgrades[upgradeKey]; + for (let i = 0; i < upgradeTiers.length; ++i) { + const tier = upgradeTiers[i]; + const required = tier.required; + for (let k = 0; k < required.length; ++k) { + if (required[k].shape === key) { + return true; + } + } + } + } + + return false; + } + + /** + * Generates a game dump + * @param {GameRoot} root + */ + generateGameDump(root) { + const shapeIds = Object.keys(root.hubGoals.storedShapes).filter(key => + this.isInterestingShape(root, key) + ); + let shapes = {}; + for (let i = 0; i < shapeIds.length; ++i) { + shapes[shapeIds[i]] = root.hubGoals.storedShapes[shapeIds[i]]; + } + return { + shapes, + upgrades: root.hubGoals.upgradeLevels, + belts: root.entityMgr.getAllWithComponent(BeltComponent).length, + buildings: + root.entityMgr.getAllWithComponent(StaticMapEntityComponent).length - + root.entityMgr.getAllWithComponent(BeltComponent).length, + }; + } + + /** + */ + handleGameStarted() { + this.sendGameEvent("game_start", ""); + } + + /** + */ + handleGameResumed() { + this.sendTimePoints(); + } + + /** + * Handles the given level completed + * @param {number} level + */ + handleLevelCompleted(level) { + logger.log("Complete level", level); + this.sendGameEvent("level_complete", "" + level); + } + + /** + * Handles the given upgrade completed + * @param {string} id + * @param {number} level + */ + handleUpgradeUnlocked(id, level) { + logger.log("Unlock upgrade", id, level); + this.sendGameEvent("upgrade_unlock", id + "@" + level); + } +} 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 726f843b..232a743b 100644 --- a/src/js/platform/browser/wrapper.js +++ b/src/js/platform/browser/wrapper.js @@ -1,214 +1,202 @@ -import { globalConfig, IS_DEMO, IS_MOBILE } from "../../core/config"; -import { createLogger } from "../../core/logging"; -import { queryParamOptions } from "../../core/query_parameters"; -import { clamp } from "../../core/utils"; -import { GamedistributionAdProvider } from "../ad_providers/gamedistribution"; -import { NoAdProvider } from "../ad_providers/no_ad_provider"; -import { PlatformWrapperInterface } from "../wrapper"; -import { StorageImplBrowser } from "./storage"; -import { StorageImplBrowserIndexedDB } from "./storage_indexed_db"; - -const logger = createLogger("platform/browser"); - -export class PlatformWrapperImplBrowser extends PlatformWrapperInterface { - initialize() { - this.recaptchaTokenCallback = null; - - this.embedProvider = { - id: "shapezio-website", - adProvider: NoAdProvider, - iframed: false, - externalLinks: true, - iogLink: true, - unlimitedSavegames: IS_DEMO ? false : true, - showDemoBadge: IS_DEMO, - }; - - if (!G_IS_STANDALONE && queryParamOptions.embedProvider) { - const providerId = queryParamOptions.embedProvider; - this.embedProvider.iframed = true; - this.embedProvider.iogLink = false; - - switch (providerId) { - case "armorgames": { - this.embedProvider.id = "armorgames"; - break; - } - - case "iogames.space": { - this.embedProvider.id = "iogames.space"; - this.embedProvider.iogLink = true; - this.embedProvider.unlimitedSavegames = true; - this.embedProvider.showDemoBadge = false; - break; - } - - case "miniclip": { - this.embedProvider.id = "miniclip"; - break; - } - - case "gamedistribution": { - this.embedProvider.id = "gamedistribution"; - this.embedProvider.externalLinks = false; - this.embedProvider.adProvider = GamedistributionAdProvider; - break; - } - - case "kongregate": { - this.embedProvider.id = "kongregate"; - break; - } - - case "crazygames": { - this.embedProvider.id = "crazygames"; - break; - } - - default: { - logger.error("Got unsupported embed provider:", providerId); - } - } - } - - logger.log("Embed provider:", this.embedProvider.id); - - return this.detectStorageImplementation() - .then(() => this.initializeAdProvider()) - .then(() => super.initialize()); - } - - detectStorageImplementation() { - return new Promise(resolve => { - logger.log("Detecting storage"); - - if (!window.indexedDB || G_IS_DEV) { - logger.log("Indexed DB not supported"); - this.app.storage = new StorageImplBrowser(this.app); - resolve(); - return; - } - - // Try accessing the indexedb - let request; - try { - 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; - } - request.onerror = err => { - logger.log("Indexed DB can *not* be accessed: ", err); - logger.log("Using fallback to local storage"); - this.app.storage = new StorageImplBrowser(this.app); - resolve(); - }; - request.onsuccess = () => { - logger.log("Indexed DB *can* be accessed"); - this.app.storage = new StorageImplBrowserIndexedDB(this.app); - resolve(); - }; - }); - } - - getHasUnlimitedSavegames() { - return this.embedProvider.unlimitedSavegames; - } - - getShowDemoBadges() { - return this.embedProvider.showDemoBadge; - } - - getId() { - return "browser@" + this.embedProvider.id; - } - - getUiScale() { - if (IS_MOBILE) { - return 1; - } - - const avgDims = Math.min(this.app.screenWidth, this.app.screenHeight); - return clamp((avgDims / 1000.0) * 1.9, 0.1, 10); - } - - getSupportsRestart() { - return true; - } - - getTouchPanStrength() { - return IS_MOBILE ? 1 : 0.5; - } - - openExternalLink(url, force = false) { - logger.log("Opening external:", url); - if (force || this.embedProvider.externalLinks) { - window.open(url); - } else { - // Do nothing - alert( - "This platform does not allow opening external links. You can play on https://shapez.io directly to open them.\n\nClicked Link: " + - url - ); - } - } - - performRestart() { - logger.log("Performing restart"); - window.location.reload(true); - } - - /** - * Detects if there is an adblocker installed - * @returns {Promise} - */ - detectAdblock() { - return Promise.race([ - new Promise(resolve => { - // If the request wasn't blocked within a very short period of time, this means - // the adblocker is not active and the request was actually made -> ignore it then - setTimeout(() => resolve(false), 30); - }), - new Promise(resolve => { - fetch("https://googleads.g.doubleclick.net/pagead/id", { - method: "HEAD", - mode: "no-cors", - }) - .then(res => { - resolve(false); - }) - .catch(err => { - resolve(true); - }); - }), - ]); - } - - initializeAdProvider() { - if (G_IS_DEV && !globalConfig.debug.testAds) { - logger.log("Ads disabled in local environment"); - return Promise.resolve(); - } - - // First, detect adblocker - return this.detectAdblock().then(hasAdblocker => { - if (hasAdblocker) { - logger.log("Adblock detected"); - return; - } - - const adProvider = this.embedProvider.adProvider; - this.app.adProvider = new adProvider(this.app); - return this.app.adProvider.initialize().catch(err => { - logger.error("Failed to initialize ad provider, disabling ads:", err); - this.app.adProvider = new NoAdProvider(this.app); - }); - }); - } - - exitApp() { - // Can not exit app - } -} +import { globalConfig, IS_MOBILE } from "../../core/config"; +import { createLogger } from "../../core/logging"; +import { queryParamOptions } from "../../core/query_parameters"; +import { clamp } from "../../core/utils"; +import { GamedistributionAdProvider } from "../ad_providers/gamedistribution"; +import { NoAdProvider } from "../ad_providers/no_ad_provider"; +import { PlatformWrapperInterface } from "../wrapper"; +import { StorageImplBrowser } from "./storage"; +import { StorageImplBrowserIndexedDB } from "./storage_indexed_db"; + +const logger = createLogger("platform/browser"); + +export class PlatformWrapperImplBrowser extends PlatformWrapperInterface { + initialize() { + this.recaptchaTokenCallback = null; + + this.embedProvider = { + id: "shapezio-website", + adProvider: NoAdProvider, + iframed: false, + externalLinks: true, + iogLink: true, + }; + + if (!G_IS_STANDALONE && queryParamOptions.embedProvider) { + const providerId = queryParamOptions.embedProvider; + this.embedProvider.iframed = true; + this.embedProvider.iogLink = false; + + switch (providerId) { + case "armorgames": { + this.embedProvider.id = "armorgames"; + break; + } + + case "iogames.space": { + this.embedProvider.id = "iogames.space"; + this.embedProvider.iogLink = true; + break; + } + + case "miniclip": { + this.embedProvider.id = "miniclip"; + break; + } + + case "gamedistribution": { + this.embedProvider.id = "gamedistribution"; + this.embedProvider.externalLinks = false; + this.embedProvider.adProvider = GamedistributionAdProvider; + break; + } + + case "kongregate": { + this.embedProvider.id = "kongregate"; + break; + } + + case "crazygames": { + this.embedProvider.id = "crazygames"; + break; + } + + default: { + logger.error("Got unsupported embed provider:", providerId); + } + } + } + + logger.log("Embed provider:", this.embedProvider.id); + + return this.detectStorageImplementation() + .then(() => this.initializeAdProvider()) + .then(() => super.initialize()); + } + + detectStorageImplementation() { + return new Promise(resolve => { + logger.log("Detecting storage"); + + if (!window.indexedDB) { + logger.log("Indexed DB not supported"); + this.app.storage = new StorageImplBrowser(this.app); + resolve(); + return; + } + + // Try accessing the indexedb + let request; + try { + 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; + } + request.onerror = err => { + logger.log("Indexed DB can *not* be accessed: ", err); + logger.log("Using fallback to local storage"); + this.app.storage = new StorageImplBrowser(this.app); + resolve(); + }; + request.onsuccess = () => { + logger.log("Indexed DB *can* be accessed"); + this.app.storage = new StorageImplBrowserIndexedDB(this.app); + resolve(); + }; + }); + } + + getId() { + return "browser@" + this.embedProvider.id; + } + + getUiScale() { + if (IS_MOBILE) { + return 1; + } + + const avgDims = Math.min(this.app.screenWidth, this.app.screenHeight); + return clamp((avgDims / 1000.0) * 1.9, 0.1, 10); + } + + getSupportsRestart() { + return true; + } + + getTouchPanStrength() { + return IS_MOBILE ? 1 : 0.5; + } + + openExternalLink(url, force = false) { + logger.log("Opening external:", url); + if (force || this.embedProvider.externalLinks) { + window.open(url); + } else { + // Do nothing + alert( + "This platform does not allow opening external links. You can play on https://shapez.io directly to open them.\n\nClicked Link: " + + url + ); + } + } + + performRestart() { + logger.log("Performing restart"); + window.location.reload(true); + } + + /** + * Detects if there is an adblocker installed + * @returns {Promise} + */ + detectAdblock() { + return Promise.race([ + new Promise(resolve => { + // If the request wasn't blocked within a very short period of time, this means + // the adblocker is not active and the request was actually made -> ignore it then + setTimeout(() => resolve(false), 30); + }), + new Promise(resolve => { + fetch("https://googleads.g.doubleclick.net/pagead/id", { + method: "HEAD", + mode: "no-cors", + }) + .then(res => { + resolve(false); + }) + .catch(err => { + resolve(true); + }); + }), + ]); + } + + initializeAdProvider() { + if (G_IS_DEV && !globalConfig.debug.testAds) { + logger.log("Ads disabled in local environment"); + return Promise.resolve(); + } + + // First, detect adblocker + return this.detectAdblock().then(hasAdblocker => { + if (hasAdblocker) { + logger.log("Adblock detected"); + return; + } + + const adProvider = this.embedProvider.adProvider; + this.app.adProvider = new adProvider(this.app); + return this.app.adProvider.initialize().catch(err => { + logger.error("Failed to initialize ad provider, disabling ads:", err); + this.app.adProvider = new NoAdProvider(this.app); + }); + }); + } + + exitApp() { + // Can not exit app + } +} diff --git a/src/js/platform/electron/wrapper.js b/src/js/platform/electron/wrapper.js index 69bc9695..941aff44 100644 --- a/src/js/platform/electron/wrapper.js +++ b/src/js/platform/electron/wrapper.js @@ -1,65 +1,57 @@ -import { PlatformWrapperImplBrowser } from "../browser/wrapper"; -import { getIPCRenderer } from "../../core/utils"; -import { createLogger } from "../../core/logging"; -import { StorageImplElectron } from "./storage"; -import { PlatformWrapperInterface } from "../wrapper"; - -const logger = createLogger("electron-wrapper"); - -export class PlatformWrapperImplElectron extends PlatformWrapperImplBrowser { - initialize() { - this.app.storage = new StorageImplElectron(this); - return PlatformWrapperInterface.prototype.initialize.call(this); - } - - getId() { - return "electron"; - } - - getSupportsRestart() { - return true; - } - - openExternalLink(url) { - logger.log(this, "Opening external:", url); - window.open(url, "about:blank"); - } - - getSupportsAds() { - return false; - } - - getHasUnlimitedSavegames() { - return true; - } - - getShowDemoBadges() { - return false; - } - - performRestart() { - logger.log(this, "Performing restart"); - window.location.reload(true); - } - - initializeAdProvider() { - return Promise.resolve(); - } - - getSupportsFullscreen() { - return true; - } - - setFullscreen(flag) { - getIPCRenderer().send("set-fullscreen", flag); - } - - getSupportsAppExit() { - return true; - } - - exitApp() { - logger.log(this, "Sending app exit signal"); - getIPCRenderer().send("exit-app"); - } -} +import { PlatformWrapperImplBrowser } from "../browser/wrapper"; +import { getIPCRenderer } from "../../core/utils"; +import { createLogger } from "../../core/logging"; +import { StorageImplElectron } from "./storage"; +import { PlatformWrapperInterface } from "../wrapper"; + +const logger = createLogger("electron-wrapper"); + +export class PlatformWrapperImplElectron extends PlatformWrapperImplBrowser { + initialize() { + this.app.storage = new StorageImplElectron(this); + return PlatformWrapperInterface.prototype.initialize.call(this); + } + + getId() { + return "electron"; + } + + getSupportsRestart() { + return true; + } + + openExternalLink(url) { + logger.log(this, "Opening external:", url); + window.open(url, "about:blank"); + } + + getSupportsAds() { + return false; + } + + performRestart() { + logger.log(this, "Performing restart"); + window.location.reload(true); + } + + initializeAdProvider() { + return Promise.resolve(); + } + + getSupportsFullscreen() { + return true; + } + + setFullscreen(flag) { + getIPCRenderer().send("set-fullscreen", flag); + } + + getSupportsAppExit() { + return true; + } + + exitApp() { + logger.log(this, "Sending app exit signal"); + getIPCRenderer().send("exit-app"); + } +} 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..9d5a8461 100644 --- a/src/js/platform/sound.js +++ b/src/js/platform/sound.js @@ -25,10 +25,13 @@ export const SOUNDS = { destroyBuilding: "destroy_building", placeBuilding: "place_building", placeBelt: "place_belt", + copy: "copy", }; export const MUSIC = { - theme: "theme", + // The theme always depends on the standalone only, even if running the full + // version in the browser + theme: G_IS_STANDALONE ? "theme-full" : "theme-short", menu: "menu", }; @@ -61,7 +64,11 @@ export class MusicInstanceInterface { abstract; } - play() { + play(volume) { + abstract; + } + + setVolume(volume) { abstract; } @@ -99,8 +106,8 @@ export class SoundInterface { this.pageIsVisible = true; - this.musicMuted = false; - this.soundsMuted = false; + this.musicVolume = 1.0; + this.soundVolume = 1.0; } /** @@ -120,11 +127,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 +169,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 +211,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 +224,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 +242,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 +251,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 +273,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..f80c2fd6 100644 --- a/src/js/platform/wrapper.js +++ b/src/js/platform/wrapper.js @@ -1,142 +1,131 @@ -/* typehints:start */ -import { Application } from "../application"; -/* typehints:end */ - -import { IS_MOBILE } from "../core/config"; - -export class PlatformWrapperInterface { - constructor(app) { - /** @type {Application} */ - this.app = app; - } - - /** @returns {string} */ - getId() { - abstract; - return "unknown-platform"; - } - - /** - * Returns the UI scale, called on every resize - * @returns {number} */ - getUiScale() { - return 1; - } - - /** @returns {boolean} */ - getSupportsRestart() { - abstract; - return false; - } - - /** - * Whether the user has unlimited savegames - */ - getHasUnlimitedSavegames() { - return true; - } - - getShowDemoBadges() { - return false; - } - - /** - * Returns the strength of touch pans with the mouse - */ - getTouchPanStrength() { - return 1; - } - - /** @returns {Promise} */ - initialize() { - document.documentElement.classList.add("p-" + this.getId()); - return Promise.resolve(); - } - - /** - * Should initialize the apps ad provider in case supported - * @returns {Promise} - */ - initializeAdProvider() { - return Promise.resolve(); - } - - /** - * Should return the minimum supported zoom level - * @returns {number} - */ - getMinimumZoom() { - return 0.2 * this.getScreenScale(); - } - - /** - * Should return the maximum supported zoom level - * @returns {number} - */ - getMaximumZoom() { - return 4 * this.getScreenScale(); - } - - getScreenScale() { - return Math.min(window.innerWidth, window.innerHeight) / 1024.0; - } - - /** - * Should return if this platform supports ads at all - */ - getSupportsAds() { - return false; - } - - /** - * Attempt to open an external url - * @param {string} url - * @param {boolean=} force Whether to always open the url even if not allowed - */ - openExternalLink(url, force = false) { - abstract; - } - - /** - * Attempt to restart the app - */ - performRestart() { - abstract; - } - - /** - * Returns whether this platform supports a toggleable fullscreen - */ - getSupportsFullscreen() { - return false; - } - - /** - * Should set the apps fullscreen state to the desired state - * @param {boolean} flag - */ - setFullscreen(flag) { - abstract; - } - - /** - * Returns whether this platform supports quitting the app - */ - getSupportsAppExit() { - return false; - } - - /** - * Attempts to quit the app - */ - exitApp() { - abstract; - } - - /** - * Whether this platform supports a keyboard - */ - getSupportsKeyboard() { - return !IS_MOBILE; - } -} +/* typehints:start */ +import { Application } from "../application"; +/* typehints:end */ + +import { IS_MOBILE } from "../core/config"; + +export class PlatformWrapperInterface { + constructor(app) { + /** @type {Application} */ + this.app = app; + } + + /** @returns {string} */ + getId() { + abstract; + return "unknown-platform"; + } + + /** + * Returns the UI scale, called on every resize + * @returns {number} */ + getUiScale() { + return 1; + } + + /** @returns {boolean} */ + getSupportsRestart() { + abstract; + return false; + } + + /** + * Returns the strength of touch pans with the mouse + */ + getTouchPanStrength() { + return 1; + } + + /** @returns {Promise} */ + initialize() { + document.documentElement.classList.add("p-" + this.getId()); + return Promise.resolve(); + } + + /** + * Should initialize the apps ad provider in case supported + * @returns {Promise} + */ + initializeAdProvider() { + return Promise.resolve(); + } + + /** + * Should return the minimum supported zoom level + * @returns {number} + */ + getMinimumZoom() { + return 0.1 * this.getScreenScale(); + } + + /** + * Should return the maximum supported zoom level + * @returns {number} + */ + getMaximumZoom() { + return 3.5 * this.getScreenScale(); + } + + getScreenScale() { + return Math.min(window.innerWidth, window.innerHeight) / 1024.0; + } + + /** + * Should return if this platform supports ads at all + */ + getSupportsAds() { + return false; + } + + /** + * Attempt to open an external url + * @param {string} url + * @param {boolean=} force Whether to always open the url even if not allowed + */ + openExternalLink(url, force = false) { + abstract; + } + + /** + * Attempt to restart the app + */ + performRestart() { + abstract; + } + + /** + * Returns whether this platform supports a toggleable fullscreen + */ + getSupportsFullscreen() { + return false; + } + + /** + * Should set the apps fullscreen state to the desired state + * @param {boolean} flag + */ + setFullscreen(flag) { + abstract; + } + + /** + * Returns whether this platform supports quitting the app + */ + getSupportsAppExit() { + return false; + } + + /** + * Attempts to quit the app + */ + exitApp() { + abstract; + } + + /** + * Whether this platform supports a keyboard + */ + getSupportsKeyboard() { + return !IS_MOBILE; + } +} diff --git a/src/js/profile/application_settings.js b/src/js/profile/application_settings.js index e3ff0ee3..9ec5d541 100644 --- a/src/js/profile/application_settings.js +++ b/src/js/profile/application_settings.js @@ -3,18 +3,24 @@ 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"; -import { IS_DEMO } from "../core/config"; +import { THEMES, applyGameTheme } from "../game/theme"; import { T } from "../translations"; 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 +122,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 +149,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 +158,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 */ @@ -152,43 +186,27 @@ export const allApplicationSettings = [ app.platformWrapper.setFullscreen(value); } }, - !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) + */ app => app.restrictionMgr.getHasExtendedSettings() ), 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: /** @@ -198,14 +216,16 @@ export const allApplicationSettings = [ applyGameTheme(id); document.documentElement.setAttribute("data-theme", id); }, - enabled: !IS_DEMO, + enabledCb: /** + * @param {Application} app + */ app => app.restrictionMgr.getHasExtendedSettings(), }), new EnumSetting("autosaveInterval", { 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 +234,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 +251,40 @@ 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("enableMousePan", enumCategories.advanced, (app, value) => {}), + new BoolSetting("alwaysMultiplace", enumCategories.advanced, (app, value) => {}), + new BoolSetting("zoomToCursor", 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 RangeSetting("mapResourcesScale", enumCategories.advanced, () => null), + + new EnumSetting("refreshRate", { + options: refreshRateOptions, + valueGetter: rate => rate, + textGetter: rate => rate + " Hz", + category: enumCategories.performance, + restartRequired: false, + changeCb: (app, id) => {}, + enabledCb: /** + * @param {Application} app + */ app => app.restrictionMgr.getHasExtendedSettings(), + }), + + new BoolSetting("lowQualityMapResources", enumCategories.performance, (app, value) => {}), + new BoolSetting("disableTileGrid", enumCategories.performance, (app, value) => {}), + new BoolSetting("lowQualityTextures", enumCategories.performance, (app, value) => {}), + new BoolSetting("simplifiedBelts", enumCategories.performance, (app, value) => {}), new BoolSetting("middleMousePan", categoryGame, (app, value) => {}), new BoolSetting("canDeleteWhileBuilding", categoryGame, (app, value) => {}), ]; @@ -265,8 +298,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"; @@ -281,11 +315,22 @@ class SettingsStorage { this.compactBuildingInfo = false; this.disableCutDeleteWarnings = false; this.rotationByBuilding = true; + this.clearCursorOnDeleteWhilePlacing = true; + this.displayChunkBorders = false; + this.pickMinerOnPatch = true; + this.enableMousePan = true; this.middleMousePan = false; this.canDeleteWhileBuilding = false; this.enableColorBlindHelper = false; + this.lowQualityMapResources = false; + this.disableTileGrid = false; + this.lowQualityTextures = false; + this.simplifiedBelts = false; + this.zoomToCursor = true; + this.mapResourcesScale = 0.5; + /** * @type {Object.} */ @@ -323,7 +368,7 @@ export class ApplicationSettings extends ReadWriteProxy { * @returns {SettingsStorage} */ getAllSettings() { - return this.getCurrentData().settings; + return this.currentData.settings; } /** @@ -411,7 +456,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) { @@ -471,7 +516,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(); @@ -485,7 +540,7 @@ export class ApplicationSettings extends ReadWriteProxy { } getCurrentVersion() { - return 19; + return 31; } /** @param {{settings: SettingsStorage, version: number}} data */ @@ -564,9 +619,78 @@ export class ApplicationSettings extends ReadWriteProxy { } 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; + } + + if (data.version < 27) { + data.settings.simplifiedBelts = false; + data.version = 27; + } + + if (data.version < 28) { + data.settings.enableMousePan = true; + data.version = 28; + } + + if (data.version < 29) { + data.settings.zoomToCursor = true; + data.version = 29; + } + + if (data.version < 30) { + data.settings.mapResourcesScale = 0.5; + + // Re-enable hints as well + data.settings.offerHints = true; + + data.version = 30; + } + + if (data.version < 31) { data.settings.middleMousePan = false; data.settings.canDeleteWhileBuilding = false; - data.version = 19; + data.version = 31; } return ExplainedResult.good(); diff --git a/src/js/profile/setting_types.js b/src/js/profile/setting_types.js index 1255f961..4df02892 100644 --- a/src/js/profile/setting_types.js +++ b/src/js/profile/setting_types.js @@ -7,19 +7,30 @@ import { T } from "../translations"; const logger = createLogger("setting_types"); +/* + * *************************************************** + * + * LEGACY CODE WARNING + * + * This is old code from yorg3.io and needs to be refactored + * @TODO + * + * *************************************************** + */ + export class BaseSetting { /** * * @param {string} id * @param {string} categoryId * @param {function(Application, any):void} changeCb - * @param {boolean} enabled + * @param {function(Application) : boolean=} enabledCb */ - constructor(id, categoryId, changeCb, enabled) { + constructor(id, categoryId, changeCb, enabledCb = null) { this.id = id; this.categoryId = categoryId; this.changeCb = changeCb; - this.enabled = enabled; + this.enabledCb = enabledCb; /** @type {Application} */ this.app = null; @@ -39,8 +50,9 @@ export class BaseSetting { } /** + * Binds all parameters * @param {Application} app - * @param {Element} element + * @param {HTMLElement} element * @param {any} dialogs */ bind(app, element, dialogs) { @@ -49,19 +61,37 @@ export class BaseSetting { this.dialogs = dialogs; } - getHtml() { + /** + * Returns the HTML for this setting + * @param {Application} app + */ + getHtml(app) { abstract; return ""; } + /** + * Returns whether this setting is enabled and available + * @param {Application} app + */ + getIsAvailable(app) { + return this.enabledCb ? this.enabledCb(app) : true; + } + syncValueToElement() { abstract; } + /** + * Attempts to modify the setting + */ modify() { abstract; } + /** + * Shows the dialog that a restart is required + */ showRestartRequiredDialog() { const { restart } = this.dialogs.showInfo( T.dialogs.restartRequired.title, @@ -74,6 +104,7 @@ export class BaseSetting { } /** + * Validates the set value * @param {any} value * @returns {boolean} */ @@ -96,10 +127,10 @@ export class EnumSetting extends BaseSetting { iconPrefix = null, changeCb = null, magicValue = null, - enabled = true, + enabledCb = null, } ) { - super(id, category, changeCb, enabled); + super(id, category, changeCb, enabledCb); this.options = options; this.valueGetter = valueGetter; @@ -110,10 +141,14 @@ export class EnumSetting extends BaseSetting { this.magicValue = magicValue; } - getHtml() { + /** + * @param {Application} app + */ + getHtml(app) { + const available = this.getIsAvailable(app); return ` -
- ${this.enabled ? "" : `${T.demo.settingNotAvailable}`} +
+ ${available ? "" : `${T.demo.settingNotAvailable}`}
@@ -180,15 +215,19 @@ export class EnumSetting extends BaseSetting { } export class BoolSetting extends BaseSetting { - constructor(id, category, changeCb = null, enabled = true) { - super(id, category, changeCb, enabled); + constructor(id, category, changeCb = null, enabledCb = null) { + super(id, category, changeCb, enabledCb); } - getHtml() { + /** + * @param {Application} app + */ + getHtml(app) { + const available = this.getIsAvailable(app); return ` -
- ${this.enabled ? "" : `${T.demo.settingNotAvailable}`} - +
+ ${available ? "" : `${T.demo.settingNotAvailable}`} +
@@ -220,3 +259,107 @@ export class BoolSetting extends BaseSetting { return typeof value === "boolean"; } } + +export class RangeSetting extends BaseSetting { + constructor( + id, + category, + changeCb = null, + defaultValue = 1.0, + minValue = 0, + maxValue = 1.0, + stepSize = 0.0001, + enabledCb = null + ) { + super(id, category, changeCb, enabledCb); + + this.defaultValue = defaultValue; + this.minValue = minValue; + this.maxValue = maxValue; + this.stepSize = stepSize; + } + + /** + * @param {Application} app + */ + getHtml(app) { + const available = this.getIsAvailable(app); + return ` +
+ ${available ? "" : `${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..0ad630f6 100644 --- a/src/js/savegame/savegame.js +++ b/src/js/savegame/savegame.js @@ -1,269 +1,279 @@ -/* 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"; -import { BaseSavegameInterface } from "./savegame_interface"; -import { createLogger } from "../core/logging"; -import { globalConfig } from "../core/config"; -import { getSavegameInterface, savegameInterfaces } from "./savegame_interface_registry"; -import { SavegameInterface_V1001 } from "./schemas/1001"; -import { SavegameInterface_V1002 } from "./schemas/1002"; -import { SavegameInterface_V1003 } from "./schemas/1003"; -import { SavegameInterface_V1004 } from "./schemas/1004"; -import { SavegameInterface_V1005 } from "./schemas/1005"; - -const logger = createLogger("savegame"); - -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 - */ - constructor(app, { internalId, metaDataRef }) { - super(app, "savegame-" + internalId + ".bin"); - this.internalId = internalId; - this.metaDataRef = metaDataRef; - - /** @type {import("./savegame_typedefs").SavegameData} */ - this.currentData = this.getDefaultData(); - - assert( - savegameInterfaces[Savegame.getCurrentVersion()], - "Savegame interface not defined: " + Savegame.getCurrentVersion() - ); - } - - //////// RW Proxy Impl ////////// - - /** - * @returns {number} - */ - static getCurrentVersion() { - return 1005; - } - - /** - * @returns {typeof BaseSavegameInterface} - */ - static getReaderClass() { - return savegameInterfaces[Savegame.getCurrentVersion()]; - } - - /** - * @returns {number} - */ - getCurrentVersion() { - return /** @type {typeof Savegame} */ (this.constructor).getCurrentVersion(); - } - - /** - * Returns the savegames default data - * @returns {import("./savegame_typedefs").SavegameData} - */ - getDefaultData() { - return { - version: this.getCurrentVersion(), - dump: null, - stats: {}, - lastUpdate: Date.now(), - }; - } - - /** - * Migrates the savegames data - * @param {import("./savegame_typedefs").SavegameData} data - */ - migrate(data) { - if (data.version < 1000) { - return ExplainedResult.bad("Can not migrate savegame, too old"); - } - - if (data.version === 1000) { - SavegameInterface_V1001.migrate1000to1001(data); - data.version = 1001; - } - - if (data.version === 1001) { - SavegameInterface_V1002.migrate1001to1002(data); - data.version = 1002; - } - - if (data.version === 1002) { - SavegameInterface_V1003.migrate1002to1003(data); - data.version = 1003; - } - - if (data.version === 1003) { - SavegameInterface_V1004.migrate1003to1004(data); - data.version = 1004; - } - - if (data.version === 1004) { - SavegameInterface_V1005.migrate1004to1005(data); - data.version = 1005; - } - - return ExplainedResult.good(); - } - - /** - * Verifies the savegames data - * @param {import("./savegame_typedefs").SavegameData} data - */ - verify(data) { - if (!data.dump) { - // Well, guess that works - return ExplainedResult.good(); - } - - if (!this.getDumpReaderForExternalData(data).validate()) { - return ExplainedResult.bad("dump-reader-failed-validation"); - } - return ExplainedResult.good(); - } - - //////// Subclasses interface //////// - - /** - * Returns if this game can be saved on disc - * @returns {boolean} - */ - isSaveable() { - return true; - } - /** - * Returns the statistics of the savegame - * @returns {import("./savegame_typedefs").SavegameStats} - */ - getStatistics() { - return this.currentData.stats; - } - - /** - * Returns the *real* last update of the savegame, not the one of the metadata - * which could also be the servers one - */ - getRealLastUpdate() { - return this.currentData.lastUpdate; - } - - /** - * Returns if this game has a serialized game dump - */ - hasGameDump() { - return !!this.currentData.dump && this.currentData.dump.entities.length > 0; - } - - /** - * Returns the current game dump - * @returns {import("./savegame_typedefs").SerializedGame} - */ - getCurrentDump() { - return this.currentData.dump; - } - - /** - * Returns a reader to access the data - * @returns {BaseSavegameInterface} - */ - getDumpReader() { - if (!this.currentData.dump) { - logger.warn("Getting reader on null-savegame dump"); - } - - const cls = /** @type {typeof Savegame} */ (this.constructor).getReaderClass(); - return new cls(this.currentData); - } - - /** - * Returns a reader to access external data - * @returns {BaseSavegameInterface} - */ - getDumpReaderForExternalData(data) { - assert(data.version, "External data contains no version"); - return getSavegameInterface(data); - } - - ///////// Public Interface /////////// - - /** - * Updates the last update field so we can send the savegame to the server, - * WITHOUT Saving! - */ - setLastUpdate(time) { - this.currentData.lastUpdate = time; - } - - /** - * - * @param {GameRoot} root - */ - updateData(root) { - // Construct a new serializer - const serializer = new SavegameSerializer(); - - // let timer = performance.now(); - const dump = serializer.generateDumpFromGameRoot(root); - if (!dump) { - return false; - } - - const shadowData = Object.assign({}, this.currentData); - shadowData.dump = dump; - shadowData.lastUpdate = new Date().getTime(); - shadowData.version = this.getCurrentVersion(); - - const reader = this.getDumpReaderForExternalData(shadowData); - - // Validate (not in prod though) - if (!G_IS_RELEASE) { - const validationResult = reader.validate(); - if (!validationResult) { - return false; - } - } - - // Save data - this.currentData = shadowData; - } - - /** - * Writes the savegame as well as its metadata - */ - writeSavegameAndMetadata() { - return this.writeAsync().then(() => this.saveMetadata()); - } - - /** - * Updates the savegames metadata - */ - saveMetadata() { - this.metaDataRef.lastUpdate = new Date().getTime(); - this.metaDataRef.version = this.getCurrentVersion(); - if (!this.hasGameDump()) { - this.metaDataRef.level = 0; - } else { - this.metaDataRef.level = this.currentData.dump.hubGoals.level; - } - - return this.app.savegameMgr.writeAsync(); - } - - /** - * @see ReadWriteProxy.writeAsync - * @returns {Promise} - */ - writeAsync() { - if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) { - return Promise.resolve(); - } - return super.writeAsync(); - } -} +import { ReadWriteProxy } from "../core/read_write_proxy"; +import { ExplainedResult } from "../core/explained_result"; +import { SavegameSerializer } from "./savegame_serializer"; +import { BaseSavegameInterface } from "./savegame_interface"; +import { createLogger } from "../core/logging"; +import { globalConfig } from "../core/config"; +import { getSavegameInterface, savegameInterfaces } from "./savegame_interface_registry"; +import { SavegameInterface_V1001 } from "./schemas/1001"; +import { SavegameInterface_V1002 } from "./schemas/1002"; +import { SavegameInterface_V1003 } from "./schemas/1003"; +import { SavegameInterface_V1004 } from "./schemas/1004"; +import { SavegameInterface_V1005 } from "./schemas/1005"; +import { SavegameInterface_V1006 } from "./schemas/1006"; + +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 {SavegameMetadata} param0.metaDataRef Handle to the meta data + */ + constructor(app, { internalId, metaDataRef }) { + super(app, "savegame-" + internalId + ".bin"); + this.internalId = internalId; + this.metaDataRef = metaDataRef; + + /** @type {SavegameData} */ + this.currentData = this.getDefaultData(); + + assert( + savegameInterfaces[Savegame.getCurrentVersion()], + "Savegame interface not defined: " + Savegame.getCurrentVersion() + ); + } + + //////// RW Proxy Impl ////////// + + /** + * @returns {number} + */ + static getCurrentVersion() { + return 1006; + } + + /** + * @returns {typeof BaseSavegameInterface} + */ + static getReaderClass() { + return savegameInterfaces[Savegame.getCurrentVersion()]; + } + + /** + * @returns {number} + */ + getCurrentVersion() { + return /** @type {typeof Savegame} */ (this.constructor).getCurrentVersion(); + } + + /** + * Returns the savegames default data + * @returns {SavegameData} + */ + getDefaultData() { + return { + version: this.getCurrentVersion(), + dump: null, + stats: {}, + lastUpdate: Date.now(), + }; + } + + /** + * Migrates the savegames data + * @param {SavegameData} data + */ + migrate(data) { + if (data.version < 1000) { + return ExplainedResult.bad("Can not migrate savegame, too old"); + } + + if (data.version === 1000) { + SavegameInterface_V1001.migrate1000to1001(data); + data.version = 1001; + } + + if (data.version === 1001) { + SavegameInterface_V1002.migrate1001to1002(data); + data.version = 1002; + } + + if (data.version === 1002) { + SavegameInterface_V1003.migrate1002to1003(data); + data.version = 1003; + } + + if (data.version === 1003) { + SavegameInterface_V1004.migrate1003to1004(data); + data.version = 1004; + } + + if (data.version === 1004) { + SavegameInterface_V1005.migrate1004to1005(data); + data.version = 1005; + } + + if (data.version === 1005) { + SavegameInterface_V1006.migrate1005to1006(data); + data.version = 1006; + } + + return ExplainedResult.good(); + } + + /** + * Verifies the savegames data + * @param {SavegameData} data + */ + verify(data) { + if (!data.dump) { + // Well, guess that works + return ExplainedResult.good(); + } + + if (!this.getDumpReaderForExternalData(data).validate()) { + return ExplainedResult.bad("dump-reader-failed-validation"); + } + return ExplainedResult.good(); + } + + //////// Subclasses interface //////// + + /** + * Returns if this game can be saved on disc + * @returns {boolean} + */ + isSaveable() { + return true; + } + /** + * Returns the statistics of the savegame + * @returns {SavegameStats} + */ + getStatistics() { + return this.currentData.stats; + } + + /** + * Returns the *real* last update of the savegame, not the one of the metadata + * which could also be the servers one + */ + getRealLastUpdate() { + return this.currentData.lastUpdate; + } + + /** + * Returns if this game has a serialized game dump + */ + hasGameDump() { + return !!this.currentData.dump && this.currentData.dump.entities.length > 0; + } + + /** + * Returns the current game dump + * @returns {SerializedGame} + */ + getCurrentDump() { + return this.currentData.dump; + } + + /** + * Returns a reader to access the data + * @returns {BaseSavegameInterface} + */ + getDumpReader() { + if (!this.currentData.dump) { + logger.warn("Getting reader on null-savegame dump"); + } + + const cls = /** @type {typeof Savegame} */ (this.constructor).getReaderClass(); + return new cls(this.currentData); + } + + /** + * Returns a reader to access external data + * @returns {BaseSavegameInterface} + */ + getDumpReaderForExternalData(data) { + assert(data.version, "External data contains no version"); + return getSavegameInterface(data); + } + + ///////// Public Interface /////////// + + /** + * Updates the last update field so we can send the savegame to the server, + * WITHOUT Saving! + */ + setLastUpdate(time) { + this.currentData.lastUpdate = time; + } + + /** + * + * @param {GameRoot} root + */ + updateData(root) { + // Construct a new serializer + const serializer = new SavegameSerializer(); + + // let timer = performance.now(); + const dump = serializer.generateDumpFromGameRoot(root); + if (!dump) { + return false; + } + + const shadowData = Object.assign({}, this.currentData); + shadowData.dump = dump; + shadowData.lastUpdate = new Date().getTime(); + shadowData.version = this.getCurrentVersion(); + + const reader = this.getDumpReaderForExternalData(shadowData); + + // Validate (not in prod though) + if (!G_IS_RELEASE) { + const validationResult = reader.validate(); + if (!validationResult) { + return false; + } + } + + // Save data + this.currentData = shadowData; + } + + /** + * Writes the savegame as well as its metadata + */ + writeSavegameAndMetadata() { + return this.writeAsync().then(() => this.saveMetadata()); + } + + /** + * Updates the savegames metadata + */ + saveMetadata() { + this.metaDataRef.lastUpdate = new Date().getTime(); + this.metaDataRef.version = this.getCurrentVersion(); + if (!this.hasGameDump()) { + this.metaDataRef.level = 0; + } else { + this.metaDataRef.level = this.currentData.dump.hubGoals.level; + } + + return this.app.savegameMgr.writeAsync(); + } + + /** + * @see ReadWriteProxy.writeAsync + * @returns {Promise} + */ + writeAsync() { + if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) { + return Promise.resolve(); + } + return super.writeAsync(); + } +} 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_interface_registry.js b/src/js/savegame/savegame_interface_registry.js index fb1df52f..07b5353c 100644 --- a/src/js/savegame/savegame_interface_registry.js +++ b/src/js/savegame/savegame_interface_registry.js @@ -1,45 +1,47 @@ -import { BaseSavegameInterface } from "./savegame_interface"; -import { SavegameInterface_V1000 } from "./schemas/1000"; -import { createLogger } from "../core/logging"; -import { SavegameInterface_V1001 } from "./schemas/1001"; -import { SavegameInterface_V1002 } from "./schemas/1002"; -import { SavegameInterface_V1003 } from "./schemas/1003"; -import { SavegameInterface_V1004 } from "./schemas/1004"; -import { SavegameInterface_V1005 } from "./schemas/1005"; - -/** @type {Object.} */ -export const savegameInterfaces = { - 1000: SavegameInterface_V1000, - 1001: SavegameInterface_V1001, - 1002: SavegameInterface_V1002, - 1003: SavegameInterface_V1003, - 1004: SavegameInterface_V1004, - 1005: SavegameInterface_V1005, -}; - -const logger = createLogger("savegame_interface_registry"); - -/** - * Returns if the given savegame has any supported interface - * @param {any} savegame - * @returns {BaseSavegameInterface|null} - */ -export function getSavegameInterface(savegame) { - if (!savegame || !savegame.version) { - logger.warn("Savegame does not contain a valid version (undefined)"); - return null; - } - const version = savegame.version; - if (!Number.isInteger(version)) { - logger.warn("Savegame does not contain a valid version (non-integer):", version); - return null; - } - - const interfaceClass = savegameInterfaces[version]; - if (!interfaceClass) { - logger.warn("Version", version, "has no implemented interface!"); - return null; - } - - return new interfaceClass(savegame); -} +import { BaseSavegameInterface } from "./savegame_interface"; +import { SavegameInterface_V1000 } from "./schemas/1000"; +import { createLogger } from "../core/logging"; +import { SavegameInterface_V1001 } from "./schemas/1001"; +import { SavegameInterface_V1002 } from "./schemas/1002"; +import { SavegameInterface_V1003 } from "./schemas/1003"; +import { SavegameInterface_V1004 } from "./schemas/1004"; +import { SavegameInterface_V1005 } from "./schemas/1005"; +import { SavegameInterface_V1006 } from "./schemas/1006"; + +/** @type {Object.} */ +export const savegameInterfaces = { + 1000: SavegameInterface_V1000, + 1001: SavegameInterface_V1001, + 1002: SavegameInterface_V1002, + 1003: SavegameInterface_V1003, + 1004: SavegameInterface_V1004, + 1005: SavegameInterface_V1005, + 1006: SavegameInterface_V1006, +}; + +const logger = createLogger("savegame_interface_registry"); + +/** + * Returns if the given savegame has any supported interface + * @param {any} savegame + * @returns {BaseSavegameInterface|null} + */ +export function getSavegameInterface(savegame) { + if (!savegame || !savegame.version) { + logger.warn("Savegame does not contain a valid version (undefined)"); + return null; + } + const version = savegame.version; + if (!Number.isInteger(version)) { + logger.warn("Savegame does not contain a valid version (non-integer):", version); + return null; + } + + const interfaceClass = savegameInterfaces[version]; + if (!interfaceClass) { + logger.warn("Version", version, "has no implemented interface!"); + return null; + } + + return new interfaceClass(savegame); +} diff --git a/src/js/savegame/savegame_manager.js b/src/js/savegame/savegame_manager.js index e3052806..eb0d53d0 100644 --- a/src/js/savegame/savegame_manager.js +++ b/src/js/savegame/savegame_manager.js @@ -1,228 +1,248 @@ -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; + } + + verify(data) { + // @TODO + 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 }); + } + + /** + * Returns if this manager has any savegame of a 1.1.19 version, which + * enables all levels + */ + getHasAnyLegacySavegames() { + return this.currentData.savegames.some(savegame => savegame.version === 1005 || savegame.level > 14); + } + + /** + * 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); + + // Notice: This is async and happening in the background + this.updateAfterSavegamesChanged(); + + return new Savegame(this.app, { + internalId: id, + metaDataRef: metaData, + }); + } + + /** + * Attempts to import a savegame + * @param {object} data + */ + importSavegame(data) { + const savegame = this.createNewSavegame(); + + // Track legacy savegames + const isOldSavegame = data.version < 1006; + + 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.updateAfterSavegamesChanged()) + .then(() => this.app.restrictionMgr.onHasLegacySavegamesChanged(isOldSavegame)); + } + + /** + * Hook after the savegames got changed + */ + updateAfterSavegamesChanged() { + return this.sortSavegames() + .then(() => this.writeAsync()) + .then(() => this.app.restrictionMgr.onHasLegacySavegamesChanged(this.getHasAnyLegacySavegames())); + } + + /** + * 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.updateAfterSavegamesChanged(); + }); + } +} diff --git a/src/js/savegame/savegame_serializer.js b/src/js/savegame/savegame_serializer.js index eff802a0..c1247225 100644 --- a/src/js/savegame/savegame_serializer.js +++ b/src/js/savegame/savegame_serializer.js @@ -1,148 +1,146 @@ -/* 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"; - -const logger = createLogger("savegame_serializer"); - -/** - * Allows to serialize a savegame - */ -export class SavegameSerializer { - constructor() { - this.internal = new SerializerInternal(); - } - - /** - * Serializes the game root into a dump - * @param {GameRoot} root - * @param {boolean=} sanityChecks Whether to check for validity - * @returns {object} - */ - generateDumpFromGameRoot(root, sanityChecks = true) { - // Now store generic savegame payload - const data = { - camera: root.camera.serialize(), - time: root.time.serialize(), - map: root.map.serialize(), - entityMgr: root.entityMgr.serialize(), - hubGoals: root.hubGoals.serialize(), - pinnedShapes: root.hud.parts.pinnedShapes.serialize(), - waypoints: root.hud.parts.waypoints.serialize(), - beltPaths: root.systemMgr.systems.belt.serializePaths(), - }; - - data.entities = this.internal.serializeEntityArray(root.entityMgr.entities); - - if (!G_IS_RELEASE) { - if (sanityChecks) { - // Sanity check - const sanity = this.verifyLogicalErrors(data); - if (!sanity.result) { - logger.error("Created invalid savegame:", sanity.reason, "savegame:", data); - return null; - } - } - } - return data; - } - - /** - * Verifies if there are logical errors in the savegame - * @param {object} savegame - * @returns {ExplainedResult} - */ - verifyLogicalErrors(savegame) { - if (!savegame.entities) { - return ExplainedResult.bad("Savegame has no entities"); - } - - 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); - - // 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); - - // Check component id is known - if (!componentClass) { - return ExplainedResult.bad("Unknown component id: " + componentId); - } - - // Check component data is ok - const componentVerifyError = /** @type {typeof Component} */ (componentClass).verify( - componentData - ); - if (componentVerifyError) { - return ExplainedResult.bad( - "Component " + componentId + " has invalid data: " + componentVerifyError - ); - } - } - } - } - } - - return ExplainedResult.good(); - } - - /** - * Tries to load the savegame from a given dump - * @param {import("./savegame_typedefs").SerializedGame} savegame - * @param {GameRoot} root - * @returns {ExplainedResult} - */ - deserialize(savegame, root) { - // Sanity - const verifyResult = this.verifyLogicalErrors(savegame); - if (!verifyResult.result) { - return ExplainedResult.bad(verifyResult.reason); - } - let errorReason = null; - - errorReason = errorReason || root.entityMgr.deserialize(savegame.entityMgr); - errorReason = errorReason || root.time.deserialize(savegame.time); - errorReason = errorReason || root.camera.deserialize(savegame.camera); - errorReason = errorReason || root.map.deserialize(savegame.map); - errorReason = errorReason || root.hubGoals.deserialize(savegame.hubGoals); - errorReason = errorReason || root.hud.parts.pinnedShapes.deserialize(savegame.pinnedShapes); - errorReason = errorReason || root.hud.parts.waypoints.deserialize(savegame.waypoints); - errorReason = errorReason || this.internal.deserializeEntityArray(root, savegame.entities); - errorReason = errorReason || root.systemMgr.systems.belt.deserializePaths(savegame.beltPaths); - - // Check for errors - if (errorReason) { - return ExplainedResult.bad(errorReason); - } - - return ExplainedResult.good(); - } -} +import { ExplainedResult } from "../core/explained_result"; +import { createLogger } from "../core/logging"; +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"); + +/** + * Serializes a savegame + */ +export class SavegameSerializer { + constructor() { + this.internal = new SerializerInternal(); + } + + /** + * Serializes the game root into a dump + * @param {GameRoot} root + * @param {boolean=} sanityChecks Whether to check for validity + * @returns {object} + */ + generateDumpFromGameRoot(root, sanityChecks = true) { + /** @type {SerializedGame} */ + const data = { + camera: root.camera.serialize(), + time: root.time.serialize(), + map: root.map.serialize(), + entityMgr: root.entityMgr.serialize(), + 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(), + }; + + if (G_IS_DEV) { + if (sanityChecks) { + // Sanity check + const sanity = this.verifyLogicalErrors(data); + if (!sanity.result) { + logger.error("Created invalid savegame:", sanity.reason, "savegame:", data); + return null; + } + } + } + return data; + } + + /** + * Verifies if there are logical errors in the savegame + * @param {SerializedGame} savegame + * @returns {ExplainedResult} + */ + verifyLogicalErrors(savegame) { + if (!savegame.entities) { + return ExplainedResult.bad("Savegame has no entities"); + } + + const seenUids = new Set(); + + // Check for duplicate UIDS + for (let i = 0; i < savegame.entities.length; ++i) { + /** @type {Entity} */ + const entity = savegame.entities[i]; + + const uid = entity.uid; + if (!Number.isInteger(uid)) { + return ExplainedResult.bad("Entity has invalid uid: " + uid); + } + if (seenUids.has(uid)) { + return ExplainedResult.bad("Duplicate uid " + uid); + } + seenUids.add(uid); + + // 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) { + 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 + ); + } + } + } + + return ExplainedResult.good(); + } + + /** + * Tries to load the savegame from a given dump + * @param {SerializedGame} savegame + * @param {GameRoot} root + * @returns {ExplainedResult} + */ + deserialize(savegame, root) { + // Sanity + const verifyResult = this.verifyLogicalErrors(savegame); + if (!verifyResult.result) { + return ExplainedResult.bad(verifyResult.reason); + } + let errorReason = null; + + errorReason = errorReason || root.entityMgr.deserialize(savegame.entityMgr); + errorReason = errorReason || root.time.deserialize(savegame.time); + errorReason = errorReason || root.camera.deserialize(savegame.camera); + errorReason = errorReason || root.map.deserialize(savegame.map); + errorReason = errorReason || root.hubGoals.deserialize(savegame.hubGoals, root); + errorReason = errorReason || root.hud.parts.pinnedShapes.deserialize(savegame.pinnedShapes); + errorReason = errorReason || root.hud.parts.waypoints.deserialize(savegame.waypoints); + errorReason = errorReason || this.internal.deserializeEntityArray(root, savegame.entities); + errorReason = errorReason || root.systemMgr.systems.belt.deserializePaths(savegame.beltPaths); + + // Check for errors + if (errorReason) { + return ExplainedResult.bad(errorReason); + } + + return ExplainedResult.good(); + } +} 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/schemas/1006.js b/src/js/savegame/schemas/1006.js new file mode 100644 index 00000000..79226772 --- /dev/null +++ b/src/js/savegame/schemas/1006.js @@ -0,0 +1,304 @@ +import { gMetaBuildingRegistry } from "../../core/global_registries.js"; +import { createLogger } from "../../core/logging.js"; +import { enumBalancerVariants, MetaBalancerBuilding } from "../../game/buildings/balancer.js"; +import { MetaBeltBuilding } from "../../game/buildings/belt.js"; +import { enumCutterVariants, MetaCutterBuilding } from "../../game/buildings/cutter.js"; +import { MetaHubBuilding } from "../../game/buildings/hub.js"; +import { enumMinerVariants, MetaMinerBuilding } from "../../game/buildings/miner.js"; +import { MetaMixerBuilding } from "../../game/buildings/mixer.js"; +import { enumPainterVariants, MetaPainterBuilding } from "../../game/buildings/painter.js"; +import { enumRotaterVariants, MetaRotaterBuilding } from "../../game/buildings/rotater.js"; +import { MetaStackerBuilding } from "../../game/buildings/stacker.js"; +import { MetaStorageBuilding } from "../../game/buildings/storage.js"; +import { MetaTrashBuilding } from "../../game/buildings/trash.js"; +import { + enumUndergroundBeltVariants, + MetaUndergroundBeltBuilding, +} from "../../game/buildings/underground_belt.js"; +import { getCodeFromBuildingData } from "../../game/building_codes.js"; +import { StaticMapEntityComponent } from "../../game/components/static_map_entity.js"; +import { Entity } from "../../game/entity.js"; +import { defaultBuildingVariant, MetaBuilding } from "../../game/meta_building.js"; +import { SavegameInterface_V1005 } from "./1005.js"; + +const schema = require("./1006.json"); +const logger = createLogger("savegame_interface/1006"); + +/** + * + * @param {typeof MetaBuilding} metaBuilding + * @param {string=} variant + * @param {number=} rotationVariant + */ +function findCode(metaBuilding, variant = defaultBuildingVariant, rotationVariant = 0) { + return getCodeFromBuildingData(gMetaBuildingRegistry.findByClass(metaBuilding), variant, rotationVariant); +} + +/** + * Rebalances a value from the old balancing to the new one + * @param {number} value + * @returns {number} + */ +function rebalance(value) { + return Math.round(Math.pow(value, 0.75)); +} + +export class SavegameInterface_V1006 extends SavegameInterface_V1005 { + getVersion() { + return 1006; + } + + getSchemaUncached() { + return schema; + } + + static computeSpriteMapping() { + return { + // Belt + "sprites/blueprints/belt_top.png": findCode(MetaBeltBuilding, defaultBuildingVariant, 0), + "sprites/blueprints/belt_left.png": findCode(MetaBeltBuilding, defaultBuildingVariant, 1), + "sprites/blueprints/belt_right.png": findCode(MetaBeltBuilding, defaultBuildingVariant, 2), + + // Splitter (=Balancer) + "sprites/blueprints/splitter.png": findCode(MetaBalancerBuilding), + "sprites/blueprints/splitter-compact.png": findCode( + MetaBalancerBuilding, + enumBalancerVariants.merger + ), + "sprites/blueprints/splitter-compact-inverse.png": findCode( + MetaBalancerBuilding, + enumBalancerVariants.mergerInverse + ), + + // Underground belt + "sprites/blueprints/underground_belt_entry.png": findCode( + MetaUndergroundBeltBuilding, + defaultBuildingVariant, + 0 + ), + "sprites/blueprints/underground_belt_exit.png": findCode( + MetaUndergroundBeltBuilding, + defaultBuildingVariant, + 1 + ), + + "sprites/blueprints/underground_belt_entry-tier2.png": findCode( + MetaUndergroundBeltBuilding, + enumUndergroundBeltVariants.tier2, + 0 + ), + "sprites/blueprints/underground_belt_exit-tier2.png": findCode( + MetaUndergroundBeltBuilding, + enumUndergroundBeltVariants.tier2, + 1 + ), + + // Miner + "sprites/blueprints/miner.png": findCode(MetaMinerBuilding), + "sprites/blueprints/miner-chainable.png": findCode( + MetaMinerBuilding, + enumMinerVariants.chainable, + 0 + ), + + // Cutter + "sprites/blueprints/cutter.png": findCode(MetaCutterBuilding), + "sprites/blueprints/cutter-quad.png": findCode(MetaCutterBuilding, enumCutterVariants.quad), + + // Rotater + "sprites/blueprints/rotater.png": findCode(MetaRotaterBuilding), + "sprites/blueprints/rotater-ccw.png": findCode(MetaRotaterBuilding, enumRotaterVariants.ccw), + + // Stacker + "sprites/blueprints/stacker.png": findCode(MetaStackerBuilding), + + // Mixer + "sprites/blueprints/mixer.png": findCode(MetaMixerBuilding), + + // Painter + "sprites/blueprints/painter.png": findCode(MetaPainterBuilding), + "sprites/blueprints/painter-mirrored.png": findCode( + MetaPainterBuilding, + enumPainterVariants.mirrored + ), + "sprites/blueprints/painter-double.png": findCode( + MetaPainterBuilding, + enumPainterVariants.double + ), + "sprites/blueprints/painter-quad.png": findCode(MetaPainterBuilding, enumPainterVariants.quad), + + // Trash + "sprites/blueprints/trash.png": findCode(MetaTrashBuilding), + + // Storage + "sprites/blueprints/trash-storage.png": findCode(MetaStorageBuilding), + }; + } + + /** + * @param {import("../savegame_typedefs.js").SavegameData} data + */ + static migrate1005to1006(data) { + logger.log("Migrating 1005 to 1006"); + const dump = data.dump; + if (!dump) { + return true; + } + + // Reduce stored shapes + const stored = dump.hubGoals.storedShapes; + for (const shapeKey in stored) { + stored[shapeKey] = rebalance(stored[shapeKey]); + } + + // Reset final game shape + stored["RuCw--Cw:----Ru--"] = 0; + + // Reduce goals + if (dump.hubGoals.currentGoal) { + dump.hubGoals.currentGoal.required = rebalance(dump.hubGoals.currentGoal.required); + } + + let level = Math.min(19, dump.hubGoals.level); + + const levelMapping = { + 14: 15, + 15: 16, + 16: 17, + 17: 18, + 18: 19, + 19: 20, + }; + + dump.hubGoals.level = levelMapping[level] || level; + + // Update entities + const entities = dump.entities; + for (let i = 0; i < entities.length; ++i) { + const entity = entities[i]; + const components = entity.components; + this.migrateStaticComp1005to1006(entity); + + // HUB + if (components.Hub) { + // @ts-ignore + components.Hub = {}; + } + + // Item Processor + if (components.ItemProcessor) { + // @ts-ignore + components.ItemProcessor = { + nextOutputSlot: 0, + }; + } + + // OLD: Unremovable component + // @ts-ignore + if (components.Unremovable) { + // @ts-ignore + delete components.Unremovable; + } + + // OLD: ReplaceableMapEntity + // @ts-ignore + if (components.ReplaceableMapEntity) { + // @ts-ignore + delete components.ReplaceableMapEntity; + } + + // ItemAcceptor + if (components.ItemAcceptor) { + // @ts-ignore + components.ItemAcceptor = {}; + } + + // Belt + if (components.Belt) { + // @ts-ignore + components.Belt = {}; + } + + // Item Ejector + if (components.ItemEjector) { + // @ts-ignore + components.ItemEjector = { + slots: [], + }; + } + + // UndergroundBelt + if (components.UndergroundBelt) { + // @ts-ignore + components.UndergroundBelt = { + pendingItems: [], + }; + } + + // Miner + if (components.Miner) { + // @ts-ignore + delete components.Miner.chainable; + + components.Miner.lastMiningTime = 0; + components.Miner.itemChainBuffer = []; + } + + // Storage + if (components.Storage) { + // @ts-ignore + components.Storage = { + storedCount: rebalance(components.Storage.storedCount), + storedItem: null, + }; + } + } + } + + /** + * + * @param {Entity} entity + */ + static migrateStaticComp1005to1006(entity) { + const spriteMapping = this.computeSpriteMapping(); + const staticComp = entity.components.StaticMapEntity; + + /** @type {StaticMapEntityComponent} */ + const newStaticComp = {}; + newStaticComp.origin = staticComp.origin; + newStaticComp.originalRotation = staticComp.originalRotation; + newStaticComp.rotation = staticComp.rotation; + + // @ts-ignore + newStaticComp.code = spriteMapping[staticComp.blueprintSpriteKey]; + + // Hub special case + if (entity.components.Hub) { + newStaticComp.code = findCode(MetaHubBuilding); + } + + // Belt special case + if (entity.components.Belt) { + const actualCode = { + top: findCode(MetaBeltBuilding, defaultBuildingVariant, 0), + left: findCode(MetaBeltBuilding, defaultBuildingVariant, 1), + right: findCode(MetaBeltBuilding, defaultBuildingVariant, 2), + }[entity.components.Belt.direction]; + if (actualCode !== newStaticComp.code) { + if (G_IS_DEV) { + console.warn("Belt mismatch"); + } + newStaticComp.code = actualCode; + } + } + + if (!newStaticComp.code) { + throw new Error( + // @ts-ignore + "1006 Migration: Could not reconstruct code for " + staticComp.blueprintSpriteKey + ); + } + + entity.components.StaticMapEntity = newStaticComp; + } +} diff --git a/src/js/savegame/schemas/1006.json b/src/js/savegame/schemas/1006.json new file mode 100644 index 00000000..b0916986 --- /dev/null +++ b/src/js/savegame/schemas/1006.json @@ -0,0 +1,5 @@ +{ + "type": "object", + "required": [], + "additionalProperties": true +} diff --git a/src/js/savegame/serialization.js b/src/js/savegame/serialization.js index aea2f944..801b26ab 100644 --- a/src/js/savegame/serialization.js +++ b/src/js/savegame/serialization.js @@ -1,336 +1,351 @@ -import { - BaseDataType, - TypeArray, - TypeBoolean, - TypeClass, - TypeClassId, - TypeEntity, - TypeEntityWeakref, - TypeEnum, - TypeFixedClass, - TypeInteger, - TypeKeyValueMap, - TypeMetaClass, - TypeNullable, - TypeNumber, - TypePair, - TypePositiveInteger, - TypePositiveNumber, - TypeString, - TypeVector, - TypeClassFromMetaclass, - TypeClassData, - TypeStructuredObject, -} from "./serialization_data_types"; -import { createLogger } from "../core/logging"; - -const logger = createLogger("serialization"); - -// Schema declarations -export const types = { - int: new TypeInteger(), - uint: new TypePositiveInteger(), - float: new TypeNumber(), - ufloat: new TypePositiveNumber(), - string: new TypeString(), - entity: new TypeEntity(), - weakEntityRef: new TypeEntityWeakref(), - vector: new TypeVector(), - tileVector: new TypeVector(), - bool: new TypeBoolean(), - - /** - * @param {BaseDataType} wrapped - */ - nullable(wrapped) { - return new TypeNullable(wrapped); - }, - - /** - * @param {FactoryTemplate<*>|SingletonFactoryTemplate<*>} registry - */ - classId(registry) { - return new TypeClassId(registry); - }, - /** - * @param {BaseDataType} valueType - * @param {boolean=} includeEmptyValues - */ - keyValueMap(valueType, includeEmptyValues = true) { - return new TypeKeyValueMap(valueType, includeEmptyValues); - }, - - /** - * @param {Object} values - */ - enum(values) { - return new TypeEnum(values); - }, - - /** - * @param {FactoryTemplate<*>} registry - */ - obj(registry) { - return new TypeClass(registry); - }, - - /** - * @param {FactoryTemplate<*>} registry - */ - objData(registry) { - return new TypeClassData(registry); - }, - - /** - * @param {typeof BasicSerializableObject} cls - */ - knownType(cls) { - return new TypeFixedClass(cls); - }, - - /** - * @param {BaseDataType} innerType - */ - array(innerType) { - return new TypeArray(innerType); - }, - - /** - * @param {SingletonFactoryTemplate<*>} innerType - */ - classRef(registry) { - return new TypeMetaClass(registry); - }, - - /** - * @param {Object.} descriptor - */ - structured(descriptor) { - return new TypeStructuredObject(descriptor); - }, - - /** - * @param {BaseDataType} a - * @param {BaseDataType} b - */ - pair(a, b) { - return new TypePair(a, b); - }, - - /** - * @param {typeof BasicSerializableObject} classHandle - * @param {SingletonFactoryTemplate<*>} registry - */ - classWithMetaclass(classHandle, registry) { - return new TypeClassFromMetaclass(classHandle, registry); - }, -}; - -/** - * A full schema declaration - * @typedef {Object.} Schema - */ - -const globalSchemaCache = {}; - -/* dev:start */ -const classnamesCache = {}; -/* dev:end*/ - -export class BasicSerializableObject { - /* dev:start */ - /** - * Fixes typeof DerivedComponent is not assignable to typeof Component, compiled out - * in non-dev builds - */ - constructor(...args) {} - - /* dev:end */ - - static getId() { - abstract; - } - - /** - * Should return the serialization schema - * @returns {Schema} - */ - static getSchema() { - return {}; - } - - // Implementation - /** @returns {Schema} */ - static getCachedSchema() { - const id = this.getId(); - - /* dev:start */ - assert( - classnamesCache[id] === this || classnamesCache[id] === undefined, - "Class name taken twice: " + id + " (from " + this.name + ")" - ); - classnamesCache[id] = this; - /* dev:end */ - - const entry = globalSchemaCache[id]; - if (entry) { - return entry; - } - - const schema = this.getSchema(); - globalSchemaCache[id] = schema; - return schema; - } - - /** @returns {object} */ - serialize() { - return serializeSchema( - this, - /** @type {typeof BasicSerializableObject} */ (this.constructor).getCachedSchema() - ); - } - - /** @returns {string|void} */ - deserialize(data) { - return deserializeSchema( - this, - /** @type {typeof BasicSerializableObject} */ (this.constructor).getCachedSchema(), - data - ); - } - - /** @returns {string|void} */ - static verify(data) { - return verifySchema(this.getCachedSchema(), data); - } -} - -/** - * Serializes an object using the given schema, mergin with the given properties - * @param {object} obj The object to serialize - * @param {Schema} schema The schema to use - * @param {object=} mergeWith Any additional properties to merge with the schema, useful for super calls - * @returns {object} Serialized data object - */ -export function serializeSchema(obj, schema, mergeWith = {}) { - for (const key in schema) { - if (!obj.hasOwnProperty(key)) { - logger.error("Invalid schema, property", key, "does not exist on", obj, "(schema=", schema, ")"); - assert( - obj.hasOwnProperty(key), - "serialization: invalid schema, property does not exist on object: " + key - ); - } - if (!schema[key]) { - assert(false, "Invalid schema (bad key '" + key + "'): " + JSON.stringify(schema)); - } - - if (G_IS_DEV) { - try { - mergeWith[key] = schema[key].serialize(obj[key]); - } catch (ex) { - logger.error( - "Serialization of", - obj, - "failed on key '" + key + "' ->", - ex, - "(schema was", - schema, - ")" - ); - throw ex; - } - } else { - mergeWith[key] = schema[key].serialize(obj[key]); - } - } - return mergeWith; -} - -/** - * Deserializes data into an object - * @param {object} obj The object to store the deserialized data into - * @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 - * @returns {string|void} String error code or nothing on success - */ -export function deserializeSchema(obj, schema, data, baseclassErrorResult = null) { - if (baseclassErrorResult) { - return baseclassErrorResult; - } - - if (!data) { - logger.error("Got 'NULL' data for", obj, "and schema", schema, "!"); - return "Got null data"; - } - - for (const key in schema) { - if (!data.hasOwnProperty(key)) { - logger.error("Data", data, "does not contain", key, "(schema:", schema, ")"); - return "Missing key in schema: " + key + " of class " + obj.constructor.name; - } - if (!schema[key].allowNull() && (data[key] === null || data[key] === undefined)) { - logger.error("Data", data, "has null value for", key, "(schema:", schema, ")"); - return "Non-nullable entry is null: " + key + " of class " + obj.constructor.name; - } - - const errorStatus = schema[key].deserializeWithVerify(data[key], obj, key, obj.root); - if (errorStatus) { - logger.error( - "Deserialization failed with error '" + errorStatus + "' on object", - obj, - "and key", - key, - "(root? =", - obj.root ? "y" : "n", - ")" - ); - return errorStatus; - } - } -} - -/** - * Verifies stored data using the given schema - * @param {Schema} schema The schema to use - * @param {object} data The data to verify - * @returns {string|void} String error code or nothing on success - */ -export function verifySchema(schema, data) { - for (const key in schema) { - if (!data.hasOwnProperty(key)) { - logger.error("Data", data, "does not contain", key, "(schema:", schema, ")"); - return "verify: missing key required by schema in stored data: " + key; - } - if (!schema[key].allowNull() && (data[key] === null || data[key] === undefined)) { - logger.error("Data", data, "has null value for", key, "(schema:", schema, ")"); - return "verify: non-nullable entry is null: " + key; - } - - const errorStatus = schema[key].verifySerializedValue(data[key]); - if (errorStatus) { - logger.error(errorStatus); - return "verify: " + errorStatus; - } - } -} - -/** - * Extends a schema by adding the properties from the new schema to the existing base schema - * @param {Schema} base - * @param {Schema} newOne - * @returns {Schema} - */ -export function extendSchema(base, newOne) { - /** @type {Schema} */ - const result = Object.assign({}, base); - for (const key in newOne) { - if (result.hasOwnProperty(key)) { - logger.error("Extend schema got duplicate key:", key); - continue; - } - result[key] = newOne[key]; - } - return result; -} +import { createLogger } from "../core/logging"; +import { + BaseDataType, + TypeArray, + TypeBoolean, + TypeClass, + TypeClassData, + TypeClassFromMetaclass, + TypeClassId, + TypeEntity, + TypeEntityWeakref, + TypeEnum, + TypeFixedClass, + TypeInteger, + TypeKeyValueMap, + TypeMetaClass, + TypeNullable, + TypeNumber, + TypePair, + TypePositiveInteger, + TypePositiveNumber, + TypeString, + TypeStructuredObject, + TypeVector, +} from "./serialization_data_types"; + +const logger = createLogger("serialization"); + +// Schema declarations +export const types = { + int: new TypeInteger(), + uint: new TypePositiveInteger(), + float: new TypeNumber(), + ufloat: new TypePositiveNumber(), + string: new TypeString(), + entity: new TypeEntity(), + weakEntityRef: new TypeEntityWeakref(), + vector: new TypeVector(), + tileVector: new TypeVector(), + bool: new TypeBoolean(), + + /** + * @param {BaseDataType} wrapped + */ + nullable(wrapped) { + return new TypeNullable(wrapped); + }, + + /** + * @param {FactoryTemplate<*>|SingletonFactoryTemplate<*>} registry + */ + classId(registry) { + return new TypeClassId(registry); + }, + /** + * @param {BaseDataType} valueType + * @param {boolean=} includeEmptyValues + */ + keyValueMap(valueType, includeEmptyValues = true) { + return new TypeKeyValueMap(valueType, includeEmptyValues); + }, + + /** + * @param {Object} values + */ + enum(values) { + return new TypeEnum(values); + }, + + /** + * @param {FactoryTemplate<*>} registry + * @param {(GameRoot, any) => object=} resolver + */ + obj(registry, resolver = null) { + return new TypeClass(registry, resolver); + }, + + /** + * @param {FactoryTemplate<*>} registry + */ + objData(registry) { + return new TypeClassData(registry); + }, + + /** + * @param {typeof BasicSerializableObject} cls + */ + knownType(cls) { + return new TypeFixedClass(cls); + }, + + /** + * @param {BaseDataType} innerType + */ + array(innerType) { + return new TypeArray(innerType); + }, + + /** + * @param {BaseDataType} innerType + */ + fixedSizeArray(innerType) { + return new TypeArray(innerType, true); + }, + + /** + * @param {SingletonFactoryTemplate<*>} innerType + */ + classRef(registry) { + return new TypeMetaClass(registry); + }, + + /** + * @param {Object.} descriptor + */ + structured(descriptor) { + return new TypeStructuredObject(descriptor); + }, + + /** + * @param {BaseDataType} a + * @param {BaseDataType} b + */ + pair(a, b) { + return new TypePair(a, b); + }, + + /** + * @param {typeof BasicSerializableObject} classHandle + * @param {SingletonFactoryTemplate<*>} registry + */ + classWithMetaclass(classHandle, registry) { + return new TypeClassFromMetaclass(classHandle, registry); + }, +}; + +/** + * A full schema declaration + * @typedef {Object.} Schema + */ + +const globalSchemaCache = {}; + +/* dev:start */ +const classnamesCache = {}; +/* dev:end*/ + +export class BasicSerializableObject { + /* dev:start */ + /** + * Fixes typeof DerivedComponent is not assignable to typeof Component, compiled out + * in non-dev builds + */ + constructor(...args) {} + + /* dev:end */ + + static getId() { + abstract; + } + + /** + * Should return the serialization schema + * @returns {Schema} + */ + static getSchema() { + return {}; + } + + // Implementation + /** @returns {Schema} */ + static getCachedSchema() { + const id = this.getId(); + + /* dev:start */ + assert( + classnamesCache[id] === this || classnamesCache[id] === undefined, + "Class name taken twice: " + id + " (from " + this.name + ")" + ); + classnamesCache[id] = this; + /* dev:end */ + + const entry = globalSchemaCache[id]; + if (entry) { + return entry; + } + + const schema = this.getSchema(); + globalSchemaCache[id] = schema; + return schema; + } + + /** @returns {object} */ + serialize() { + return serializeSchema( + this, + /** @type {typeof BasicSerializableObject} */ (this.constructor).getCachedSchema() + ); + } + + /** + * @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, + null, + root + ); + } + + /** @returns {string|void} */ + static verify(data) { + return verifySchema(this.getCachedSchema(), data); + } +} + +/** + * Serializes an object using the given schema, mergin with the given properties + * @param {object} obj The object to serialize + * @param {Schema} schema The schema to use + * @param {object=} mergeWith Any additional properties to merge with the schema, useful for super calls + * @returns {object} Serialized data object + */ +export function serializeSchema(obj, schema, mergeWith = {}) { + for (const key in schema) { + if (!obj.hasOwnProperty(key)) { + logger.error("Invalid schema, property", key, "does not exist on", obj, "(schema=", schema, ")"); + assert( + obj.hasOwnProperty(key), + "serialization: invalid schema, property does not exist on object: " + key + ); + } + if (!schema[key]) { + assert(false, "Invalid schema (bad key '" + key + "'): " + JSON.stringify(schema)); + } + + if (G_IS_DEV) { + try { + mergeWith[key] = schema[key].serialize(obj[key]); + } catch (ex) { + logger.error( + "Serialization of", + obj, + "failed on key '" + key + "' ->", + ex, + "(schema was", + schema, + ")" + ); + throw ex; + } + } else { + mergeWith[key] = schema[key].serialize(obj[key]); + } + } + return mergeWith; +} + +/** + * Deserializes data into an object + * @param {object} obj The object to store the deserialized data into + * @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, root) { + if (baseclassErrorResult) { + return baseclassErrorResult; + } + + if (!data) { + logger.error("Got 'NULL' data for", obj, "and schema", schema, "!"); + return "Got null data"; + } + + for (const key in schema) { + if (!data.hasOwnProperty(key)) { + logger.error("Data", data, "does not contain", key, "(schema:", schema, ")"); + return "Missing key in schema: " + key + " of class " + obj.constructor.name; + } + if (!schema[key].allowNull() && (data[key] === null || data[key] === undefined)) { + logger.error("Data", data, "has null value for", key, "(schema:", schema, ")"); + return "Non-nullable entry is null: " + key + " of class " + obj.constructor.name; + } + + const errorStatus = schema[key].deserializeWithVerify(data[key], obj, key, obj.root || root); + if (errorStatus) { + logger.error( + "Deserialization failed with error '" + errorStatus + "' on object", + obj, + "and key", + key, + "(root? =", + obj.root ? "y" : "n", + ")" + ); + return errorStatus; + } + } +} + +/** + * Verifies stored data using the given schema + * @param {Schema} schema The schema to use + * @param {object} data The data to verify + * @returns {string|void} String error code or nothing on success + */ +export function verifySchema(schema, data) { + for (const key in schema) { + if (!data.hasOwnProperty(key)) { + logger.error("Data", data, "does not contain", key, "(schema:", schema, ")"); + return "verify: missing key required by schema in stored data: " + key; + } + if (!schema[key].allowNull() && (data[key] === null || data[key] === undefined)) { + logger.error("Data", data, "has null value for", key, "(schema:", schema, ")"); + return "verify: non-nullable entry is null: " + key; + } + + const errorStatus = schema[key].verifySerializedValue(data[key]); + if (errorStatus) { + logger.error(errorStatus); + return "verify: " + errorStatus; + } + } +} + +/** + * Extends a schema by adding the properties from the new schema to the existing base schema + * @param {Schema} base + * @param {Schema} newOne + * @returns {Schema} + */ +export function extendSchema(base, newOne) { + /** @type {Schema} */ + const result = Object.assign({}, base); + for (const key in newOne) { + if (result.hasOwnProperty(key)) { + logger.error("Extend schema got duplicate key:", key); + continue; + } + result[key] = newOne[key]; + } + return result; +} diff --git a/src/js/savegame/serialization_data_types.js b/src/js/savegame/serialization_data_types.js index 86b177c1..9d3b689f 100644 --- a/src/js/savegame/serialization_data_types.js +++ b/src/js/savegame/serialization_data_types.js @@ -1,1279 +1,1295 @@ -/* typehints:start */ -import { GameRoot } from "../game/root"; -import { BasicSerializableObject } from "./serialization"; -/* typehints:end */ - -import { Vector } from "../core/vector"; -import { round4Digits, schemaObject, accessNestedPropertyReverse } from "../core/utils"; -export const globalJsonSchemaDefs = {}; - -/** - * - * @param {import("./serialization").Schema} schema - */ -export function schemaToJsonSchema(schema) { - const jsonSchema = { - type: "object", - additionalProperties: false, - required: [], - properties: {}, - }; - - for (const key in schema) { - const subSchema = schema[key].getAsJsonSchema(); - jsonSchema.required.push(key); - jsonSchema.properties[key] = subSchema; - } - - return jsonSchema; -} - -/** - * Base serialization data type - */ -export class BaseDataType { - /** - * Serializes a given raw value - * @param {any} value - */ - serialize(value) { - abstract; - return {}; - } - - /** - * Verifies a given serialized value - * @param {any} value - * @returns {string|void} String error code or null on success - */ - verifySerializedValue(value) {} - - /** - * Deserializes a serialized value into the target object under the given key - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - abstract; - } - - /** - * Returns the json schema - */ - getAsJsonSchema() { - const key = this.getCacheKey(); - const schema = this.getAsJsonSchemaUncached(); - - if (!globalJsonSchemaDefs[key]) { - // schema.$id = key; - globalJsonSchemaDefs[key] = schema; - } - - 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(); - } - - /** - * INTERNAL Should return the json schema representation - */ - getAsJsonSchemaUncached() { - abstract; - } - - /** - * Returns whether null values are okay - * @returns {boolean} - */ - allowNull() { - return false; - } - - // Helper methods - - /** - * Deserializes a serialized value, but performs integrity checks before - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserializeWithVerify(value, targetObject, targetKey, root) { - const errorCode = this.verifySerializedValue(value); - if (errorCode) { - return ( - "serialization verify failed: " + - errorCode + - " [value " + - JSON.stringify(value).substr(0, 100) + - "]" - ); - } - return this.deserialize(value, targetObject, targetKey, root); - } - - /** - * Should return a cacheable key - */ - getCacheKey() { - abstract; - return ""; - } -} - -export class TypeInteger extends BaseDataType { - serialize(value) { - assert(Number.isInteger(value), "Type integer got non integer for serialize: " + value); - return value; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - targetObject[targetKey] = value; - } - - getAsJsonSchemaUncached() { - return { - type: "integer", - }; - } - - verifySerializedValue(value) { - if (!Number.isInteger(value)) { - return "Not a valid number"; - } - } - - getCacheKey() { - return "int"; - } -} - -export class TypePositiveInteger extends BaseDataType { - serialize(value) { - assert(Number.isInteger(value), "Type integer got non integer for serialize: " + value); - assert(value >= 0, "value < 0: " + value); - return value; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - targetObject[targetKey] = value; - } - - getAsJsonSchemaUncached() { - return { - type: "integer", - minimum: 0, - }; - } - - verifySerializedValue(value) { - if (!Number.isInteger(value)) { - return "Not a valid number"; - } - if (value < 0) { - return "Negative value for positive integer"; - } - } - - getCacheKey() { - return "uint"; - } -} - -export class TypeBoolean extends BaseDataType { - serialize(value) { - assert(value === true || value === false, "Type bool got non bool for serialize: " + value); - return value; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - targetObject[targetKey] = value; - } - - getAsJsonSchemaUncached() { - return { - type: "boolean", - }; - } - - verifySerializedValue(value) { - if (value !== true && value !== false) { - return "Not a boolean"; - } - } - - getCacheKey() { - return "bool"; - } -} - -export class TypeString extends BaseDataType { - serialize(value) { - assert(typeof value === "string", "Type string got non string for serialize: " + value); - return value; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - targetObject[targetKey] = value; - } - getAsJsonSchemaUncached() { - return { - type: "string", - }; - } - - verifySerializedValue(value) { - if (typeof value !== "string") { - return "Not a valid string"; - } - } - - getCacheKey() { - return "string"; - } -} - -export class TypeVector extends BaseDataType { - serialize(value) { - assert(value instanceof Vector, "Type vector got non vector for serialize: " + value); - return { - x: round4Digits(value.x), - y: round4Digits(value.y), - }; - } - - getAsJsonSchemaUncached() { - return schemaObject({ - x: { - type: "number", - }, - y: { - type: "number", - }, - }); - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - targetObject[targetKey] = new Vector(value.x, value.y); - } - - verifySerializedValue(value) { - if (!Number.isFinite(value.x) || !Number.isFinite(value.y)) { - return "Not a valid vector, missing x/y or bad data type"; - } - } - - getCacheKey() { - return "vector"; - } -} - -export class TypeTileVector extends BaseDataType { - serialize(value) { - assert(value instanceof Vector, "Type vector got non vector for serialize: " + value); - assert(Number.isInteger(value.x) && value.x > 0, "Invalid tile x:" + value.x); - assert(Number.isInteger(value.y) && value.y > 0, "Invalid tile x:" + value.y); - return { x: value.x, y: value.y }; - } - - getAsJsonSchemaUncached() { - return schemaObject({ - x: { - type: "integer", - minimum: 0, - maximum: 256, - }, - y: { - type: "integer", - minimum: 0, - maximum: 256, - }, - }); - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - targetObject[targetKey] = new Vector(value.x, value.y); - } - - verifySerializedValue(value) { - if (!Number.isInteger(value.x) || !Number.isInteger(value.y)) { - return "Not a valid tile vector, missing x/y or bad data type"; - } - if (value.x < 0 || value.y < 0) { - return "Invalid tile vector, x or y < 0"; - } - } - - getCacheKey() { - return "tilevector"; - } -} - -export class TypeNumber extends BaseDataType { - serialize(value) { - assert(Number.isFinite(value), "Type number got non number for serialize: " + value); - assert(!Number.isNaN(value), "Value is nan: " + value); - return round4Digits(value); - } - - getAsJsonSchemaUncached() { - return { - type: "number", - }; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - targetObject[targetKey] = value; - } - - verifySerializedValue(value) { - if (!Number.isFinite(value)) { - return "Not a valid number: " + value; - } - } - - getCacheKey() { - return "float"; - } -} - -export class TypePositiveNumber extends BaseDataType { - serialize(value) { - assert(Number.isFinite(value), "Type number got non number for serialize: " + value); - assert(value >= 0, "Postitive number got negative value: " + value); - return round4Digits(value); - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - targetObject[targetKey] = value; - } - - getAsJsonSchemaUncached() { - return { - type: "number", - minimum: 0, - }; - } - - verifySerializedValue(value) { - if (!Number.isFinite(value)) { - return "Not a valid number: " + value; - } - if (value < 0) { - return "Positive number got negative value: " + value; - } - } - - getCacheKey() { - return "ufloat"; - } -} - -export class TypeEnum extends BaseDataType { - /** - * @param {Object.} enumeration - */ - constructor(enumeration = {}) { - super(); - this.availableValues = Object.keys(enumeration); - } - - serialize(value) { - assert(this.availableValues.indexOf(value) >= 0, "Unknown value: " + value); - return value; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - targetObject[targetKey] = value; - } - - getAsJsonSchemaUncached() { - return { - type: "string", - enum: this.availableValues, - }; - } - - verifySerializedValue(value) { - if (this.availableValues.indexOf(value) < 0) { - return "Unknown enum value: " + value; - } - } - - getCacheKey() { - return "enum." + this.availableValues.join(","); - } -} - -export class TypeEntity extends BaseDataType { - serialize(value) { - // assert(value instanceof Entity, "Not a valid entity ref: " + value); - assert(value.uid, "Entity has no uid yet"); - assert(!value.destroyed, "Entity already destroyed"); - assert(!value.queuedForDestroy, "Entity queued for destroy"); - - return value.uid; - } - - getAsJsonSchemaUncached() { - return { - type: "integer", - minimum: 0, - }; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - const entity = root.entityMgr.findByUid(value); - if (!entity) { - return "Entity not found by uid: " + value; - } - targetObject[targetKey] = entity; - } - - verifySerializedValue(value) { - if (!Number.isFinite(value)) { - return "Not a valid uuid: " + value; - } - } - - getCacheKey() { - return "entity"; - } -} - -export class TypeEntityWeakref extends BaseDataType { - serialize(value) { - if (value === null) { - return null; - } - - // assert(value instanceof Entity, "Not a valid entity ref (weak): " + value); - assert(value.uid, "Entity has no uid yet"); - if (value.destroyed || value.queuedForDestroy) { - return null; - } - return value.uid; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - if (value === null) { - targetObject[targetKey] = null; - return; - } - const entity = root.entityMgr.findByUid(value, false); - targetObject[targetKey] = entity; - } - - getAsJsonSchemaUncached() { - return { - type: ["null", "integer"], - minimum: 0, - }; - } - - allowNull() { - return true; - } - - verifySerializedValue(value) { - if (value !== null && !Number.isFinite(value)) { - return "Not a valid uuid: " + value; - } - } - - getCacheKey() { - return "entity-weakref"; - } -} - -export class TypeClass extends BaseDataType { - /** - * - * @param {FactoryTemplate<*>} registry - */ - constructor(registry) { - super(); - this.registry = registry; - } - - serialize(value) { - assert(typeof value === "object", "Not a class instance: " + value); - return { - $: value.constructor.getId(), - data: value.serialize(), - }; - } - - getAsJsonSchemaUncached() { - const options = []; - const entries = this.registry.getEntries(); - for (let i = 0; i < entries.length; ++i) { - const entry = entries[i]; - - options.push( - schemaObject({ - $: { - type: "string", - // @ts-ignore - enum: [entry.getId()], - }, - // @ts-ignore - data: schemaToJsonSchema(entry.getCachedSchema()), - }) - ); - } - - return { oneOf: options }; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @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; - } - targetObject[targetKey] = instance; - } - - verifySerializedValue(value) { - if (!value) { - return "Got null data"; - } - - if (!this.registry.hasId(value.$)) { - return "Invalid class id: " + value.$ + " (factory is " + this.registry.getId() + ")"; - } - } - - getCacheKey() { - return "class." + this.registry.getId(); - } -} - -export class TypeClassData extends BaseDataType { - /** - * - * @param {FactoryTemplate<*>} registry - */ - constructor(registry) { - super(); - this.registry = registry; - } - - serialize(value) { - assert(typeof value === "object", "Not a class instance: " + value); - return value.serialize(); - } - - getAsJsonSchemaUncached() { - const options = []; - const entries = this.registry.getEntries(); - for (let i = 0; i < entries.length; ++i) { - const entry = entries[i]; - options.push( - schemaToJsonSchema(/** @type {typeof BasicSerializableObject} */ (entry).getCachedSchema()) - ); - } - return { oneOf: options }; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - assert(false, "can not deserialize class data of type " + this.registry.getId()); - } - - verifySerializedValue(value) { - if (!value) { - return "Got null data"; - } - } - - getCacheKey() { - return "class." + this.registry.getId(); - } -} - -export class TypeClassFromMetaclass extends BaseDataType { - /** - * - * @param {typeof BasicSerializableObject} classHandle - * @param {SingletonFactoryTemplate<*>} registry - */ - constructor(classHandle, registry) { - super(); - this.registry = registry; - this.classHandle = classHandle; - } - - serialize(value) { - assert(typeof value === "object", "Not a class instance: " + value); - return { - $: value.getMetaclass().getId(), - data: value.serialize(), - }; - } - - getAsJsonSchemaUncached() { - // const options = []; - const ids = this.registry.getAllIds(); - - return { - $: { - type: "string", - enum: ids, - }, - data: schemaToJsonSchema(this.classHandle.getCachedSchema()), - }; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - const metaClassInstance = this.registry.findById(value.$); - if (!metaClassInstance || !metaClassInstance.prototype) { - return "Invalid meta class id (runtime-err): " + value.$ + "->" + metaClassInstance; - } - - const instanceClass = metaClassInstance.getInstanceClass(); - const instance = Object.create(instanceClass.prototype); - const errorState = instance.deserialize(value.data); - if (errorState) { - return errorState; - } - targetObject[targetKey] = instance; - } - - verifySerializedValue(value) { - if (!value) { - return "Got null data"; - } - - if (!this.registry.hasId(value.$)) { - return "Invalid class id: " + value.$ + " (factory is " + this.registry.getId() + ")"; - } - } - - getCacheKey() { - return "classofmetaclass." + this.registry.getId(); - } -} - -export class TypeMetaClass extends BaseDataType { - /** - * - * @param {SingletonFactoryTemplate<*>} registry - */ - constructor(registry) { - super(); - this.registry = registry; - } - - serialize(value) { - return value.getId(); - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - const instanceClass = this.registry.findById(value); - if (!instanceClass) { - return "Invalid class id (runtime-err): " + value; - } - targetObject[targetKey] = instanceClass; - } - - getAsJsonSchemaUncached() { - return { - type: "string", - enum: this.registry.getAllIds(), - }; - } - - verifySerializedValue(value) { - if (!value) { - return "Got null data"; - } - - if (typeof value !== "string") { - return "Got non string data"; - } - - if (!this.registry.hasId(value)) { - return "Invalid class id: " + value + " (factory is " + this.registry.getId() + ")"; - } - } - - getCacheKey() { - return "metaclass." + this.registry.getId(); - } -} - -export class TypeArray extends BaseDataType { - /** - * @param {BaseDataType} innerType - */ - constructor(innerType) { - super(); - this.innerType = innerType; - } - - serialize(value) { - assert(Array.isArray(value), "Not an array"); - const result = new Array(value.length); - for (let i = 0; i < value.length; ++i) { - result[i] = this.innerType.serialize(value[i]); - } - return result; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - const result = new Array(value.length); - for (let i = 0; i < value.length; ++i) { - const errorStatus = this.innerType.deserializeWithVerify(value[i], result, i, root); - if (errorStatus) { - return errorStatus; - } - } - targetObject[targetKey] = result; - } - - getAsJsonSchemaUncached() { - return { - type: "array", - items: this.innerType.getAsJsonSchema(), - }; - } - - verifySerializedValue(value) { - if (!Array.isArray(value)) { - return "Not an array: " + value; - } - } - - getCacheKey() { - return "array." + this.innerType.getCacheKey(); - } -} - -export class TypeFixedClass extends BaseDataType { - /** - * - * @param {typeof BasicSerializableObject} baseclass - */ - constructor(baseclass) { - super(); - this.baseclass = baseclass; - } - - serialize(value) { - assert(value instanceof this.baseclass, "Not a valid class instance"); - return value.serialize(); - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - const instance = Object.create(this.baseclass.prototype); - const errorState = instance.deserialize(value); - if (errorState) { - return "Failed to deserialize class: " + errorState; - } - targetObject[targetKey] = instance; - } - - getAsJsonSchemaUncached() { - this.baseclass.getSchema(); - this.baseclass.getCachedSchema(); - return schemaToJsonSchema(this.baseclass.getCachedSchema()); - } - - verifySerializedValue(value) { - if (!value) { - return "Got null data"; - } - } - - getCacheKey() { - return "fixedclass." + this.baseclass.getId(); - } -} - -export class TypeKeyValueMap extends BaseDataType { - /** - * @param {BaseDataType} valueType - * @param {boolean=} includeEmptyValues - */ - constructor(valueType, includeEmptyValues = true) { - super(); - this.valueType = valueType; - this.includeEmptyValues = includeEmptyValues; - } - - serialize(value) { - assert(typeof value === "object", "not an object"); - let result = {}; - for (const key in value) { - const serialized = this.valueType.serialize(value[key]); - if (!this.includeEmptyValues && typeof serialized === "object") { - if ( - serialized.$ && - typeof serialized.data === "object" && - Object.keys(serialized.data).length === 0 - ) { - continue; - } else if (Object.keys(serialized).length === 0) { - continue; - } - } - - result[key] = serialized; - } - return result; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - let result = {}; - for (const key in value) { - const errorCode = this.valueType.deserializeWithVerify(value[key], result, key, root); - if (errorCode) { - return errorCode; - } - } - targetObject[targetKey] = result; - } - - getAsJsonSchemaUncached() { - return { - type: "object", - additionalProperties: this.valueType.getAsJsonSchema(), - }; - } - - verifySerializedValue(value) { - if (typeof value !== "object") { - return "KV map is not an object"; - } - } - - getCacheKey() { - return "kvmap." + this.valueType.getCacheKey(); - } -} - -export class TypeClassId extends BaseDataType { - /** - * @param {FactoryTemplate<*>|SingletonFactoryTemplate<*>} registry - */ - constructor(registry) { - super(); - this.registry = registry; - } - - serialize(value) { - assert(typeof value === "string", "Not a valid string"); - assert(this.registry.hasId(value), "Id " + value + " not found in registry"); - return value; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - targetObject[targetKey] = value; - } - - getAsJsonSchemaUncached() { - return { - type: "string", - enum: this.registry.getAllIds(), - }; - } - - verifySerializedValue(value) { - if (typeof value !== "string") { - return "Not a valid registry id key: " + value; - } - if (!this.registry.hasId(value)) { - return "Id " + value + " not known to registry"; - } - } - - getCacheKey() { - return "classid." + this.registry.getId(); - } -} - -export class TypePair extends BaseDataType { - /** - * @param {BaseDataType} type1 - * @param {BaseDataType} type2 - */ - constructor(type1, type2) { - super(); - assert(type1 && type1 instanceof BaseDataType, "bad first type given for pair"); - assert(type2 && type2 instanceof BaseDataType, "bad second type given for pair"); - this.type1 = type1; - this.type2 = type2; - } - - serialize(value) { - assert(Array.isArray(value), "pair: not an array"); - assert(value.length === 2, "pair: length != 2"); - return [this.type1.serialize(value[0]), this.type2.serialize(value[1])]; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - const result = [undefined, undefined]; - - let errorCode = this.type1.deserialize(value[0], result, 0, root); - if (errorCode) { - return errorCode; - } - errorCode = this.type2.deserialize(value[1], result, 1, root); - if (errorCode) { - return errorCode; - } - - targetObject[targetKey] = result; - } - - getAsJsonSchemaUncached() { - return { - type: "array", - minLength: 2, - maxLength: 2, - items: [this.type1.getAsJsonSchema(), this.type2.getAsJsonSchema()], - }; - } - - verifySerializedValue(value) { - if (!Array.isArray(value)) { - return "Pair is not an array"; - } - if (value.length !== 2) { - return "Pair length != 2"; - } - let errorCode = this.type1.verifySerializedValue(value[0]); - if (errorCode) { - return errorCode; - } - errorCode = this.type2.verifySerializedValue(value[1]); - if (errorCode) { - return errorCode; - } - } - - getCacheKey() { - return "pair.(" + this.type1.getCacheKey() + "," + this.type2.getCacheKey + ")"; - } -} - -export class TypeNullable extends BaseDataType { - /** - * @param {BaseDataType} wrapped - */ - constructor(wrapped) { - super(); - this.wrapped = wrapped; - } - - serialize(value) { - if (value === null || value === undefined) { - return null; - } - return this.wrapped.serialize(value); - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - if (value === null || value === undefined) { - targetObject[targetKey] = null; - return; - } - return this.wrapped.deserialize(value, targetObject, targetKey, root); - } - - verifySerializedValue(value) { - if (value === null) { - return; - } - return this.wrapped.verifySerializedValue(value); - } - - getAsJsonSchemaUncached() { - return { - oneOf: [ - { - type: "null", - }, - this.wrapped.getAsJsonSchema(), - ], - }; - } - - allowNull() { - return true; - } - - getCacheKey() { - return "nullable." + this.wrapped.getCacheKey(); - } -} - -export class TypeStructuredObject extends BaseDataType { - /** - * @param {Object.} descriptor - */ - constructor(descriptor) { - super(); - this.descriptor = descriptor; - } - - serialize(value) { - assert(typeof value === "object", "not an object"); - let result = {}; - for (const key in this.descriptor) { - // assert(value.hasOwnProperty(key), "Serialization: Object does not have", key, "property!"); - result[key] = this.descriptor[key].serialize(value[key]); - } - return result; - } - - /** - * @see BaseDataType.deserialize - * @param {any} value - * @param {GameRoot} root - * @param {object} targetObject - * @param {string|number} targetKey - * @returns {string|void} String error code or null on success - */ - deserialize(value, targetObject, targetKey, root) { - let result = {}; - for (const key in value) { - const valueType = this.descriptor[key]; - const errorCode = valueType.deserializeWithVerify(value[key], result, key, root); - if (errorCode) { - return errorCode; - } - } - targetObject[targetKey] = result; - } - - getAsJsonSchemaUncached() { - let properties = {}; - for (const key in this.descriptor) { - properties[key] = this.descriptor[key].getAsJsonSchema(); - } - - return { - type: "object", - required: Object.keys(this.descriptor), - properties, - }; - } - - verifySerializedValue(value) { - if (typeof value !== "object") { - return "structured object is not an object"; - } - for (const key in this.descriptor) { - if (!value.hasOwnProperty(key)) { - return "structured object is missing key " + key; - } - const subError = this.descriptor[key].verifySerializedValue(value[key]); - if (subError) { - return "structured object::" + subError; - } - } - } - - getCacheKey() { - let props = []; - for (const key in this.descriptor) { - props.push(key + "=" + this.descriptor[key].getCacheKey()); - } - return "structured[" + props.join(",") + "]"; - } -} +/* typehints:start */ +import { GameRoot } from "../game/root"; +import { BasicSerializableObject } from "./serialization"; +/* typehints:end */ + +import { Vector } from "../core/vector"; +import { round4Digits } from "../core/utils"; +export const globalJsonSchemaDefs = {}; + +/** + * + * @param {import("./serialization").Schema} schema + */ +export function schemaToJsonSchema(schema) { + const jsonSchema = { + type: "object", + additionalProperties: false, + required: [], + properties: {}, + }; + + for (const key in schema) { + const subSchema = schema[key].getAsJsonSchema(); + jsonSchema.required.push(key); + jsonSchema.properties[key] = subSchema; + } + + 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 + */ +export class BaseDataType { + /** + * Serializes a given raw value + * @param {any} value + */ + serialize(value) { + abstract; + return {}; + } + + /** + * Verifies a given serialized value + * @param {any} value + * @returns {string|void} String error code or null on success + */ + verifySerializedValue(value) {} + + /** + * Deserializes a serialized value into the target object under the given key + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + abstract; + } + + /** + * Returns the json schema + */ + getAsJsonSchema() { + const key = this.getCacheKey(); + const schema = this.getAsJsonSchemaUncached(); + + if (!globalJsonSchemaDefs[key]) { + // schema.$id = key; + globalJsonSchemaDefs[key] = schema; + } + + return { + $ref: "#/definitions/" + key, + }; + } + + /** + * INTERNAL Should return the json schema representation + */ + getAsJsonSchemaUncached() { + abstract; + } + + /** + * Returns whether null values are okay + * @returns {boolean} + */ + allowNull() { + return false; + } + + // Helper methods + + /** + * Deserializes a serialized value, but performs integrity checks before + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserializeWithVerify(value, targetObject, targetKey, root) { + const errorCode = this.verifySerializedValue(value); + if (errorCode) { + return ( + "serialization verify failed: " + + errorCode + + " [value " + + (JSON.stringify(value) || "").substr(0, 100) + + "]" + ); + } + return this.deserialize(value, targetObject, targetKey, root); + } + + /** + * Should return a cacheable key + */ + getCacheKey() { + abstract; + return ""; + } +} + +export class TypeInteger extends BaseDataType { + serialize(value) { + assert(Number.isInteger(value), "Type integer got non integer for serialize: " + value); + return value; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + targetObject[targetKey] = value; + } + + getAsJsonSchemaUncached() { + return { + type: "integer", + }; + } + + verifySerializedValue(value) { + if (!Number.isInteger(value)) { + return "Not a valid number"; + } + } + + getCacheKey() { + return "int"; + } +} + +export class TypePositiveInteger extends BaseDataType { + serialize(value) { + assert(Number.isInteger(value), "Type integer got non integer for serialize: " + value); + assert(value >= 0, "value < 0: " + value); + return value; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + targetObject[targetKey] = value; + } + + getAsJsonSchemaUncached() { + return { + type: "integer", + minimum: 0, + }; + } + + verifySerializedValue(value) { + if (!Number.isInteger(value)) { + return "Not a valid number"; + } + if (value < 0) { + return "Negative value for positive integer"; + } + } + + getCacheKey() { + return "uint"; + } +} + +export class TypeBoolean extends BaseDataType { + serialize(value) { + assert(value === true || value === false, "Type bool got non bool for serialize: " + value); + return value; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + targetObject[targetKey] = value; + } + + getAsJsonSchemaUncached() { + return { + type: "boolean", + }; + } + + verifySerializedValue(value) { + if (value !== true && value !== false) { + return "Not a boolean"; + } + } + + getCacheKey() { + return "bool"; + } +} + +export class TypeString extends BaseDataType { + serialize(value) { + assert(typeof value === "string", "Type string got non string for serialize: " + value); + return value; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + targetObject[targetKey] = value; + } + getAsJsonSchemaUncached() { + return { + type: "string", + }; + } + + verifySerializedValue(value) { + if (typeof value !== "string") { + return "Not a valid string"; + } + } + + getCacheKey() { + return "string"; + } +} + +export class TypeVector extends BaseDataType { + serialize(value) { + assert(value instanceof Vector, "Type vector got non vector for serialize: " + value); + return { + x: round4Digits(value.x), + y: round4Digits(value.y), + }; + } + + getAsJsonSchemaUncached() { + return schemaObject({ + x: { + type: "number", + }, + y: { + type: "number", + }, + }); + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + targetObject[targetKey] = new Vector(value.x, value.y); + } + + verifySerializedValue(value) { + if (!Number.isFinite(value.x) || !Number.isFinite(value.y)) { + return "Not a valid vector, missing x/y or bad data type"; + } + } + + getCacheKey() { + return "vector"; + } +} + +export class TypeTileVector extends BaseDataType { + serialize(value) { + assert(value instanceof Vector, "Type vector got non vector for serialize: " + value); + assert(Number.isInteger(value.x) && value.x > 0, "Invalid tile x:" + value.x); + assert(Number.isInteger(value.y) && value.y > 0, "Invalid tile x:" + value.y); + return { x: value.x, y: value.y }; + } + + getAsJsonSchemaUncached() { + return schemaObject({ + x: { + type: "integer", + minimum: 0, + maximum: 256, + }, + y: { + type: "integer", + minimum: 0, + maximum: 256, + }, + }); + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + targetObject[targetKey] = new Vector(value.x, value.y); + } + + verifySerializedValue(value) { + if (!Number.isInteger(value.x) || !Number.isInteger(value.y)) { + return "Not a valid tile vector, missing x/y or bad data type"; + } + if (value.x < 0 || value.y < 0) { + return "Invalid tile vector, x or y < 0"; + } + } + + getCacheKey() { + return "tilevector"; + } +} + +export class TypeNumber extends BaseDataType { + serialize(value) { + assert(Number.isFinite(value), "Type number got non number for serialize: " + value); + assert(!Number.isNaN(value), "Value is nan: " + value); + return round4Digits(value); + } + + getAsJsonSchemaUncached() { + return { + type: "number", + }; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + targetObject[targetKey] = value; + } + + verifySerializedValue(value) { + if (!Number.isFinite(value)) { + return "Not a valid number: " + value; + } + } + + getCacheKey() { + return "float"; + } +} + +export class TypePositiveNumber extends BaseDataType { + serialize(value) { + assert(Number.isFinite(value), "Type number got non number for serialize: " + value); + assert(value >= 0, "Postitive number got negative value: " + value); + return round4Digits(value); + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + targetObject[targetKey] = value; + } + + getAsJsonSchemaUncached() { + return { + type: "number", + minimum: 0, + }; + } + + verifySerializedValue(value) { + if (!Number.isFinite(value)) { + return "Not a valid number: " + value; + } + if (value < 0) { + return "Positive number got negative value: " + value; + } + } + + getCacheKey() { + return "ufloat"; + } +} + +export class TypeEnum extends BaseDataType { + /** + * @param {Object.} enumeration + */ + constructor(enumeration = {}) { + super(); + this.availableValues = Object.values(enumeration); + } + + serialize(value) { + assert(this.availableValues.indexOf(value) >= 0, "Unknown value: " + value); + return value; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + targetObject[targetKey] = value; + } + + getAsJsonSchemaUncached() { + return { + type: "string", + enum: this.availableValues, + }; + } + + verifySerializedValue(value) { + if (this.availableValues.indexOf(value) < 0) { + return "Unknown enum value: " + value; + } + } + + getCacheKey() { + return "enum." + this.availableValues.join(","); + } +} + +export class TypeEntity extends BaseDataType { + serialize(value) { + // assert(value instanceof Entity, "Not a valid entity ref: " + value); + assert(value.uid, "Entity has no uid yet"); + assert(!value.destroyed, "Entity already destroyed"); + assert(!value.queuedForDestroy, "Entity queued for destroy"); + + return value.uid; + } + + getAsJsonSchemaUncached() { + return { + type: "integer", + minimum: 0, + }; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + const entity = root.entityMgr.findByUid(value); + if (!entity) { + return "Entity not found by uid: " + value; + } + targetObject[targetKey] = entity; + } + + verifySerializedValue(value) { + if (!Number.isFinite(value)) { + return "Not a valid uuid: " + value; + } + } + + getCacheKey() { + return "entity"; + } +} + +export class TypeEntityWeakref extends BaseDataType { + serialize(value) { + if (value === null) { + return null; + } + + // assert(value instanceof Entity, "Not a valid entity ref (weak): " + value); + assert(value.uid, "Entity has no uid yet"); + if (value.destroyed || value.queuedForDestroy) { + return null; + } + return value.uid; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + if (value === null) { + targetObject[targetKey] = null; + return; + } + const entity = root.entityMgr.findByUid(value, false); + targetObject[targetKey] = entity; + } + + getAsJsonSchemaUncached() { + return { + type: ["null", "integer"], + minimum: 0, + }; + } + + allowNull() { + return true; + } + + verifySerializedValue(value) { + if (value !== null && !Number.isFinite(value)) { + return "Not a valid uuid: " + value; + } + } + + getCacheKey() { + return "entity-weakref"; + } +} + +export class TypeClass extends BaseDataType { + /** + * + * @param {FactoryTemplate<*>} registry + * @param {(GameRoot, object) => object} customResolver + */ + constructor(registry, customResolver = null) { + super(); + this.registry = registry; + this.customResolver = customResolver; + } + + serialize(value) { + assert(typeof value === "object", "Not a class instance: " + value); + return { + $: value.constructor.getId(), + data: value.serialize(), + }; + } + + getAsJsonSchemaUncached() { + const options = []; + const entries = this.registry.getEntries(); + for (let i = 0; i < entries.length; ++i) { + const entry = entries[i]; + + options.push( + schemaObject({ + $: { + type: "string", + // @ts-ignore + enum: [entry.getId()], + }, + // @ts-ignore + data: schemaToJsonSchema(entry.getCachedSchema()), + }) + ); + } + + return { oneOf: options }; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + 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; + } + + verifySerializedValue(value) { + if (!value) { + return "Got null data"; + } + + if (!this.registry.hasId(value.$)) { + return "Invalid class id: " + value.$ + " (factory is " + this.registry.getId() + ")"; + } + } + + getCacheKey() { + return "class." + this.registry.getId(); + } +} + +export class TypeClassData extends BaseDataType { + /** + * + * @param {FactoryTemplate<*>} registry + */ + constructor(registry) { + super(); + this.registry = registry; + } + + serialize(value) { + assert(typeof value === "object", "Not a class instance: " + value); + return value.serialize(); + } + + getAsJsonSchemaUncached() { + const options = []; + const entries = this.registry.getEntries(); + for (let i = 0; i < entries.length; ++i) { + const entry = entries[i]; + options.push( + schemaToJsonSchema(/** @type {typeof BasicSerializableObject} */ (entry).getCachedSchema()) + ); + } + return { oneOf: options }; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + assert(false, "can not deserialize class data of type " + this.registry.getId()); + } + + verifySerializedValue(value) { + if (!value) { + return "Got null data"; + } + } + + getCacheKey() { + return "class." + this.registry.getId(); + } +} + +export class TypeClassFromMetaclass extends BaseDataType { + /** + * + * @param {typeof BasicSerializableObject} classHandle + * @param {SingletonFactoryTemplate<*>} registry + */ + constructor(classHandle, registry) { + super(); + this.registry = registry; + this.classHandle = classHandle; + } + + serialize(value) { + assert(typeof value === "object", "Not a class instance: " + value); + return { + $: value.getMetaclass().getId(), + data: value.serialize(), + }; + } + + getAsJsonSchemaUncached() { + // const options = []; + const ids = this.registry.getAllIds(); + + return { + $: { + type: "string", + enum: ids, + }, + data: schemaToJsonSchema(this.classHandle.getCachedSchema()), + }; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + const metaClassInstance = this.registry.findById(value.$); + if (!metaClassInstance || !metaClassInstance.prototype) { + return "Invalid meta class id (runtime-err): " + value.$ + "->" + metaClassInstance; + } + + const instanceClass = metaClassInstance.getInstanceClass(); + const instance = Object.create(instanceClass.prototype); + const errorState = instance.deserialize(value.data); + if (errorState) { + return errorState; + } + targetObject[targetKey] = instance; + } + + verifySerializedValue(value) { + if (!value) { + return "Got null data"; + } + + if (!this.registry.hasId(value.$)) { + return "Invalid class id: " + value.$ + " (factory is " + this.registry.getId() + ")"; + } + } + + getCacheKey() { + return "classofmetaclass." + this.registry.getId(); + } +} + +export class TypeMetaClass extends BaseDataType { + /** + * + * @param {SingletonFactoryTemplate<*>} registry + */ + constructor(registry) { + super(); + this.registry = registry; + } + + serialize(value) { + return value.getId(); + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + const instanceClass = this.registry.findById(value); + if (!instanceClass) { + return "Invalid class id (runtime-err): " + value; + } + targetObject[targetKey] = instanceClass; + } + + getAsJsonSchemaUncached() { + return { + type: "string", + enum: this.registry.getAllIds(), + }; + } + + verifySerializedValue(value) { + if (!value) { + return "Got null data"; + } + + if (typeof value !== "string") { + return "Got non string data"; + } + + if (!this.registry.hasId(value)) { + return "Invalid class id: " + value + " (factory is " + this.registry.getId() + ")"; + } + } + + getCacheKey() { + return "metaclass." + this.registry.getId(); + } +} + +export class TypeArray extends BaseDataType { + /** + * @param {BaseDataType} innerType + */ + constructor(innerType, fixedSize = false) { + super(); + this.fixedSize = fixedSize; + this.innerType = innerType; + } + + serialize(value) { + assert(Array.isArray(value), "Not an array"); + const result = new Array(value.length); + for (let i = 0; i < value.length; ++i) { + result[i] = this.innerType.serialize(value[i]); + } + return result; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + let destination = targetObject[targetKey]; + if (!destination) { + targetObject[targetKey] = destination = new Array(value.length); + } + + const size = this.fixedSize ? Math.min(value.length, destination.length) : value.length; + + for (let i = 0; i < size; ++i) { + const errorStatus = this.innerType.deserializeWithVerify(value[i], destination, i, root); + if (errorStatus) { + return errorStatus; + } + } + } + + getAsJsonSchemaUncached() { + return { + type: "array", + items: this.innerType.getAsJsonSchema(), + }; + } + + verifySerializedValue(value) { + if (!Array.isArray(value)) { + return "Not an array: " + value; + } + } + + getCacheKey() { + return "array." + this.innerType.getCacheKey(); + } +} + +export class TypeFixedClass extends BaseDataType { + /** + * + * @param {typeof BasicSerializableObject} baseclass + */ + constructor(baseclass) { + super(); + this.baseclass = baseclass; + } + + serialize(value) { + assert(value instanceof this.baseclass, "Not a valid class instance"); + return value.serialize(); + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + const instance = Object.create(this.baseclass.prototype); + const errorState = instance.deserialize(value); + if (errorState) { + return "Failed to deserialize class: " + errorState; + } + targetObject[targetKey] = instance; + } + + getAsJsonSchemaUncached() { + this.baseclass.getSchema(); + this.baseclass.getCachedSchema(); + return schemaToJsonSchema(this.baseclass.getCachedSchema()); + } + + verifySerializedValue(value) { + if (!value) { + return "Got null data"; + } + } + + getCacheKey() { + return "fixedclass." + this.baseclass.getId(); + } +} + +export class TypeKeyValueMap extends BaseDataType { + /** + * @param {BaseDataType} valueType + * @param {boolean=} includeEmptyValues + */ + constructor(valueType, includeEmptyValues = true) { + super(); + this.valueType = valueType; + this.includeEmptyValues = includeEmptyValues; + } + + serialize(value) { + assert(typeof value === "object", "not an object"); + let result = {}; + for (const key in value) { + const serialized = this.valueType.serialize(value[key]); + if (!this.includeEmptyValues && typeof serialized === "object") { + if ( + serialized.$ && + typeof serialized.data === "object" && + Object.keys(serialized.data).length === 0 + ) { + continue; + } else if (Object.keys(serialized).length === 0) { + continue; + } + } + + result[key] = serialized; + } + return result; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + let result = {}; + for (const key in value) { + const errorCode = this.valueType.deserializeWithVerify(value[key], result, key, root); + if (errorCode) { + return errorCode; + } + } + targetObject[targetKey] = result; + } + + getAsJsonSchemaUncached() { + return { + type: "object", + additionalProperties: this.valueType.getAsJsonSchema(), + }; + } + + verifySerializedValue(value) { + if (typeof value !== "object") { + return "KV map is not an object"; + } + } + + getCacheKey() { + return "kvmap." + this.valueType.getCacheKey(); + } +} + +export class TypeClassId extends BaseDataType { + /** + * @param {FactoryTemplate<*>|SingletonFactoryTemplate<*>} registry + */ + constructor(registry) { + super(); + this.registry = registry; + } + + serialize(value) { + assert(typeof value === "string", "Not a valid string"); + assert(this.registry.hasId(value), "Id " + value + " not found in registry"); + return value; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + targetObject[targetKey] = value; + } + + getAsJsonSchemaUncached() { + return { + type: "string", + enum: this.registry.getAllIds(), + }; + } + + verifySerializedValue(value) { + if (typeof value !== "string") { + return "Not a valid registry id key: " + value; + } + if (!this.registry.hasId(value)) { + return "Id " + value + " not known to registry"; + } + } + + getCacheKey() { + return "classid." + this.registry.getId(); + } +} + +export class TypePair extends BaseDataType { + /** + * @param {BaseDataType} type1 + * @param {BaseDataType} type2 + */ + constructor(type1, type2) { + super(); + assert(type1 && type1 instanceof BaseDataType, "bad first type given for pair"); + assert(type2 && type2 instanceof BaseDataType, "bad second type given for pair"); + this.type1 = type1; + this.type2 = type2; + } + + serialize(value) { + assert(Array.isArray(value), "pair: not an array"); + assert(value.length === 2, "pair: length != 2"); + return [this.type1.serialize(value[0]), this.type2.serialize(value[1])]; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + const result = [undefined, undefined]; + + let errorCode = this.type1.deserialize(value[0], result, 0, root); + if (errorCode) { + return errorCode; + } + errorCode = this.type2.deserialize(value[1], result, 1, root); + if (errorCode) { + return errorCode; + } + + targetObject[targetKey] = result; + } + + getAsJsonSchemaUncached() { + return { + type: "array", + minLength: 2, + maxLength: 2, + items: [this.type1.getAsJsonSchema(), this.type2.getAsJsonSchema()], + }; + } + + verifySerializedValue(value) { + if (!Array.isArray(value)) { + return "Pair is not an array"; + } + if (value.length !== 2) { + return "Pair length != 2"; + } + let errorCode = this.type1.verifySerializedValue(value[0]); + if (errorCode) { + return errorCode; + } + errorCode = this.type2.verifySerializedValue(value[1]); + if (errorCode) { + return errorCode; + } + } + + getCacheKey() { + return "pair.(" + this.type1.getCacheKey() + "," + this.type2.getCacheKey + ")"; + } +} + +export class TypeNullable extends BaseDataType { + /** + * @param {BaseDataType} wrapped + */ + constructor(wrapped) { + super(); + this.wrapped = wrapped; + } + + serialize(value) { + if (value === null || value === undefined) { + return null; + } + return this.wrapped.serialize(value); + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + if (value === null || value === undefined) { + targetObject[targetKey] = null; + return; + } + return this.wrapped.deserialize(value, targetObject, targetKey, root); + } + + verifySerializedValue(value) { + if (value === null) { + return; + } + return this.wrapped.verifySerializedValue(value); + } + + getAsJsonSchemaUncached() { + return { + oneOf: [ + { + type: "null", + }, + this.wrapped.getAsJsonSchema(), + ], + }; + } + + allowNull() { + return true; + } + + getCacheKey() { + return "nullable." + this.wrapped.getCacheKey(); + } +} + +export class TypeStructuredObject extends BaseDataType { + /** + * @param {Object.} descriptor + */ + constructor(descriptor) { + super(); + this.descriptor = descriptor; + } + + serialize(value) { + assert(typeof value === "object", "not an object"); + let result = {}; + for (const key in this.descriptor) { + // assert(value.hasOwnProperty(key), "Serialization: Object does not have", key, "property!"); + result[key] = this.descriptor[key].serialize(value[key]); + } + return result; + } + + /** + * @see BaseDataType.deserialize + * @param {any} value + * @param {GameRoot} root + * @param {object} targetObject + * @param {string|number} targetKey + * @returns {string|void} String error code or null on success + */ + deserialize(value, targetObject, targetKey, root) { + 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], target, key, root); + if (errorCode) { + return errorCode; + } + } + } + + getAsJsonSchemaUncached() { + let properties = {}; + for (const key in this.descriptor) { + properties[key] = this.descriptor[key].getAsJsonSchema(); + } + + return { + type: "object", + required: Object.keys(this.descriptor), + properties, + }; + } + + verifySerializedValue(value) { + if (typeof value !== "object") { + return "structured object is not an object"; + } + for (const key in this.descriptor) { + if (!value.hasOwnProperty(key)) { + return "structured object is missing key " + key; + } + const subError = this.descriptor[key].verifySerializedValue(value[key]); + if (subError) { + return "structured object::" + subError; + } + } + } + + getCacheKey() { + let props = []; + for (const key in this.descriptor) { + props.push(key + "=" + this.descriptor[key].getCacheKey()); + } + return "structured[" + props.join(",") + "]"; + } +} diff --git a/src/js/savegame/serializer_internal.js b/src/js/savegame/serializer_internal.js index 8df6f6e4..c75cebad 100644 --- a/src/js/savegame/serializer_internal.js +++ b/src/js/savegame/serializer_internal.js @@ -1,74 +1,97 @@ -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 { globalConfig } from "../core/config"; +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]) { + if (G_IS_DEV && !globalConfig.debug.disableSlowAsserts) { + // @ts-ignore + if (++window.componentWarningsShown < 100) { + 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..316c536c 100644 --- a/src/js/states/ingame.js +++ b/src/js/states/ingame.js @@ -1,449 +1,454 @@ -import { APPLICATION_ERROR_OCCURED } from "../core/error_handler"; -import { GameState } from "../core/game_state"; -import { logSection, createLogger } from "../core/logging"; -import { waitNextFrame } from "../core/utils"; -import { globalConfig } from "../core/config"; -import { GameLoadingOverlay } from "../game/game_loading_overlay"; -import { KeyActionMapper } from "../game/key_action_mapper"; -import { Savegame } from "../savegame/savegame"; -import { GameCore } from "../game/core"; -import { MUSIC } from "../platform/sound"; - -const logger = createLogger("state/ingame"); - -// Different sub-states -const stages = { - s3_createCore: "🌈 3: Create core", - s4_A_initEmptyGame: "🌈 4/A: Init empty game", - s4_B_resumeGame: "🌈 4/B: Resume game", - - s5_firstUpdate: "🌈 5: First game update", - s6_postLoadHook: "🌈 6: Post load hook", - s7_warmup: "🌈 7: Warmup", - - s10_gameRunning: "🌈 10: Game finally running", - - leaving: "🌈 Saving, then leaving the game", - destroyed: "🌈 DESTROYED: Core is empty and waits for state leave", - initFailed: "🌈 ERROR: Initialization failed!", -}; - -export const gameCreationAction = { - new: "new-game", - resume: "resume-game", -}; - -// Typehints -export class GameCreationPayload { - constructor() { - /** @type {boolean|undefined} */ - this.fastEnter; - - /** @type {Savegame} */ - this.savegame; - } -} - -export class InGameState extends GameState { - constructor() { - super("InGameState"); - - /** @type {GameCreationPayload} */ - this.creationPayload = null; - - // Stores current stage - this.stage = ""; - - /** @type {GameCore} */ - this.core = null; - - /** @type {KeyActionMapper} */ - this.keyActionMapper = null; - - /** @type {GameLoadingOverlay} */ - this.loadingOverlay = null; - - /** @type {Savegame} */ - this.savegame; - - this.boundInputFilter = this.filterInput.bind(this); - } - - /** - * Switches the game into another sub-state - * @param {string} stage - */ - switchStage(stage) { - assert(stage, "Got empty stage"); - if (stage !== this.stage) { - this.stage = stage; - logger.log(this.stage); - return true; - } else { - // log(this, "Re entering", stage); - return false; - } - } - - // GameState implementation - getInnerHTML() { - return ""; - } - - getThemeMusic() { - return MUSIC.theme; - } - - onBeforeExit() { - // logger.log("Saving before quitting"); - // return this.doSave().then(() => { - // logger.log(this, "Successfully saved"); - // // this.stageDestroyed(); - // }); - } - - onAppPause() { - // if (this.stage === stages.s10_gameRunning) { - // logger.log("Saving because app got paused"); - // this.doSave(); - // } - } - - getHasFadeIn() { - return false; - } - - getPauseOnFocusLost() { - return false; - } - - getHasUnloadConfirmation() { - return true; - } - - onLeave() { - if (this.core) { - this.stageDestroyed(); - } - this.app.inputMgr.dismountFilter(this.boundInputFilter); - } - - onResized(w, h) { - super.onResized(w, h); - if (this.stage === stages.s10_gameRunning) { - this.core.resize(w, h); - } - } - - // ---- End of GameState implementation - - /** - * Goes back to the menu state - */ - goBackToMenu() { - this.saveThenGoToState("MainMenuState"); - } - - /** - * Goes back to the settings state - */ - goToSettings() { - this.saveThenGoToState("SettingsState", { - backToStateId: this.key, - backToStatePayload: this.creationPayload, - }); - } - - /** - * Goes back to the settings state - */ - goToKeybindings() { - this.saveThenGoToState("KeybindingsState", { - backToStateId: this.key, - backToStatePayload: this.creationPayload, - }); - } - - /** - * Moves to a state outside of the game - * @param {string} stateId - * @param {any=} payload - */ - saveThenGoToState(stateId, payload) { - if (this.stage === stages.leaving || this.stage === stages.destroyed) { - logger.warn( - "Tried to leave game twice or during destroy:", - this.stage, - "(attempted to move to", - stateId, - ")" - ); - return; - } - this.stageLeavingGame(); - this.doSave().then(() => { - this.stageDestroyed(); - this.moveToState(stateId, payload); - }); - } - - onBackButton() { - // do nothing - } - - /** - * Called when the game somehow failed to initialize. Resets everything to basic state and - * then goes to the main menu, showing the error - * @param {string} err - */ - onInitializationFailure(err) { - if (this.switchStage(stages.initFailed)) { - logger.error("Init failure:", err); - this.stageDestroyed(); - this.moveToState("MainMenuState", { loadError: err }); - } - } - - // STAGES - - /** - * Creates the game core instance, and thus the root - */ - stage3CreateCore() { - if (this.switchStage(stages.s3_createCore)) { - logger.log("Creating new game core"); - this.core = new GameCore(this.app); - - this.core.initializeRoot(this, this.savegame); - - if (this.savegame.hasGameDump()) { - this.stage4bResumeGame(); - } else { - this.app.gameAnalytics.handleGameStarted(); - this.stage4aInitEmptyGame(); - } - } - } - - /** - * Initializes a new empty game - */ - stage4aInitEmptyGame() { - if (this.switchStage(stages.s4_A_initEmptyGame)) { - this.core.initNewGame(); - this.stage5FirstUpdate(); - } - } - - /** - * Resumes an existing game - */ - stage4bResumeGame() { - if (this.switchStage(stages.s4_B_resumeGame)) { - if (!this.core.initExistingGame()) { - this.onInitializationFailure("Savegame is corrupt and can not be restored."); - return; - } - this.app.gameAnalytics.handleGameResumed(); - this.stage5FirstUpdate(); - } - } - - /** - * Performs the first game update on the game which initializes most caches - */ - stage5FirstUpdate() { - if (this.switchStage(stages.s5_firstUpdate)) { - this.core.root.logicInitialized = true; - this.core.updateLogic(); - this.stage6PostLoadHook(); - } - } - - /** - * Call the post load hook, this means that we have loaded the game, and all systems - * can operate and start to work now. - */ - stage6PostLoadHook() { - if (this.switchStage(stages.s6_postLoadHook)) { - logger.log("Post load hook"); - this.core.postLoadHook(); - this.stage7Warmup(); - } - } - - /** - * This makes the game idle and draw for a while, because we run most code this way - * the V8 engine can already start to optimize it. Also this makes sure the resources - * are in the VRAM and we have a smooth experience once we start. - */ - stage7Warmup() { - if (this.switchStage(stages.s7_warmup)) { - if (G_IS_DEV && globalConfig.debug.noArtificialDelays) { - this.warmupTimeSeconds = 0.05; - } else { - if (this.creationPayload.fastEnter) { - this.warmupTimeSeconds = globalConfig.warmupTimeSecondsFast; - } else { - this.warmupTimeSeconds = globalConfig.warmupTimeSecondsRegular; - } - } - } - } - - /** - * The final stage where this game is running and updating regulary. - */ - stage10GameRunning() { - if (this.switchStage(stages.s10_gameRunning)) { - this.core.root.signals.readyToRender.dispatch(); - - logSection("GAME STARTED", "#26a69a"); - - // Initial resize, might have changed during loading (this is possible) - this.core.resize(this.app.screenWidth, this.app.screenHeight); - } - } - - /** - * This stage destroys the whole game, used to cleanup - */ - stageDestroyed() { - if (this.switchStage(stages.destroyed)) { - // Cleanup all api calls - this.cancelAllAsyncOperations(); - - if (this.syncer) { - this.syncer.cancelSync(); - this.syncer = null; - } - - // Cleanup core - if (this.core) { - this.core.destruct(); - this.core = null; - } - } - } - - /** - * When leaving the game - */ - stageLeavingGame() { - if (this.switchStage(stages.leaving)) { - // ... - } - } - - // END STAGES - - /** - * Filters the input (keybindings) - */ - filterInput() { - return this.stage === stages.s10_gameRunning; - } - - /** - * @param {GameCreationPayload} payload - */ - onEnter(payload) { - this.app.inputMgr.installFilter(this.boundInputFilter); - - this.creationPayload = payload; - this.savegame = payload.savegame; - - this.loadingOverlay = new GameLoadingOverlay(this.app, this.getDivElement()); - this.loadingOverlay.showBasic(); - - // Remove unneded default element - document.body.querySelector(".modalDialogParent").remove(); - - this.asyncChannel.watch(waitNextFrame()).then(() => this.stage3CreateCore()); - } - - /** - * Render callback - * @param {number} dt - */ - onRender(dt) { - if (APPLICATION_ERROR_OCCURED) { - // Application somehow crashed, do not do anything - return; - } - - if (this.stage === stages.s7_warmup) { - this.core.draw(); - this.warmupTimeSeconds -= dt / 1000.0; - if (this.warmupTimeSeconds < 0) { - logger.log("Warmup completed"); - this.stage10GameRunning(); - } - } - - // // 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); - } - - // If the stage is still active (This might not be the case if tick() moved us to game over) - if (this.stage === stages.s10_gameRunning) { - // Only draw if page visible - if (this.app.pageVisible) { - this.core.draw(); - } - - this.loadingOverlay.removeIfAttached(); - } else { - if (!this.loadingOverlay.isAttached()) { - this.loadingOverlay.showBasic(); - } - } - } - - onBackgroundTick(dt) { - this.onRender(dt); - } - - /** - * Saves the game - */ - - doSave() { - if (!this.savegame || !this.savegame.isSaveable()) { - return Promise.resolve(); - } - - if (APPLICATION_ERROR_OCCURED) { - logger.warn("skipping save because application crashed"); - return Promise.resolve(); - } - - if ( - this.stage !== stages.s10_gameRunning && - this.stage !== stages.s7_warmup && - this.stage !== stages.leaving - ) { - logger.warn("Skipping save because game is not ready"); - return Promise.resolve(); - } - - // First update the game data - logger.log("Starting to save game ..."); - this.core.root.signals.gameSaved.dispatch(); - this.savegame.updateData(this.core.root); - return this.savegame.writeSavegameAndMetadata().catch(err => { - logger.warn("Failed to save:", err); - }); - } -} +import { APPLICATION_ERROR_OCCURED } from "../core/error_handler"; +import { GameState } from "../core/game_state"; +import { logSection, createLogger } from "../core/logging"; +import { waitNextFrame } from "../core/utils"; +import { globalConfig } from "../core/config"; +import { GameLoadingOverlay } from "../game/game_loading_overlay"; +import { KeyActionMapper } from "../game/key_action_mapper"; +import { Savegame } from "../savegame/savegame"; +import { GameCore } from "../game/core"; +import { MUSIC } from "../platform/sound"; + +const logger = createLogger("state/ingame"); + +// Different sub-states +const stages = { + s3_createCore: "🌈 3: Create core", + s4_A_initEmptyGame: "🌈 4/A: Init empty game", + s4_B_resumeGame: "🌈 4/B: Resume game", + + s5_firstUpdate: "🌈 5: First game update", + s6_postLoadHook: "🌈 6: Post load hook", + s7_warmup: "🌈 7: Warmup", + + s10_gameRunning: "🌈 10: Game finally running", + + leaving: "🌈 Saving, then leaving the game", + destroyed: "🌈 DESTROYED: Core is empty and waits for state leave", + initFailed: "🌈 ERROR: Initialization failed!", +}; + +export const gameCreationAction = { + new: "new-game", + resume: "resume-game", +}; + +// Typehints +export class GameCreationPayload { + constructor() { + /** @type {boolean|undefined} */ + this.fastEnter; + + /** @type {Savegame} */ + this.savegame; + } +} + +export class InGameState extends GameState { + constructor() { + super("InGameState"); + + /** @type {GameCreationPayload} */ + this.creationPayload = null; + + // Stores current stage + this.stage = ""; + + /** @type {GameCore} */ + this.core = null; + + /** @type {KeyActionMapper} */ + this.keyActionMapper = null; + + /** @type {GameLoadingOverlay} */ + this.loadingOverlay = null; + + /** @type {Savegame} */ + this.savegame = null; + + this.boundInputFilter = this.filterInput.bind(this); + + /** + * Whether we are currently saving the game + * @TODO: This doesn't realy fit here + */ + this.currentSavePromise = null; + } + + /** + * Switches the game into another sub-state + * @param {string} stage + */ + switchStage(stage) { + assert(stage, "Got empty stage"); + if (stage !== this.stage) { + this.stage = stage; + logger.log(this.stage); + return true; + } else { + // log(this, "Re entering", stage); + return false; + } + } + + // GameState implementation + getInnerHTML() { + return ""; + } + + getThemeMusic() { + return MUSIC.theme; + } + + onBeforeExit() { + // logger.log("Saving before quitting"); + // return this.doSave().then(() => { + // logger.log(this, "Successfully saved"); + // // this.stageDestroyed(); + // }); + } + + onAppPause() { + // if (this.stage === stages.s10_gameRunning) { + // logger.log("Saving because app got paused"); + // this.doSave(); + // } + } + + getHasFadeIn() { + return false; + } + + getPauseOnFocusLost() { + return false; + } + + getHasUnloadConfirmation() { + return true; + } + + onLeave() { + if (this.core) { + this.stageDestroyed(); + } + this.app.inputMgr.dismountFilter(this.boundInputFilter); + } + + onResized(w, h) { + super.onResized(w, h); + if (this.stage === stages.s10_gameRunning) { + this.core.resize(w, h); + } + } + + // ---- End of GameState implementation + + /** + * Goes back to the menu state + */ + goBackToMenu() { + this.saveThenGoToState("MainMenuState"); + } + + /** + * Goes back to the settings state + */ + goToSettings() { + this.saveThenGoToState("SettingsState", { + backToStateId: this.key, + backToStatePayload: this.creationPayload, + }); + } + + /** + * Goes back to the settings state + */ + goToKeybindings() { + this.saveThenGoToState("KeybindingsState", { + backToStateId: this.key, + backToStatePayload: this.creationPayload, + }); + } + + /** + * Moves to a state outside of the game + * @param {string} stateId + * @param {any=} payload + */ + saveThenGoToState(stateId, payload) { + if (this.stage === stages.leaving || this.stage === stages.destroyed) { + logger.warn( + "Tried to leave game twice or during destroy:", + this.stage, + "(attempted to move to", + stateId, + ")" + ); + return; + } + this.stageLeavingGame(); + this.doSave().then(() => { + this.stageDestroyed(); + this.moveToState(stateId, payload); + }); + } + + onBackButton() { + // do nothing + } + + /** + * Called when the game somehow failed to initialize. Resets everything to basic state and + * then goes to the main menu, showing the error + * @param {string} err + */ + onInitializationFailure(err) { + if (this.switchStage(stages.initFailed)) { + logger.error("Init failure:", err); + this.stageDestroyed(); + this.moveToState("MainMenuState", { loadError: err }); + } + } + + // STAGES + + /** + * Creates the game core instance, and thus the root + */ + stage3CreateCore() { + if (this.switchStage(stages.s3_createCore)) { + logger.log("Creating new game core"); + this.core = new GameCore(this.app); + + this.core.initializeRoot(this, this.savegame); + + if (this.savegame.hasGameDump()) { + this.stage4bResumeGame(); + } else { + this.app.gameAnalytics.handleGameStarted(); + this.stage4aInitEmptyGame(); + } + } + } + + /** + * Initializes a new empty game + */ + stage4aInitEmptyGame() { + if (this.switchStage(stages.s4_A_initEmptyGame)) { + this.core.initNewGame(); + this.stage5FirstUpdate(); + } + } + + /** + * Resumes an existing game + */ + stage4bResumeGame() { + if (this.switchStage(stages.s4_B_resumeGame)) { + if (!this.core.initExistingGame()) { + this.onInitializationFailure("Savegame is corrupt and can not be restored."); + return; + } + this.app.gameAnalytics.handleGameResumed(); + this.stage5FirstUpdate(); + } + } + + /** + * Performs the first game update on the game which initializes most caches + */ + stage5FirstUpdate() { + if (this.switchStage(stages.s5_firstUpdate)) { + this.core.root.logicInitialized = true; + this.core.updateLogic(); + this.stage6PostLoadHook(); + } + } + + /** + * Call the post load hook, this means that we have loaded the game, and all systems + * can operate and start to work now. + */ + stage6PostLoadHook() { + if (this.switchStage(stages.s6_postLoadHook)) { + logger.log("Post load hook"); + this.core.postLoadHook(); + this.stage7Warmup(); + } + } + + /** + * This makes the game idle and draw for a while, because we run most code this way + * the V8 engine can already start to optimize it. Also this makes sure the resources + * are in the VRAM and we have a smooth experience once we start. + */ + stage7Warmup() { + if (this.switchStage(stages.s7_warmup)) { + if (this.creationPayload.fastEnter) { + this.warmupTimeSeconds = globalConfig.warmupTimeSecondsFast; + } else { + this.warmupTimeSeconds = globalConfig.warmupTimeSecondsRegular; + } + } + } + + /** + * The final stage where this game is running and updating regulary. + */ + stage10GameRunning() { + if (this.switchStage(stages.s10_gameRunning)) { + this.core.root.signals.readyToRender.dispatch(); + + logSection("GAME STARTED", "#26a69a"); + + // Initial resize, might have changed during loading (this is possible) + this.core.resize(this.app.screenWidth, this.app.screenHeight); + } + } + + /** + * This stage destroys the whole game, used to cleanup + */ + stageDestroyed() { + if (this.switchStage(stages.destroyed)) { + // Cleanup all api calls + this.cancelAllAsyncOperations(); + + if (this.syncer) { + this.syncer.cancelSync(); + this.syncer = null; + } + + // Cleanup core + if (this.core) { + this.core.destruct(); + this.core = null; + } + } + } + + /** + * When leaving the game + */ + stageLeavingGame() { + if (this.switchStage(stages.leaving)) { + // ... + } + } + + // END STAGES + + /** + * Filters the input (keybindings) + */ + filterInput() { + return this.stage === stages.s10_gameRunning; + } + + /** + * @param {GameCreationPayload} payload + */ + onEnter(payload) { + this.app.inputMgr.installFilter(this.boundInputFilter); + + this.creationPayload = payload; + this.savegame = payload.savegame; + + this.loadingOverlay = new GameLoadingOverlay(this.app, this.getDivElement()); + this.loadingOverlay.showBasic(); + + // Remove unneded default element + document.body.querySelector(".modalDialogParent").remove(); + + this.asyncChannel.watch(waitNextFrame()).then(() => this.stage3CreateCore()); + } + + /** + * Render callback + * @param {number} dt + */ + onRender(dt) { + if (APPLICATION_ERROR_OCCURED) { + // Application somehow crashed, do not do anything + return; + } + + if (this.stage === stages.s7_warmup) { + this.core.draw(); + this.warmupTimeSeconds -= dt / 1000.0; + if (this.warmupTimeSeconds < 0) { + logger.log("Warmup completed"); + this.stage10GameRunning(); + } + } + + if (this.stage === stages.s10_gameRunning) { + this.core.tick(dt); + } + + // If the stage is still active (This might not be the case if tick() moved us to game over) + if (this.stage === stages.s10_gameRunning) { + // Only draw if page visible + if (this.app.pageVisible) { + this.core.draw(); + } + + this.loadingOverlay.removeIfAttached(); + } else { + if (!this.loadingOverlay.isAttached()) { + this.loadingOverlay.showBasic(); + } + } + } + + onBackgroundTick(dt) { + this.onRender(dt); + } + + /** + * Saves the game + */ + + doSave() { + if (!this.savegame || !this.savegame.isSaveable()) { + return Promise.resolve(); + } + + if (APPLICATION_ERROR_OCCURED) { + logger.warn("skipping save because application crashed"); + return Promise.resolve(); + } + + if ( + this.stage !== stages.s10_gameRunning && + this.stage !== stages.s7_warmup && + this.stage !== stages.leaving + ) { + logger.warn("Skipping save because game is not ready"); + return Promise.resolve(); + } + + if (this.currentSavePromise) { + logger.warn("Skipping double save and returning same promise"); + return this.currentSavePromise; + } + logger.log("Starting to save game ..."); + this.savegame.updateData(this.core.root); + + this.currentSavePromise = this.savegame + .writeSavegameAndMetadata() + .catch(err => { + // Catch errors + logger.warn("Failed to save:", err); + }) + .then(() => { + // Clear promise + logger.log("Saved!"); + this.core.root.signals.gameSaved.dispatch(); + this.currentSavePromise = null; + }); + + return this.currentSavePromise; + } +} diff --git a/src/js/states/keybindings.js b/src/js/states/keybindings.js index b68626c7..a01629f1 100644 --- a/src/js/states/keybindings.js +++ b/src/js/states/keybindings.js @@ -1,179 +1,173 @@ -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 { IS_DEMO } from "../core/config"; - -export class KeybindingsState extends TextualGameState { - constructor() { - super("KeybindingsState"); - } - - getStateHeaderTitle() { - return T.keybindings.title; - } - - getMainContentHTML() { - return ` - -
- ${T.keybindings.hint} - - -
- -
- -
- `; - } - - onEnter() { - const keybindingsElem = this.htmlElement.querySelector(".keybindings"); - - this.trackClicks(this.htmlElement.querySelector(".resetBindings"), this.resetBindings); - - for (const category in KEYMAPPINGS) { - const categoryDiv = document.createElement("div"); - categoryDiv.classList.add("category"); - keybindingsElem.appendChild(categoryDiv); - - const labelDiv = document.createElement("strong"); - labelDiv.innerText = T.keybindings.categoryLabels[category]; - labelDiv.classList.add("categoryLabel"); - categoryDiv.appendChild(labelDiv); - - for (const keybindingId in KEYMAPPINGS[category]) { - const mapped = KEYMAPPINGS[category][keybindingId]; - - const elem = document.createElement("div"); - elem.classList.add("entry"); - elem.setAttribute("data-keybinding", keybindingId); - categoryDiv.appendChild(elem); - - const title = document.createElement("span"); - title.classList.add("title"); - title.innerText = T.keybindings.mappings[keybindingId]; - elem.appendChild(title); - - const mappingDiv = document.createElement("span"); - mappingDiv.classList.add("mapping"); - elem.appendChild(mappingDiv); - - const editBtn = document.createElement("button"); - editBtn.classList.add("styledButton", "editKeybinding"); - - const resetBtn = document.createElement("button"); - resetBtn.classList.add("styledButton", "resetKeybinding"); - - if (mapped.builtin) { - editBtn.classList.add("disabled"); - resetBtn.classList.add("disabled"); - } else { - this.trackClicks(editBtn, () => this.editKeybinding(keybindingId)); - this.trackClicks(resetBtn, () => this.resetKeybinding(keybindingId)); - } - elem.appendChild(editBtn); - elem.appendChild(resetBtn); - } - } - this.updateKeybindings(); - } - - editKeybinding(id) { - // if (IS_DEMO) { - // this.dialogs.showFeatureRestrictionInfo(T.demo.features.customizeKeybindings); - // return; - // } - - const dialog = new Dialog({ - app: this.app, - title: T.dialogs.editKeybinding.title, - contentHTML: T.dialogs.editKeybinding.desc, - buttons: ["cancel:good"], - type: "info", - }); - - dialog.inputReciever.keydown.add(({ keyCode, shift, alt, event }) => { - if (keyCode === 27) { - this.dialogs.closeDialog(dialog); - return; - } - - if (event) { - event.preventDefault(); - } - - if (event.target && event.target.tagName === "BUTTON" && keyCode === 1) { - return; - } - - if ( - // Enter - keyCode === 13 - ) { - // Ignore builtins - return; - } - - this.app.settings.updateKeybindingOverride(id, keyCode); - - this.dialogs.closeDialog(dialog); - this.updateKeybindings(); - }); - - dialog.inputReciever.backButton.add(() => {}); - this.dialogs.internalShowDialog(dialog); - - this.app.sound.playUiSound(SOUNDS.dialogOk); - } - - updateKeybindings() { - const overrides = this.app.settings.getKeybindingOverrides(); - for (const category in KEYMAPPINGS) { - for (const keybindingId in KEYMAPPINGS[category]) { - const mapped = KEYMAPPINGS[category][keybindingId]; - - const container = this.htmlElement.querySelector("[data-keybinding='" + keybindingId + "']"); - assert(container, "Container for keybinding not found: " + keybindingId); - - let keyCode = mapped.keyCode; - if (overrides[keybindingId]) { - keyCode = overrides[keybindingId]; - } - - const mappingDiv = container.querySelector(".mapping"); - mappingDiv.innerHTML = getStringForKeyCode(keyCode); - mappingDiv.classList.toggle("changed", !!overrides[keybindingId]); - - const resetBtn = container.querySelector("button.resetKeybinding"); - resetBtn.classList.toggle("disabled", mapped.builtin || !overrides[keybindingId]); - } - } - } - - resetKeybinding(id) { - this.app.settings.resetKeybindingOverride(id); - this.updateKeybindings(); - } - - resetBindings() { - const { reset } = this.dialogs.showWarning( - T.dialogs.resetKeybindingsConfirmation.title, - T.dialogs.resetKeybindingsConfirmation.desc, - ["cancel:good", "reset:bad"] - ); - - reset.add(() => { - this.app.settings.resetKeybindingOverrides(); - this.updateKeybindings(); - - this.dialogs.showInfo(T.dialogs.keybindingsResetOk.title, T.dialogs.keybindingsResetOk.desc); - }); - } - - getDefaultPreviousState() { - return "SettingsState"; - } -} +import { Dialog } from "../core/modal_dialog_elements"; +import { TextualGameState } from "../core/textual_game_state"; +import { getStringForKeyCode, KEYMAPPINGS } from "../game/key_action_mapper"; +import { SOUNDS } from "../platform/sound"; +import { T } from "../translations"; + +export class KeybindingsState extends TextualGameState { + constructor() { + super("KeybindingsState"); + } + + getStateHeaderTitle() { + return T.keybindings.title; + } + + getMainContentHTML() { + return ` + +
+ ${T.keybindings.hint} + + +
+ +
+ +
+ `; + } + + onEnter() { + const keybindingsElem = this.htmlElement.querySelector(".keybindings"); + + this.trackClicks(this.htmlElement.querySelector(".resetBindings"), this.resetBindings); + + for (const category in KEYMAPPINGS) { + const categoryDiv = document.createElement("div"); + categoryDiv.classList.add("category"); + keybindingsElem.appendChild(categoryDiv); + + const labelDiv = document.createElement("strong"); + labelDiv.innerText = T.keybindings.categoryLabels[category]; + labelDiv.classList.add("categoryLabel"); + categoryDiv.appendChild(labelDiv); + + for (const keybindingId in KEYMAPPINGS[category]) { + const mapped = KEYMAPPINGS[category][keybindingId]; + + const elem = document.createElement("div"); + elem.classList.add("entry"); + elem.setAttribute("data-keybinding", keybindingId); + categoryDiv.appendChild(elem); + + const title = document.createElement("span"); + title.classList.add("title"); + title.innerText = T.keybindings.mappings[keybindingId]; + elem.appendChild(title); + + const mappingDiv = document.createElement("span"); + mappingDiv.classList.add("mapping"); + elem.appendChild(mappingDiv); + + const editBtn = document.createElement("button"); + editBtn.classList.add("styledButton", "editKeybinding"); + + const resetBtn = document.createElement("button"); + resetBtn.classList.add("styledButton", "resetKeybinding"); + + if (mapped.builtin) { + editBtn.classList.add("disabled"); + resetBtn.classList.add("disabled"); + } else { + this.trackClicks(editBtn, () => this.editKeybinding(keybindingId)); + this.trackClicks(resetBtn, () => this.resetKeybinding(keybindingId)); + } + elem.appendChild(editBtn); + elem.appendChild(resetBtn); + } + } + this.updateKeybindings(); + } + + editKeybinding(id) { + const dialog = new Dialog({ + app: this.app, + title: T.dialogs.editKeybinding.title, + contentHTML: T.dialogs.editKeybinding.desc, + buttons: ["cancel:good"], + type: "info", + }); + + dialog.inputReciever.keydown.add(({ keyCode, shift, alt, event }) => { + if (keyCode === 27) { + this.dialogs.closeDialog(dialog); + return; + } + + if (event) { + event.preventDefault(); + } + + if (event.target && event.target.tagName === "BUTTON" && keyCode === 1) { + return; + } + + if ( + // Enter + keyCode === 13 + ) { + // Ignore builtins + return; + } + + this.app.settings.updateKeybindingOverride(id, keyCode); + + this.dialogs.closeDialog(dialog); + this.updateKeybindings(); + }); + + dialog.inputReciever.backButton.add(() => {}); + this.dialogs.internalShowDialog(dialog); + + this.app.sound.playUiSound(SOUNDS.dialogOk); + } + + updateKeybindings() { + const overrides = this.app.settings.getKeybindingOverrides(); + for (const category in KEYMAPPINGS) { + for (const keybindingId in KEYMAPPINGS[category]) { + const mapped = KEYMAPPINGS[category][keybindingId]; + + const container = this.htmlElement.querySelector("[data-keybinding='" + keybindingId + "']"); + assert(container, "Container for keybinding not found: " + keybindingId); + + let keyCode = mapped.keyCode; + if (overrides[keybindingId]) { + keyCode = overrides[keybindingId]; + } + + const mappingDiv = container.querySelector(".mapping"); + mappingDiv.innerHTML = getStringForKeyCode(keyCode); + mappingDiv.classList.toggle("changed", !!overrides[keybindingId]); + + const resetBtn = container.querySelector("button.resetKeybinding"); + resetBtn.classList.toggle("disabled", mapped.builtin || !overrides[keybindingId]); + } + } + } + + resetKeybinding(id) { + this.app.settings.resetKeybindingOverride(id); + this.updateKeybindings(); + } + + resetBindings() { + const { reset } = this.dialogs.showWarning( + T.dialogs.resetKeybindingsConfirmation.title, + T.dialogs.resetKeybindingsConfirmation.desc, + ["cancel:good", "reset:bad"] + ); + + reset.add(() => { + this.app.settings.resetKeybindingOverrides(); + this.updateKeybindings(); + + this.dialogs.showInfo(T.dialogs.keybindingsResetOk.title, T.dialogs.keybindingsResetOk.desc); + }); + } + + getDefaultPreviousState() { + return "SettingsState"; + } +} diff --git a/src/js/states/main_menu.js b/src/js/states/main_menu.js index cf7a05ac..fa177874 100644 --- a/src/js/states/main_menu.js +++ b/src/js/states/main_menu.js @@ -1,530 +1,576 @@ -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 { cachebust } from "../core/cachebust"; +import { A_B_TESTING_LINK_TYPE, globalConfig, THIRDPARTY_URLS } from "../core/config"; +import { GameState } from "../core/game_state"; +import { DialogWithForm } from "../core/modal_dialog_elements"; +import { FormElementInput } from "../core/modal_dialog_forms"; +import { ReadWriteProxy } from "../core/read_write_proxy"; +import { + formatSecondsToTimeAgo, + generateFileDownload, + isSupportedBrowser, + makeButton, + makeButtonElement, + makeDiv, + removeAllChildren, + startFileChoose, + waitNextFrame, +} from "../core/utils"; +import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs"; +import { getApplicationSettingById } from "../profile/application_settings"; +import { T } from "../translations"; + +const trim = require("trim"); + +/** + * @typedef {import("../savegame/savegame_typedefs").SavegameMetadata} SavegameMetadata + * @typedef {import("../profile/setting_types").EnumSetting} EnumSetting + */ + +export class MainMenuState extends GameState { + constructor() { + super("MainMenuState"); + } + + getInnerHTML() { + const bannerHtml = ` +

${T.demoBanners.title}

+

${T.demoBanners.intro}

+ Get the shapez.io standalone! + `; + + const showDemoBadges = this.app.restrictionMgr.getIsStandaloneMarketingActive(); + + return ` +
+ + + ${ + G_IS_STANDALONE || G_IS_DEV + ? ` + + ` + : "" + } +
+ + + + + +
+
+ ${showDemoBadges ? `
${bannerHtml}
` : ""} +
+ +
+ ${ + isSupportedBrowser() + ? "" + : `
${T.mainMenu.browserWarning}
` + } +
+
+
+ + + `; + } + + /** + * Asks the user to import a savegame + */ + requestImportSavegame() { + if ( + this.app.savegameMgr.getSavegamesMetaData().length > 0 && + !this.app.restrictionMgr.getHasUnlimitedSavegames() + ) { + this.app.analytics.trackUiClick("importgame_slot_limit_show"); + this.showSavegameSlotLimit(); + return; + } + + // Create a 'fake' file-input to accept savegames + startFileChoose(".bin").then(file => { + if (file) { + const closeLoader = this.dialogs.showLoadingDialog(); + waitNextFrame().then(() => { + this.app.analytics.trackUiClick("import_savegame"); + 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"); + }); + } + }); + } + + 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_" + A_B_TESTING_LINK_TYPE); + this.app.platformWrapper.openExternalLink( + THIRDPARTY_URLS.standaloneStorePage + "?ref=mmsl2&prc=" + A_B_TESTING_LINK_TYPE + ); + + 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).then(() => { + 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) && trim(val).length > 0, + }); + 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 = trim(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 + .replace("", game.name || T.mainMenu.savegameUnnamed) + .replace("", String(game.level)), + ["cancel:good", "delete:bad:timeout"] + ); + + 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); + }); + } + + /** + * Shows a hint that the slot limit has been reached + */ + showSavegameSlotLimit() { + const { getStandalone } = this.dialogs.showWarning( + T.dialogs.oneSavegameLimit.title, + T.dialogs.oneSavegameLimit.desc, + ["cancel:bad", "getStandalone:good"] + ); + getStandalone.add(() => { + this.app.analytics.trackUiClick("visit_steampage_from_slot_limit"); + this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.standaloneStorePage + "?reF=ssll"); + }); + } + + 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 ( + this.app.savegameMgr.getSavegamesMetaData().length > 0 && + !this.app.restrictionMgr.getHasUnlimitedSavegames() + ) { + this.app.analytics.trackUiClick("startgame_slot_limit_show"); + this.showSavegameSlotLimit(); + 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..98eb1cd8 100644 --- a/src/js/states/mobile_warning.js +++ b/src/js/states/mobile_warning.js @@ -17,11 +17,11 @@ 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:

Get the shapez.io standalone! `; } diff --git a/src/js/states/preload.js b/src/js/states/preload.js index eee57f05..811b9419 100644 --- a/src/js/states/preload.js +++ b/src/js/states/preload.js @@ -1,298 +1,319 @@ -import { GameState } from "../core/game_state"; -import { createLogger } from "../core/logging"; -import { findNiceValue, waitNextFrame } from "../core/utils"; -import { cachebust } from "../core/cachebust"; -import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper"; -import { T, autoDetectLanguageId, updateApplicationLanguage } from "../translations"; -import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs"; -import { CHANGELOG } from "../changelog"; -import { globalConfig } from "../core/config"; - -const logger = createLogger("state/preload"); - -export class PreloadState extends GameState { - constructor() { - super("PreloadState"); - } - - getInnerHTML() { - return ` -
-
- Booting - - - 0% - -
-
- `; - } - - getThemeMusic() { - return null; - } - - getHasFadeIn() { - return false; - } - - onEnter(payload) { - this.htmlElement.classList.add("prefab_LoadingState"); - - const elementsToRemove = ["#loadingPreload", "#fontPreload"]; - for (let i = 0; i < elementsToRemove.length; ++i) { - const elem = document.querySelector(elementsToRemove[i]); - if (elem) { - elem.remove(); - } - } - - this.dialogs = new HUDModalDialogs(null, this.app); - const dialogsElement = document.body.querySelector(".modalDialogParent"); - this.dialogs.initializeToElement(dialogsElement); - - this.statusText = this.htmlElement.querySelector(".loadingStatus > .desc"); - this.statusBar = this.htmlElement.querySelector(".loadingStatus > .bar > .inner"); - this.statusBarText = this.htmlElement.querySelector(".loadingStatus > .bar > .status"); - this.currentStatus = "booting"; - this.currentIndex = 0; - - this.startLoading(); - } - - onLeave() { - // this.dialogs.cleanup(); - } - - startLoading() { - this.setStatus("Booting") - - .then(() => this.setStatus("Creating platform wrapper")) - .then(() => this.app.platformWrapper.initialize()) - - .then(() => this.setStatus("Initializing local storage")) - .then(() => { - const wrapper = this.app.platformWrapper; - if (wrapper instanceof PlatformWrapperImplBrowser) { - try { - window.localStorage.setItem("local_storage_test", "1"); - window.localStorage.removeItem("local_storage_test"); - } catch (ex) { - logger.error("Failed to read/write local storage:", ex); - return new Promise(() => { - alert(`Your brower does not support thirdparty cookies or you have disabled it in your security settings.\n\n - In Chrome this setting is called "Block third-party cookies and site data".\n\n - Please allow third party cookies and then reload the page.`); - // Never return - }); - } - } - }) - - .then(() => this.setStatus("Creating storage")) - .then(() => { - return this.app.storage.initialize(); - }) - - .then(() => this.setStatus("Initializing libraries")) - .then(() => this.app.analytics.initialize()) - .then(() => this.app.gameAnalytics.initialize()) - - .then(() => this.setStatus("Initializing settings")) - .then(() => { - return this.app.settings.initialize(); - }) - - .then(() => { - // Initialize fullscreen - if (this.app.platformWrapper.getSupportsFullscreen()) { - this.app.platformWrapper.setFullscreen(this.app.settings.getIsFullScreen()); - } - }) - - .then(() => this.setStatus("Initializing language")) - .then(() => { - if (this.app.settings.getLanguage() === "auto-detect") { - const language = autoDetectLanguageId(); - logger.log("Setting language to", language); - return this.app.settings.updateLanguage(language); - } - }) - .then(() => { - const language = this.app.settings.getLanguage(); - updateApplicationLanguage(language); - }) - - .then(() => this.setStatus("Initializing sounds")) - .then(() => { - // Notice: We don't await the sounds loading itself - return this.app.sound.initialize(); - }) - - .then(() => { - this.app.backgroundResourceLoader.startLoading(); - }) - - .then(() => this.setStatus("Initializing savegame")) - .then(() => { - return this.app.savegameMgr.initialize().catch(err => { - logger.error("Failed to initialize savegames:", err); - alert( - "Your savegames failed to load, it seems your data files got corrupted. I'm so sorry!\n\n(This can happen if your pc crashed while a game was saved).\n\nYou can try re-importing your savegames." - ); - return this.app.savegameMgr.writeAsync(); - }); - }) - - .then(() => this.setStatus("Downloading resources")) - .then(() => { - return this.app.backgroundResourceLoader.getPromiseForBareGame(); - }) - - .then(() => this.setStatus("Checking changelog")) - .then(() => { - if (G_IS_DEV && globalConfig.debug.disableUpgradeNotification) { - return; - } - - return this.app.storage - .readFileAsync("lastversion.bin") - .catch(err => { - logger.warn("Failed to read lastversion:", err); - return G_BUILD_VERSION; - }) - .then(version => { - logger.log("Last version:", version, "App version:", G_BUILD_VERSION); - this.app.storage.writeFileAsync("lastversion.bin", G_BUILD_VERSION); - return version; - }) - .then(version => { - let changelogEntries = []; - logger.log("Last seen version:", version); - - for (let i = 0; i < CHANGELOG.length; ++i) { - if (CHANGELOG[i].version === version) { - break; - } - changelogEntries.push(CHANGELOG[i]); - } - if (changelogEntries.length === 0) { - return; - } - - let dialogHtml = T.dialogs.updateSummary.desc; - for (let i = 0; i < changelogEntries.length; ++i) { - const entry = changelogEntries[i]; - dialogHtml += ` -
- ${entry.version} - ${entry.date} -
    - ${entry.entries.map(text => `
  • ${text}
  • `).join("")} -
-
- `; - } - - return new Promise(resolve => { - this.dialogs.showInfo(T.dialogs.updateSummary.title, dialogHtml).ok.add(resolve); - }); - }); - }) - - .then(() => this.setStatus("Launching")) - .then( - () => { - this.moveToState("MainMenuState"); - }, - err => { - this.showFailMessage(err); - } - ); - } - - setStatus(text) { - logger.log("✅ " + text); - this.currentIndex += 1; - this.currentStatus = text; - this.statusText.innerText = text; - - const numSteps = 10; // FIXME - - const percentage = (this.currentIndex / numSteps) * 100.0; - this.statusBar.style.width = percentage + "%"; - this.statusBarText.innerText = findNiceValue(percentage) + "%"; - - if (G_IS_DEV) { - return Promise.resolve(); - } - return Promise.resolve(); - // return waitNextFrame(); - } - - showFailMessage(text) { - logger.error("App init failed:", text); - - const email = "bugs@shapez.io"; - - const subElement = document.createElement("div"); - subElement.classList.add("failureBox"); - - subElement.innerHTML = ` - -
-
- Failed to initialize application! -
-
- ${this.currentStatus} failed:
- ${text} -
- -
- Please send me an email with steps to reproduce and what you did before this happened: -
-
- -
- - Build ${G_BUILD_VERSION} @ ${G_BUILD_COMMIT_HASH} -
-
- `; - - this.htmlElement.classList.add("failure"); - this.htmlElement.appendChild(subElement); - - const resetBtn = subElement.querySelector("button.resetApp"); - this.trackClicks(resetBtn, this.showResetConfirm); - } - - showResetConfirm() { - 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() { - this.app.settings - .resetEverythingAsync() - .then(() => { - this.app.savegameMgr.resetEverythingAsync(); - }) - .then(() => { - this.app.settings.resetEverythingAsync(); - }) - .then(() => { - window.location.reload(); - }); - } -} +import { CHANGELOG } from "../changelog"; +import { cachebust } from "../core/cachebust"; +import { globalConfig } from "../core/config"; +import { GameState } from "../core/game_state"; +import { createLogger } from "../core/logging"; +import { findNiceValue } from "../core/utils"; +import { getRandomHint } from "../game/hints"; +import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs"; +import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper"; +import { autoDetectLanguageId, T, updateApplicationLanguage } from "../translations"; + +const logger = createLogger("state/preload"); + +export class PreloadState extends GameState { + constructor() { + super("PreloadState"); + } + + getInnerHTML() { + return ` +
+
+ Booting +
+
+ + `; + } + + getThemeMusic() { + return null; + } + + getHasFadeIn() { + return false; + } + + onEnter() { + this.htmlElement.classList.add("prefab_LoadingState"); + + const elementsToRemove = ["#loadingPreload", "#fontPreload"]; + for (let i = 0; i < elementsToRemove.length; ++i) { + const elem = document.querySelector(elementsToRemove[i]); + if (elem) { + elem.remove(); + } + } + + this.dialogs = new HUDModalDialogs(null, this.app); + const dialogsElement = document.body.querySelector(".modalDialogParent"); + this.dialogs.initializeToElement(dialogsElement); + + /** @type {HTMLElement} */ + this.statusText = this.htmlElement.querySelector(".loadingStatus > .desc"); + + /** @type {HTMLElement} */ + this.hintsText = this.htmlElement.querySelector(".prefab_GameHint"); + this.lastHintShown = -1000; + this.nextHintDuration = 0; + + this.currentStatus = "booting"; + + this.startLoading(); + } + + onLeave() { + // this.dialogs.cleanup(); + } + + startLoading() { + this.setStatus("Booting") + + .then(() => this.setStatus("Creating platform wrapper")) + .then(() => this.app.platformWrapper.initialize()) + + .then(() => this.setStatus("Initializing local storage")) + .then(() => { + const wrapper = this.app.platformWrapper; + if (wrapper instanceof PlatformWrapperImplBrowser) { + try { + window.localStorage.setItem("local_storage_test", "1"); + window.localStorage.removeItem("local_storage_test"); + } catch (ex) { + logger.error("Failed to read/write local storage:", ex); + return new Promise(() => { + alert(`Your brower does not support thirdparty cookies or you have disabled it in your security settings.\n\n + In Chrome this setting is called "Block third-party cookies and site data".\n\n + Please allow third party cookies and then reload the page.`); + // Never return + }); + } + } + }) + + .then(() => this.setStatus("Creating storage")) + .then(() => { + return this.app.storage.initialize(); + }) + + .then(() => this.setStatus("Initializing libraries")) + .then(() => this.app.analytics.initialize()) + .then(() => this.app.gameAnalytics.initialize()) + + .then(() => this.setStatus("Initializing settings")) + .then(() => { + return this.app.settings.initialize(); + }) + + .then(() => { + // Initialize fullscreen + if (this.app.platformWrapper.getSupportsFullscreen()) { + this.app.platformWrapper.setFullscreen(this.app.settings.getIsFullScreen()); + } + }) + + .then(() => this.setStatus("Initializing language")) + .then(() => { + if (this.app.settings.getLanguage() === "auto-detect") { + const language = autoDetectLanguageId(); + logger.log("Setting language to", language); + return this.app.settings.updateLanguage(language); + } + }) + .then(() => { + const language = this.app.settings.getLanguage(); + updateApplicationLanguage(language); + }) + + .then(() => this.setStatus("Initializing sounds")) + .then(() => { + // Notice: We don't await the sounds loading itself + return this.app.sound.initialize(); + }) + + .then(() => { + this.app.backgroundResourceLoader.startLoading(); + }) + + .then(() => this.setStatus("Initializing restrictions")) + .then(() => { + return this.app.restrictionMgr.initialize(); + }) + + .then(() => this.setStatus("Initializing savegame")) + .then(() => { + return this.app.savegameMgr.initialize().catch(err => { + logger.error("Failed to initialize savegames:", err); + alert( + "Your savegames failed to load, it seems your data files got corrupted. I'm so sorry!\n\n(This can happen if your pc crashed while a game was saved).\n\nYou can try re-importing your savegames." + ); + return this.app.savegameMgr.writeAsync(); + }); + }) + + .then(() => this.setStatus("Downloading resources")) + .then(() => { + return this.app.backgroundResourceLoader.getPromiseForBareGame(); + }) + + .then(() => this.setStatus("Checking changelog")) + .then(() => { + if (G_IS_DEV && globalConfig.debug.disableUpgradeNotification) { + return; + } + + return this.app.storage + .readFileAsync("lastversion.bin") + .catch(err => { + logger.warn("Failed to read lastversion:", err); + return G_BUILD_VERSION; + }) + .then(version => { + logger.log("Last version:", version, "App version:", G_BUILD_VERSION); + this.app.storage.writeFileAsync("lastversion.bin", G_BUILD_VERSION); + return version; + }) + .then(version => { + let changelogEntries = []; + logger.log("Last seen version:", version); + + for (let i = 0; i < CHANGELOG.length; ++i) { + if (CHANGELOG[i].version === version) { + break; + } + changelogEntries.push(CHANGELOG[i]); + } + if (changelogEntries.length === 0) { + return; + } + + let dialogHtml = T.dialogs.updateSummary.desc; + for (let i = 0; i < changelogEntries.length; ++i) { + const entry = changelogEntries[i]; + dialogHtml += ` +
+ ${entry.version} + ${entry.date} +
    + ${entry.entries.map(text => `
  • ${text}
  • `).join("")} +
+
+ `; + } + + return new Promise(resolve => { + this.dialogs.showInfo(T.dialogs.updateSummary.title, dialogHtml).ok.add(resolve); + }); + }); + }) + + .then(() => this.setStatus("Launching")) + .then( + () => { + this.moveToState("MainMenuState"); + }, + err => { + this.showFailMessage(err); + } + ); + } + + update() { + const now = performance.now(); + if (now - this.lastHintShown > this.nextHintDuration) { + this.lastHintShown = now; + const hintText = getRandomHint(); + + this.hintsText.innerHTML = hintText; + + /** + * Compute how long the user will need to read the hint. + * We calculate with 130 words per minute, with an average of 5 chars + * that is 650 characters / minute + */ + this.nextHintDuration = Math.max(2500, (hintText.length / 650) * 60 * 1000); + } + } + + onRender() { + this.update(); + } + + onBackgroundTick() { + this.update(); + } + + /** + * + * @param {string} text + */ + setStatus(text) { + logger.log("✅ " + text); + this.currentStatus = text; + this.statusText.innerText = text; + return Promise.resolve(); + } + + showFailMessage(text) { + logger.error("App init failed:", text); + + const email = "bugs@shapez.io"; + + const subElement = document.createElement("div"); + subElement.classList.add("failureBox"); + + subElement.innerHTML = ` + +
+
+ Failed to initialize application! +
+
+ ${this.currentStatus} failed:
+ ${text} +
+ +
+ Please send me an email with steps to reproduce and what you did before this happened: +
+
+ +
+ + Build ${G_BUILD_VERSION} @ ${G_BUILD_COMMIT_HASH} +
+
+ `; + + this.htmlElement.classList.add("failure"); + this.htmlElement.appendChild(subElement); + + const resetBtn = subElement.querySelector("button.resetApp"); + this.trackClicks(resetBtn, this.showResetConfirm); + + this.hintsText.remove(); + } + + showResetConfirm() { + if (confirm("Are you sure you want to reset the app? This will delete all your savegames!")) { + this.resetApp(); + } + } + + resetApp() { + this.app.settings + .resetEverythingAsync() + .then(() => { + this.app.savegameMgr.resetEverythingAsync(); + }) + .then(() => { + this.app.settings.resetEverythingAsync(); + }) + .then(() => { + window.location.reload(); + }); + } +} diff --git a/src/js/states/settings.js b/src/js/states/settings.js index 4dce1fa3..36dee5d8 100644 --- a/src/js/states/settings.js +++ b/src/js/states/settings.js @@ -1,117 +1,169 @@ -import { TextualGameState } from "../core/textual_game_state"; -import { formatSecondsToTimeAgo } from "../core/utils"; -import { allApplicationSettings } from "../profile/application_settings"; -import { T } from "../translations"; - -export class SettingsState extends TextualGameState { - constructor() { - super("SettingsState"); - } - - getStateHeaderTitle() { - return T.settings.title; - } - - getMainContentHTML() { - return ` - - - - - ${this.getSettingsHtml()} -
-
${T.global.loading} ...
-
- - - `; - } - - getSettingsHtml() { - let lastCategory = null; - let html = ""; - for (let i = 0; i < allApplicationSettings.length; ++i) { - const setting = allApplicationSettings[i]; - - if (setting.categoryId !== lastCategory) { - lastCategory = setting.categoryId; - if (i !== 0) { - html += "
"; - } - html += `${T.settings.categories[lastCategory]}`; - html += "
"; - } - - html += setting.getHtml(); - } - if (lastCategory) { - html += "
"; - } - - return html; - } - - renderBuildText() { - const labelVersion = this.htmlElement.querySelector(".buildVersion"); - const lastBuildMs = new Date().getTime() - G_BUILD_TIME; - const lastBuildText = formatSecondsToTimeAgo(lastBuildMs / 1000.0); - - const version = T.settings.versionBadges[G_APP_ENVIRONMENT]; - - labelVersion.innerHTML = ` - - ${G_BUILD_VERSION} @ ${version} @ ${G_BUILD_COMMIT_HASH} - - - ${T.settings.buildDate.replace("", lastBuildText)}
-
`; - } - - onEnter(payload) { - this.renderBuildText(); - this.trackClicks(this.htmlElement.querySelector(".about"), this.onAboutClicked, { - preventDefault: false, - }); - - const keybindingsButton = this.htmlElement.querySelector(".editKeybindings"); - - if (keybindingsButton) { - this.trackClicks(keybindingsButton, this.onKeybindingsClicked, { preventDefault: false }); - } - - this.initSettings(); - } - - initSettings() { - allApplicationSettings.forEach(setting => { - const element = this.htmlElement.querySelector("[data-setting='" + setting.id + "']"); - setting.bind(this.app, element, this.dialogs); - setting.syncValueToElement(); - this.trackClicks( - element, - () => { - setting.modify(); - }, - { preventDefault: false } - ); - }); - } - - onAboutClicked() { - this.moveToStateAddGoBack("AboutState"); - } - - onKeybindingsClicked() { - this.moveToStateAddGoBack("KeybindingsState"); - } -} +import { TextualGameState } from "../core/textual_game_state"; +import { formatSecondsToTimeAgo } from "../core/utils"; +import { allApplicationSettings, enumCategories } from "../profile/application_settings"; +import { T } from "../translations"; + +export class SettingsState extends TextualGameState { + constructor() { + super("SettingsState"); + } + + getStateHeaderTitle() { + return T.settings.title; + } + + getMainContentHTML() { + return ` + + + +
+ ${this.getSettingsHtml()} +
+ + `; + } + + getCategoryButtonsHtml() { + return Object.keys(enumCategories) + .map(key => enumCategories[key]) + .map( + category => + ` + + ` + ) + .join(""); + } + + getSettingsHtml() { + const categoriesHTML = {}; + + Object.keys(enumCategories).forEach(key => { + const catName = enumCategories[key]; + categoriesHTML[catName] = `
`; + }); + + for (let i = 0; i < allApplicationSettings.length; ++i) { + const setting = allApplicationSettings[i]; + + categoriesHTML[setting.categoryId] += setting.getHtml(this.app); + } + + return Object.keys(categoriesHTML) + .map(k => categoriesHTML[k] + "
") + .join(""); + } + + renderBuildText() { + const labelVersion = this.htmlElement.querySelector(".buildVersion"); + const lastBuildMs = new Date().getTime() - G_BUILD_TIME; + const lastBuildText = formatSecondsToTimeAgo(lastBuildMs / 1000.0); + + const version = T.settings.versionBadges[G_APP_ENVIRONMENT]; + + labelVersion.innerHTML = ` + + ${G_BUILD_VERSION} @ ${version} @ ${G_BUILD_COMMIT_HASH} + + + ${T.settings.buildDate.replace("", lastBuildText)}
+
`; + } + + onEnter(payload) { + this.renderBuildText(); + this.trackClicks(this.htmlElement.querySelector(".about"), this.onAboutClicked, { + preventDefault: false, + }); + + const keybindingsButton = this.htmlElement.querySelector(".editKeybindings"); + + if (keybindingsButton) { + this.trackClicks(keybindingsButton, this.onKeybindingsClicked, { preventDefault: false }); + } + + 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(); + this.trackClicks( + element, + () => { + setting.modify(); + }, + { preventDefault: false } + ); + }); + } + + 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"); + } + + onKeybindingsClicked() { + this.moveToStateAddGoBack("KeybindingsState"); + } +} diff --git a/src/js/tsconfig.json b/src/js/tsconfig.json index 5184bc42..7ecc605a 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/sync-translations.js b/sync-translations.js index d6b87278..356a4aba 100644 --- a/sync-translations.js +++ b/sync-translations.js @@ -1,82 +1,81 @@ -// Synchronizes all translations - -const fs = require("fs"); -const matchAll = require("match-all"); -const path = require("path"); -const YAWN = require("yawn-yaml/cjs"); -const YAML = require("yaml"); - -const files = fs - .readdirSync(path.join(__dirname, "translations")) - .filter(x => x.endsWith(".yaml")) - .filter(x => x.indexOf("base-en") < 0); - -const originalContents = fs - .readFileSync(path.join(__dirname, "translations", "base-en.yaml")) - .toString("utf-8"); - -const original = YAML.parse(originalContents); - -const placeholderRegexp = /[[<]([a-zA-Z_0-9]+)[\]<]/gi; - -function match(originalObj, translatedObj, path = "/") { - for (const key in originalObj) { - if (!translatedObj.hasOwnProperty(key)) { - console.warn(" | Missing key", path + key); - translatedObj[key] = originalObj[key]; - continue; - } - const valueOriginal = originalObj[key]; - const valueMatching = translatedObj[key]; - if (typeof valueOriginal !== typeof valueMatching) { - console.warn(" | MISMATCHING type (obj|non-obj) in", path + key); - continue; - } - - if (typeof valueOriginal === "object") { - match(valueOriginal, valueMatching, path + key + "/"); - } else if (typeof valueOriginal === "string") { - // todo - const originalPlaceholders = matchAll(valueOriginal, placeholderRegexp).toArray(); - const translatedPlaceholders = matchAll(valueMatching, placeholderRegexp).toArray(); - - if (originalPlaceholders.length !== translatedPlaceholders.length) { - console.warn( - " | Mismatching placeholders in", - path + key, - "->", - originalPlaceholders, - "vs", - translatedPlaceholders - ); - translatedObj[key] = originalObj[key]; - continue; - } - } else { - console.warn(" | Unknown type: ", typeof valueOriginal); - } - - // const matching = translatedObj[key]; - } - - for (const key in translatedObj) { - if (!originalObj.hasOwnProperty(key)) { - console.warn(" | Obsolete key", path + key); - delete translatedObj[key]; - } - } -} - -for (let i = 0; i < files.length; ++i) { - const filePath = path.join(__dirname, "translations", files[i]); - console.log("Processing", files[i]); - const translatedContents = fs.readFileSync(filePath).toString("utf-8"); - const translated = YAML.parse(translatedContents); - const handle = new YAWN(translatedContents); - - const json = handle.json; - match(original, json, "/"); - handle.json = json; - - fs.writeFileSync(filePath, handle.yaml, "utf-8"); -} +// Synchronizes all translations + +const fs = require("fs"); +const matchAll = require("match-all"); +const path = require("path"); +const YAML = require("yaml"); + +const files = fs + .readdirSync(path.join(__dirname, "translations")) + .filter(x => x.endsWith(".yaml")) + .filter(x => x.indexOf("base-en") < 0); + +const originalContents = fs + .readFileSync(path.join(__dirname, "translations", "base-en.yaml")) + .toString("utf-8"); + +const original = YAML.parse(originalContents); + +const placeholderRegexp = /[[<]([a-zA-Z_0-9/-_]+?)[\]>]/gi; + +function match(originalObj, translatedObj, path = "/") { + for (const key in originalObj) { + if (!translatedObj.hasOwnProperty(key)) { + console.warn(" | Missing key", path + key); + translatedObj[key] = originalObj[key]; + continue; + } + const valueOriginal = originalObj[key]; + const valueMatching = translatedObj[key]; + if (typeof valueOriginal !== typeof valueMatching) { + console.warn(" | MISMATCHING type (obj|non-obj) in", path + key); + translatedObj[key] = originalObj[key]; + continue; + } + + if (typeof valueOriginal === "object") { + match(valueOriginal, valueMatching, path + key + "/"); + } else if (typeof valueOriginal === "string") { + // @todo + const originalPlaceholders = matchAll(valueOriginal, placeholderRegexp).toArray(); + const translatedPlaceholders = matchAll(valueMatching, placeholderRegexp).toArray(); + + if (originalPlaceholders.length !== translatedPlaceholders.length) { + console.warn( + " | Mismatching placeholders in", + path + key, + "->", + originalPlaceholders, + "vs", + translatedPlaceholders + ); + translatedObj[key] = originalObj[key]; + continue; + } + } else { + console.warn(" | Unknown type: ", typeof valueOriginal); + } + } + + for (const key in translatedObj) { + if (!originalObj.hasOwnProperty(key)) { + console.warn(" | Obsolete key", path + key); + delete translatedObj[key]; + } + } +} + +for (let i = 0; i < files.length; ++i) { + const filePath = path.join(__dirname, "translations", files[i]); + console.log("Processing", files[i]); + const translatedContents = fs.readFileSync(filePath).toString("utf-8"); + + const json = YAML.parse(translatedContents); + match(original, json, "/"); + + const stringified = YAML.stringify(json, { + indent: 4, + simpleKeys: true, + }); + fs.writeFileSync(filePath, stringified, "utf-8"); +} diff --git a/translations/.gitignore b/translations/.gitignore new file mode 100644 index 00000000..6f7f420d --- /dev/null +++ b/translations/.gitignore @@ -0,0 +1 @@ +tmp diff --git a/translations/README.md b/translations/README.md index 2191edc3..020c7ca6 100644 --- a/translations/README.md +++ b/translations/README.md @@ -1,79 +1,83 @@ -# Translations - -The base language is English and can be found [here](base-en.yaml). - -## Languages - -- [German](base-de.yaml) -- [French](base-fr.yaml) -- [Korean](base-kor.yaml) -- [Dutch](base-nl.yaml) -- [Polish](base-pl.yaml) -- [Portuguese (Brazil)](base-pt-BR.yaml) -- [Portuguese (Portugal)](base-pt-PT.yaml) -- [Russian](base-ru.yaml) -- [Greek](base-el.yaml) -- [Italian](base-it.yaml) -- [Romanian](base-ro.yaml) -- [Swedish](base-sv.yaml) -- [Chinese (Simplified)](base-zh-CN.yaml) -- [Chinese (Traditional)](base-zh-TW.yaml) -- [Spanish](base-es.yaml) -- [Hungarian](base-hu.yaml) -- [Turkish](base-tr.yaml) -- [Japanese](base-ja.yaml) -- [Lithuanian](base-lt.yaml) -- [Arabic](base-ar.yaml) -- [Norwegian](base-no.yaml) -- [Kroatian](base-hr.yaml) -- [Danish](base-da.yaml) -- [Finnish](base-fi.yaml) -- [Catalan](base-cat.yaml) -- [Slovenian](base-sl.yaml) -- [Ukrainian](base-uk.yaml) -- [Indonesian](base-ind.yaml) - -(If you want to translate into a new language, see below!) - -## Editing existing translations - -If you want to edit an existing translation (Fixing typos, Updating it to a newer version, etc), you can just use the github file editor to edit the file. - -- Click the language you want to edit from the list above -- Click the small "edit" symbol on the top right - -edit symbol - -- Do the changes you wish to do (Be sure **not** to translate placeholders! For example, ` minutes` should get ` Minuten` and **not** ` Minuten`!) - -- Click "Propose Changes" - -propose changes - -- Click "Create pull request" - -create pull request - -- I will review your changes and make comments, and eventually merge them so they will be in the next release! Be sure to regulary check the created pull request for comments. - -## Adding a new language - -Please DM me on discord (tobspr#5407), so I can add the language template for you. - -Please use the following template: - -``` -Hey, could you add a new translation? - -Language: -Short code: -Local Name: -``` - -You can find the short code [here](https://www.science.co.il/language/Codes.php) (In column `Code 2`). - -PS: I'm super busy, but I'll give my best to do it quickly! - -## Updating a language to the latest version - -Run `yarn syncTranslations` in the root directory to synchronize all translations to the latest version! This will remove obsolete keys and add newly added keys. (Run `yarn` before to install packes). +# Translations + +The base language is English and can be found [here](base-en.yaml). + +## Languages + +- [German](base-de.yaml) +- [French](base-fr.yaml) +- [Korean](base-kor.yaml) +- [Dutch](base-nl.yaml) +- [Polish](base-pl.yaml) +- [Portuguese (Brazil)](base-pt-BR.yaml) +- [Portuguese (Portugal)](base-pt-PT.yaml) +- [Russian](base-ru.yaml) +- [Greek](base-el.yaml) +- [Italian](base-it.yaml) +- [Romanian](base-ro.yaml) +- [Swedish](base-sv.yaml) +- [Chinese (Simplified)](base-zh-CN.yaml) +- [Chinese (Traditional)](base-zh-TW.yaml) +- [Spanish](base-es.yaml) +- [Hungarian](base-hu.yaml) +- [Turkish](base-tr.yaml) +- [Japanese](base-ja.yaml) +- [Lithuanian](base-lt.yaml) +- [Arabic](base-ar.yaml) +- [Norwegian](base-no.yaml) +- [Kroatian](base-hr.yaml) +- [Danish](base-da.yaml) +- [Finnish](base-fi.yaml) +- [Catalan](base-cat.yaml) +- [Slovenian](base-sl.yaml) +- [Ukrainian](base-uk.yaml) +- [Indonesian](base-ind.yaml) +- [Serbian](base-sr.yaml) +- [Czech](base-cz.yaml) + +(If you want to translate into a new language, see below!) + +## Editing existing translations + +If you want to edit an existing translation (Fixing typos, updating it to a newer version, etc), you can just use the github file editor to edit the file. + +- Click the language you want to edit from the list above +- Click the small "edit" symbol on the top right + +edit symbol + +- Do the changes you wish to do (Be sure **not** to translate placeholders! For example, ` minutes` should get ` Minuten` and **not** ` Minuten`!) + +- Click "Propose Changes" + +propose changes + +- Click "Create pull request" + +create pull request + +- I will review your changes and make comments, and eventually merge them so they will be in the next release! Be sure to regulary check the created pull request for comments. + +## Adding a new language + +Please DM me on Discord (tobspr#5407), so I can add the language template for you. + +**Important: I am currently not accepting new languages until the wires update is out!** + +Please use the following template: + +``` +Hey, could you add a new translation? + +Language: +Short code: +Local Name: +``` + +You can find the short code [here](https://www.science.co.il/language/Codes.php) (In column `Code 2`). + +PS: I'm super busy, but I'll give my best to do it quickly! + +## Updating a language to the latest version + +Run `yarn syncTranslations` in the root directory to synchronize all translations to the latest version! This will remove obsolete keys and add newly added keys. (Run `yarn` before to install packages). diff --git a/translations/base-ar.yaml b/translations/base-ar.yaml index c42d5e0d..1ecee9c3 100644 --- a/translations/base-ar.yaml +++ b/translations/base-ar.yaml @@ -1,111 +1,61 @@ -# -# 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 is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. + shortText: لعبة شيبز (أشكال) هي لعبة تدور حول بناء مصانع وتوصيلها حتى تقوم بشكل + .آلي بصناعة أشكال مختلفة تزداد تعقيدا في خريطة لانهائية. + discordLinkShort: Official Discord + intro: >- + لعبة شيبز (أشكال) هي لعبة مريحة تقوم فيها ببناء مصانع ووتشغيلها آليا + لصناعة أشكال هندسية. - # 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 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]! + عند شراءك اللعبة على ستيم (Steam) تحصل على الإصدار الكامل للعبة، ولكن يمكن أيضاً لعبة نسخة تجريبية على موقع shapez.io ثم يمكنك القرار لاحقا + title_advantages: ميزات نسخة الحاسوب + advantages: + - 12 New Level for a total of 26 levels + - 18 New Buildings for a fully automated factory! + - 20 Upgrade Tiers for many hours of fun! + - Wires Update for an entirely new dimension! + - Dark Mode! + - Unlimited Savegames + - Unlimited Markers + - Support me! ❤️ + title_future: Planned Content + planned: + - Blueprint Library (Standalone Exclusive) + - Steam Achievements + - Puzzle Mode + - Minimap + - Mods + - Sandbox mode + - ... and a lot more! + title_open_source: This game is open source! + title_links: Links + links: + discord: Official Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Help translate + text_open_source: >- + Anybody can contribute, I'm actively involved in the community and + attempt to review all suggestions and take feedback into consideration + where possible. - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! - global: loading: Loading error: Error - - # 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. + decimalSeparator: . suffix: thousands: k millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: inf - time: - # Used for formatting past time dates oneSecondAgo: one second ago xSecondsAgo: seconds ago oneMinuteAgo: one minute ago @@ -114,14 +64,10 @@ global: xHoursAgo: hours ago oneDayAgo: one day ago xDaysAgo: days ago - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s hoursAndMinutesShort: h m - xMinutes: minutes - keys: tab: TAB control: CTRL @@ -129,34 +75,25 @@ global: escape: ESC shift: SHIFT space: SPACE - 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! - + intro: Get the standalone to unlock all features! 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! - - # 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. - + madeBy: Made by + 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 - - - continue: Continue - newGame: New Game - madeBy: Made by - subreddit: Reddit - + savegameUnnamed: Unnamed dialogs: buttons: ok: OK @@ -166,117 +103,108 @@ 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 - importSavegameError: title: Import Error - text: >- - Failed to import your savegame: - + text: "Failed to import your savegame:" importSavegameSuccess: title: Savegame Imported - text: >- - Your savegame has been successfully imported. - + text: Your savegame has been successfully imported. gameLoadFailure: title: Game is broken - text: >- - Failed to load your savegame: - + text: "Failed to load your savegame:" confirmSavegameDelete: title: Confirm deletion - text: >- - Are you sure you want to delete the game? - + text: Are you sure you want to delete the following game?

+ '' at level

This can not be + undone! savegameDeletionError: title: Failed to delete - text: >- - Failed to delete the savegame: - + text: "Failed to delete the savegame:" restartRequired: title: Restart required - text: >- - You need to restart the game to apply the settings. - + 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. - resetKeybindingsConfirmation: title: Reset keybindings desc: This will reset all keybindings to their default values. Please confirm. - keybindingsResetOk: title: Keybindings reset desc: The keybindings have been reset to their respective defaults! - 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! - desc: >- - Here are the changes since you last played: - + desc: "Here are the changes since you last played:" upgradesIntroduction: title: Unlock Upgrades - 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. - + 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 - desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? - - blueprintsNotUnlocked: - title: Not unlocked yet - desc: >- - Complete level 12 to unlock Blueprints! - - keybindingsIntroduction: - title: Useful 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.
- - 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 - - markerDemoLimit: - desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! + 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 + 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? - + blueprintsNotUnlocked: + title: Not unlocked yet + desc: Complete level 12 to unlock Blueprints! + keybindingsIntroduction: + title: Useful 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.
" + createMarker: + title: New Marker + 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! + 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! + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: Rename Savegame + desc: You can rename your savegame here. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Move selectBuildings: Select area @@ -284,125 +212,19 @@ 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 - - # 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. - - # 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 - itemsPerSecondDouble: (x2) - - 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 - - # Notifications on the lower right - notifications: - newUpgrade: A new upgrade is available! - gameSaved: Your game has been saved. - - # The "Upgrades" window - shop: - title: Upgrades - buttonUnlock: Upgrade - - # Gets replaced to e.g. "Tier IX" - tier: Tier - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - - maximumLevel: MAXIMUM LEVEL (Speed x) - - # The "Statistics" window - statistics: - title: Statistics - dataSources: - stored: - title: Stored - description: Displaying amount of stored shapes in your central building. - produced: - title: Produced - description: Displaying all shapes your whole factory produces, including intermediate products. - delivered: - title: Delivered - 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 - - # Settings menu, when you press "ESC" - settingsMenu: - playtime: Playtime - - buildingsPlaced: Buildings - beltsPlaced: Belts - - buttons: - continue: Continue - settings: Settings - menu: Return to menu - - # Bottom left tutorial hints - tutorialHints: - title: Need help? - showHint: Show hint - hideHint: Close - - # When placing a blueprint - blueprintPlacer: - 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. - - # Interactive tutorial - interactiveTutorial: - title: Tutorial - hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! - 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. - colors: red: Red green: Green @@ -411,14 +233,145 @@ ingame: purple: Purple cyan: Cyan white: White - uncolored: No color black: Black + uncolored: Gray + buildingPlacement: + cycleBuildingVariants: Press to cycle variants. + hotkeyLabel: "Hotkey: " + infoTexts: + speed: Speed + range: Range + storage: Storage + oneItemPerSecond: 1 item / second + itemsPerSecond: items / s + itemsPerSecondDouble: (x2) + tiles: tiles + levelCompleteNotification: + levelTitle: Level + completed: Completed + unlockText: Unlocked ! + buttonNextLevel: Next Level + notifications: + newUpgrade: A new upgrade is available! + gameSaved: Your game has been saved. + freeplayLevelComplete: Level has been completed! + shop: + title: Upgrades + buttonUnlock: Upgrade + tier: Tier + maximumLevel: MAXIMUM LEVEL (Speed x) + statistics: + title: Statistics + dataSources: + stored: + title: Stored + description: Displaying amount of stored shapes in your central building. + produced: + title: Produced + description: Displaying all shapes your whole factory produces, including + intermediate products. + delivered: + title: Delivered + description: Displaying shapes which are delivered to your central building. + noShapesProduced: No shapes have been produced so far. + shapesDisplayUnits: + second: / s + minute: / m + hour: / h + settingsMenu: + playtime: Playtime + buildingsPlaced: Buildings + beltsPlaced: Belts + tutorialHints: + title: Need help? + showHint: Show hint + hideHint: Close + blueprintPlacer: + cost: Cost + 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. shapeViewer: title: Layers empty: Empty copyKey: Copy Key - -# All shop upgrades + interactiveTutorial: + title: Tutorial + hints: + 1_1_extractor: Place an extractor on top of a circle + shape to extract it! + 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." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limited to + watermark: + title: Demo version + desc: Click here to see the Steam version advantages! + get_on_steam: Get on steam + standaloneAdvantages: + title: Get the full version! + no_thanks: No, thanks! + points: + levels: + title: 12 New Levels + desc: For a total of 26 levels! + buildings: + title: 18 New Buildings + desc: Fully automate your factory! + savegames: + title: ∞ Savegames + desc: As many as your heart desires! + upgrades: + title: 20 Upgrade Tiers + desc: This demo version has only 5! + markers: + title: ∞ Markers + desc: Never get lost in your factory! + wires: + title: Wires + desc: An entirely new dimension! + darkmode: + title: Dark Mode + desc: Stop hurting your eyes! + support: + title: Support me + desc: I develop it in my spare time! shopUpgrades: belt: name: Belts, Distributor & Tunnels @@ -432,281 +385,402 @@ shopUpgrades: painting: name: Mixing & Painting description: Speed x → x - -# Buildings and their name / description buildings: hub: deliver: Deliver toUnlock: to unlock levelShortcut: LVL - + endOfDemo: End of Demo belt: default: - name: &belt Conveyor Belt + name: 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 parts 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 top 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. wire: default: name: Energy Wire description: Allows you to transport energy. - advanced_processor: + second: + name: Wire + description: Transfers signals, which can be items, colors or booleans (1 / 0). + Different colored wires do not connect. + miner: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For + name: 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: default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: + name: Tunnel + description: Allows you to tunnel resources under buildings and belts. + tier2: + name: Tunnel Tier II + description: Allows you to tunnel resources under buildings and belts. + cutter: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: 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! + 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! + rotater: + default: + name: Rotate + description: Rotates shapes clockwise by 90 degrees. + ccw: + name: Rotate (CCW) + description: Rotates shapes counter-clockwise by 90 degrees. + rotate180: + name: Rotate (180) + description: Rotates shapes by 180 degrees. + stacker: + default: + name: Stacker + description: Stacks both items. If they can not be merged, the right item is + placed above the left item. + mixer: + default: + name: Color Mixer + description: Mixes two colors using additive blending. + painter: + default: + name: Painter + description: Colors the whole shape on the left input with the color from the + top input. + mirrored: + name: Painter + description: Colors the whole shape on the left input with the color from the + top 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 you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! + trash: + default: + name: Trash + description: Accepts inputs from all sides and destroys them. Forever. + balancer: + default: + name: Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Merger (compact) + description: Merges two conveyor belts into one. + merger-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + storage: + default: + name: Storage + description: Stores excess items, up to a given capacity. Prioritizes the left + output and can be used as an overflow gate. + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: Switch + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means + shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. + (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means + shape, color or boolean "1") + transistor: + default: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + mirrored: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: Belt Reader + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: Virtual Cutter + description: Virtually cuts the shape into two halves. + rotater: + name: Virtual Rotater + description: Virtually rotates the shape, both clockwise and counter-clockwise. + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the + remaining ones to the left. + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the shape on + the right input. + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the + wires layer on the regular layer. 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, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! reward_rotater: title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. - + desc: The rotater has been unlocked! It rotates shapes + clockwise by 90 degrees. 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! - + 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! - + desc: The mixer has been unlocked - Combine two colors using + additive blending with this building! 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! - + 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! 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!

- + desc: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! reward_tunnel: title: Tunnel - desc: The tunnel has been unlocked - You can now tunnel items through belts and buildings with it! - + desc: The tunnel has been unlocked - You can now tunnel items + through belts and buildings with it! 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 - desc: You have unlocked the chaining extractor! It can forward its resources to other extractors so you can more efficiently extract resources! - + desc: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" 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! - - 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! - + 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! 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! - + desc: You have unlocked a variant of the cutter - It allows you + to cut shapes in four parts instead of just two! 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! - - 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 works as + the regular painter but processes two shapes at + once consuming just one color instead of two! 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 the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! 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!) - + desc: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. 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). - - # Special reward, which is shown when there is no reward actually + 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). 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! - + 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: >- - Congratulations! By the way, more content is planned for the standalone! - + desc: Congratulations! By the way, more content is planned for the standalone! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: End of Demo + desc: You have reached the end of the demo version! settings: title: Settings categories: - game: Game - app: Application - + general: General + userInterface: User Interface + advanced: Advanced + performance: Performance versionBadges: dev: Development staging: Staging prod: Production buildDate: Built - labels: 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. + 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 - + 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: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + 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 - - language: - title: Language - description: >- - Change the language. All translations are user contributed and might be incomplete! - - fullscreen: - title: Fullscreen - description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. - - soundsMuted: - title: Mute Sounds - description: >- - If enabled, mutes all sound effects. - - musicMuted: - title: Mute Music - description: >- - If enabled, mutes all music. - - theme: - title: Game theme - description: >- - Choose the game theme (light / dark). - themes: - dark: Dark - light: Light - - refreshRate: - title: Simulation Target - 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: Multiplace - description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. - - 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. - movementSpeed: title: Movement speed description: Changes how fast the view moves when using the keyboard. @@ -717,59 +791,122 @@ settings: 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. - vignette: - title: Vignette - description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. - - 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 - - compactBuildingInfo: - title: Compact Building Infos - description: >- - 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. - + language: + title: Language + description: Change the language. All translations are user-contributed and + might be incomplete! enableColorBlindHelper: title: Color Blind Mode - description: Enables various tools which allow to play the game if you are color blind. + description: Enables various tools which allow you to play the game if you are + color blind. + fullscreen: + title: Fullscreen + description: It is recommended to play the game in fullscreen to get the best + experience. Only available in the standalone. + soundsMuted: + title: Mute Sounds + description: If enabled, mutes all sound effects. + musicMuted: + title: Mute Music + description: If enabled, mutes all music. + theme: + title: Game theme + description: Choose the game theme (light / dark). + themes: + dark: Dark + light: Light + refreshRate: + title: Simulation Target + 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: Multiplace + description: If enabled, all buildings will stay selected after placement until + you cancel it. This is equivalent to holding SHIFT permanently. + offerHints: + title: Hints & Tutorials + 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 + 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 + description: Enables the vignette, which darkens the screen corners and makes + text easier to read. 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. - + 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 + description: Shortens info boxes for buildings by only showing their ratios. + Otherwise a description and image is shown. + disableCutDeleteWarnings: + title: Disable Cut/Delete Warnings + description: Disables the warning dialogs brought up when cutting/deleting more + than 100 entities. + soundVolume: + title: Sound Volume + description: Set the volume for sound effects + musicVolume: + title: Music Volume + description: Set the volume for music + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: Keybindings - hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - + hint: "Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different + placement options." resetKeybindings: Reset Keybindings - categoryLabels: general: Application ingame: Game @@ -778,7 +915,6 @@ keybindings: massSelect: Mass Select buildings: Building Shortcuts placementModifiers: Placement Modifiers - mappings: confirm: Confirm back: Back @@ -786,78 +922,75 @@ keybindings: mapMoveRight: Move Right mapMoveDown: Move Down mapMoveLeft: Move Left + mapMoveFaster: Move Faster centerMap: Center Map - mapZoomIn: Zoom in mapZoomOut: Zoom out createMarker: Create Marker - menuOpenShop: Upgrades menuOpenStats: Statistics - + menuClose: Close Menu toggleHud: Toggle HUD toggleFPSInfo: Toggle FPS and Debug Info - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + switchLayers: Switch layers + exportScreenshot: Export whole Base as Image + belt: Conveyor Belt + underground_belt: Tunnel + miner: Extractor + cutter: Cutter + rotater: Rotate + stacker: Stacker + mixer: Color Mixer + painter: Painter + trash: Trash + wire: Energy Wire + pipette: Pipette rotateWhilePlacing: Rotate - rotateInverseModifier: >- - Modifier: Rotate CCW instead + 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 - + balancer: Balancer + storage: Storage + constant_signal: Constant Signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" 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.

- - Finally, huge thanks to my best friend Niklas - Without our - factorio sessions this game would never have existed. + 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. changelog: title: Changelog - demo: features: restoringGames: Restoring savegames @@ -865,5 +998,65 @@ demo: oneGameLimit: Limited to one savegame customizeKeybindings: Customizing Keybindings exportingBase: Exporting whole Base as Image - settingNotAvailable: Not available in the demo. +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-cat.yaml b/translations/base-cat.yaml index 1abab2ca..85e03e8f 100644 --- a/translations/base-cat.yaml +++ b/translations/base-cat.yaml @@ -1,111 +1,65 @@ -# -# 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 é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. + 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. + discordLinkShort: Official Discord + intro: >- + Shapez.io es un joc relaxant en el qual has de construir fàbriques per a + la producció automàtica de formes geomètriques. - # 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] + A mesura que el nivell augmenta, les formes esdevenen més complexes, i has d'explorar el mapa infinit. - 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. + Per si això no era suficient, la demanda de formes creixerà exponencialment, pel que hauràs d'escalar les teves fàbriques! - 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]! + Mentre que al principi només processes formes, més envant les hauràs de colorejar, pel que necessitaràs extreure y mesclar colors! - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! + Si compres el joc a Steam tendràs accés al joc complet, però també pots jugar a la demo a shapez.io primer i decidir-te més tard! + title_advantages: "Avantatges de la versió completa:" + advantages: + - 12 Nous nivells per a un total de 26 nivells + - 18 Nous edificis per construir una fàbrica completament + automatitzada! + - 20 Nivells de millora per més hores de diversió! + - Actualització de Cablejat per a una dimensió totalment nova! + - Mode Oscur! + - Pots guardar jocs il·limitats + - Marcadors il·limitats + - Em dones suport! ❤️ + title_future: Contingut Planejat + planned: + - Llibreria de plànols (Exclusiu de la versió completa) + - Trofeus d'Steam + - Mode Puzzle + - Minimapa + - Mods + - Mode Sandbox + - ... i mot més! + title_open_source: Aquest joc és de codi obert! + title_links: Enllaços + links: + discord: Discord Oficial + roadmap: Full de ruta + subreddit: Subreddit + source_code: Codi font (GitHub) + translate: Ajuda a traduir-lo + text_open_source: >- + Qualsevol pot contribuir, i estic activament involucrat en la comunitat + i intent prestar atenció a tots els suggeriments i tenir en compte tots + el comentaris. + Assegura't de mirar el meu tauler de Trello per al full de ruta complet! global: loading: Carregant error: Error - - # 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. + decimalSeparator: . suffix: thousands: k millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: inf - time: - # Used for formatting past time dates oneSecondAgo: fa un segon xSecondsAgo: fa segons oneMinuteAgo: fa un minut @@ -114,14 +68,10 @@ global: xHoursAgo: fa hores oneDayAgo: fa un dia xDaysAgo: fa dies - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s hoursAndMinutesShort: h m - xMinutes: minuts - keys: tab: TAB control: CTRL @@ -129,12 +79,9 @@ global: escape: ESC shift: SHIFT space: ESPAI - demoBanners: - # This is the "advertisement" shown in the main menu and other various places title: Demo - Versió de prova - intro: >- - Aconsegueix el joc complet per obtenir totes les característiques! + intro: Aconsegueix el joc complet per obtenir totes les característiques! mainMenu: play: Jugar continue: Continuar @@ -146,16 +93,12 @@ mainMenu: discordLink: Servidor Discord oficial helpTranslate: Ajuda a traduir-lo! madeBy: Creat per - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - - Disculpa, però el joc funcionarà lent al teu navegador! Aconsegueix el joc complet o descarrega't chrome per una millor experiència. + browserWarning: Disculpa, però el joc funcionarà lent al teu navegador! + Aconsegueix el joc complet o descarrega't chrome per una millor + experiència. savegameLevel: Nivell savegameLevelUnknown: Nivell desconegut - - - + savegameUnnamed: Unnamed dialogs: buttons: ok: OK @@ -169,111 +112,108 @@ dialogs: viewUpdate: Veure actualitzacions showUpgrades: Mostrar millores showKeybindings: Mostrar dreceres de teclat - importSavegameError: title: Error en importar - text: >- - Failed to import your savegame: - + text: "Ha ocurrit un error intentant importar la teva partida:" importSavegameSuccess: title: Importar - text: >- - La partida ha sigut importada amb èxit. - + text: La partida ha sigut importada amb èxit. gameLoadFailure: title: No es pot carregar la partida guardada - text: >- - Failed to load your savegame: - + text: "Ha ocurrit un error al intentar carregar la teva partida:" confirmSavegameDelete: title: Eliminar - text: >- - Estàs segur que vols eliminar la partida guardada? - + text: Are you sure you want to delete the following game?

+ '' at level

This can not be + undone! savegameDeletionError: title: Error en eliminar - text: >- - Failed to delete the savegame: - + text: "Ha ocurrit un error al intentar eliminar la teva partida:" restartRequired: title: Reiniciar - text: >- - És necessari reiniciar el joc per aplicar els canvis. - + text: És necessari reiniciar el joc per aplicar els canvis. editKeybinding: title: Cambiar dreceres de teclat - desc: Pressiona la tecla o botó del ratolí que vols designar o ESC per cancel·lar. - + desc: Pressiona la tecla o botó del ratolí que vols designar o ESC per + cancel·lar. resetKeybindingsConfirmation: title: Reiniciar dreceres de teclat desc: Això reiniciarà tots els canvis realitzats, n'estàs segur? - keybindingsResetOk: title: Cambiar dreceres de teclat desc: Les dreceres han tornat en el seu estat predeterminat! - featureRestriction: title: Demo - Versió de prova - desc: Has intentat accedir a una característica () que no està disponible en la demo. Considera obtenir el joc complet per a una experiència completa! - + desc: Has intentat accedir a una característica () que no està + disponible en la demo. Considera obtenir el joc complet per a una + experiència completa! oneSavegameLimit: title: Partides guardades limitades - desc: Només pots tenir una sola partida guardada a la versió de demostració. Si vols, elimina la ja existent o fes-te amb la versió completa del joc! - + desc: Només pots tenir una sola partida guardada a la versió de demostració. Si + vols, elimina la ja existent o fes-te amb la versió completa del + joc! updateSummary: title: Nova actualització! - desc: >- - Aquí tens els canvis des de l'últim cop que vas jugar: - + desc: "Aquí tens els canvis des de l'últim cop que vas jugar:" upgradesIntroduction: title: Desbloquejar millora - desc: >- - Totes les figures poden ser usades per desbloquejar millores - No eliminis/es les teves fabriques anteriors! - La pestanya de millores està a la part superior dreta de la pantalla. - + desc: Totes les figures poden ser usades per desbloquejar millores - No + eliminis/es les teves fabriques anteriors! La pestanya de + millores està a la part superior dreta de la pantalla. massDeleteConfirm: title: Eliminar edificis - desc: >- - Estàs esborrant molts edificis de cop ( per ser exactes)! Estàs segur que vols seguir? - + desc: Estàs esborrant molts edificis de cop ( per ser exactes)! Estàs + segur que vols seguir? massCutConfirm: title: Tallar edificis - desc: >- - Estàs esborrant molts edificis de cop ( per ser exactes)! Estàs segur que vols seguir? - + desc: 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 - desc: >- - Completa el nivell 12 per poder desbloquejar aquesta característica. - + desc: Completa el nivell 12 per poder desbloquejar aquesta característica. keybindingsIntroduction: title: Dreceres de teclat útils - desc: >- - El joc té moltes dreceres que faciliten la feina a l'hora de construir grans línies de producció. - Aquí tens algunes, però asegura't de revisar les dreceres de teclat!

- CTRL + Arrossegar: Selecciona una àrea.
- SHIFT: Mentè pressionat per col·locar vàries vegades el mateix edifici.
- ALT: Invertir la orientació de les cintes transportadores ja col·locades.
- + desc: "El joc té moltes dreceres que faciliten la feina a l'hora de construir + grans línies de producció. Aquí tens algunes, però asegura't de + revisar les dreceres de teclat!

CTRL + Arrossegar: Selecciona una + àrea.
SHIFT: Mentè pressionat + per col·locar vàries vegades el mateix edifici.
ALT: Invertir la orientació de les cintes + transportadores ja col·locades.
" createMarker: title: Nou Marcador - titleEdit: Edit Marker - desc: >- - Dona-li un nom significatiu, també pots usar claus de les figures (Pots generarles a: aquí) - + titleEdit: Editar Marcador + desc: Give it a meaningful name, you can also include a short + key of a shape (Which you can generate here) markerDemoLimit: - desc: En la Demo només pots crear dos marcadors, aconsegueix la versió completa per gaudir de l'experiència completa! - + 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 - 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? - + 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! + editSignal: + title: Configura la Senyal + descItems: "Tria un ítem predefinit:" + descShortKey: ... o introdueix uncódi de forma (El qual pots + generar aqui) + renameSavegame: + title: Canviar el nom. + desc: Canviar el nom de la partida guardada. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Moure selectBuildings: Seleccionar àrea @@ -294,8 +234,6 @@ ingame: clearSelection: Buidar selecció pipette: Pipeta switchLayers: Intercanviar capes - - # Names of the colors, used for the color blind mode colors: red: Roig green: Verd @@ -304,19 +242,11 @@ 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. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: + cycleBuildingVariants: Prem per a ciclar entre variants. + hotkeyLabel: "Hotkey: " infoTexts: speed: Velocitat range: Distància @@ -324,98 +254,135 @@ ingame: oneItemPerSecond: 1 objecte / s itemsPerSecond: objectes / s itemsPerSecondDouble: (x2) - tiles: caselles - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Nivell completed: Complet unlockText: Desbloquejat ! buttonNextLevel: Següent nivell - - # Notifications on the lower right notifications: newUpgrade: Una nova millora està disponible! gameSaved: La teva/ua partida s'ha guardat. - - # The "Upgrades" window + freeplayLevelComplete: Level has been completed! shop: title: Millores buttonUnlock: Millorar - - # Gets replaced to e.g. "Tier IX" tier: Nivell - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: NIVELL MÀXIM (Velocitat x) - - # The "Statistics" window statistics: title: Estadístiques dataSources: stored: title: Emmagatzemat - description: Mostrant la quantitat de figures emmagatzemades en el teu edifici central. + description: Mostrant la quantitat de figures emmagatzemades en el teu edifici + central. produced: title: Produit - description: Mostrant la producció total de figures de la fàbrica, incluïnt productes intermijos. + description: Mostrant la producció total de figures de la fàbrica, incluïnt + productes intermijos. delivered: title: Enviats description: Mostrant les figures que són enviades a l'edifici central. noShapesProduced: Ninguna figura s'ha produit fins ara. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Temps de joc - buildingsPlaced: Edificis beltsPlaced: Cintes transportadores - - buttons: - continue: Continuar - settings: Configuració - menu: Tornar al menú - - # Bottom left tutorial hints tutorialHints: title: Necessites ajuda? showHint: Mostrar pista hideHint: Tancar - - # When placing a blueprint blueprintPlacer: cost: Cost - - # Map markers waypoints: waypoints: Marcadors hub: NEXE - description: Fes clic esquerre en un marcador per desplaçar-te cap a ell. Fes clic dret per esborrar-lo.

Pressiona per a crear un marcador des de la vista actual, o fes clic dret per a crear un marcador en el punt seleccionat. + description: Fes clic esquerre en un marcador per desplaçar-te cap a ell. Fes + clic dret per esborrar-lo.

Pressiona per a + crear un marcador des de la vista actual, o fes clic + dret per a crear un marcador en el punt seleccionat. creationSuccessNotification: S'ha creat un marcador . - - # Shape viewer shapeViewer: title: Capes empty: Buit copyKey: Copiar clau - - # Interactive tutorial interactiveTutorial: title: Tutorial hints: - 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 + 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." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limitat a + watermark: + title: Versió demo + desc: Premeu aquí per veure les avantatges d'Steam! + get_on_steam: Comprar a Steam + standaloneAdvantages: + title: Aconsegueix la versió completa! + no_thanks: No, gràcies! + points: + levels: + title: 12 Nivells now + desc: Per a un total de 26 nivells! + buildings: + title: 18 Nous edificis + desc: Automatitza la teva fàbrica completament! + savegames: + title: Guarda ∞ partides + desc: Tantes com vulguis! + upgrades: + title: 20 Nivells de millora + desc: La versió demo només en té 5! + markers: + title: ∞ Marcadors + desc: Mai et perdis per el mapa! + wires: + title: Cables + desc: Una nova dimensió! + darkmode: + title: Mode Oscur + desc: Deixa de fer-te mal als ulls! + support: + title: Dona'm suport + desc: EL desenvolupo en el meu temps lliure! shopUpgrades: belt: name: Cintes transportadores, Distribuidors i Túnels @@ -429,238 +396,399 @@ shopUpgrades: painting: name: Mesclar i Pintar description: Velocitat x → x - -# Buildings and their name / description buildings: hub: deliver: Envia toUnlock: per a desbloquejar levelShortcut: NVL - + endOfDemo: Fi de la Demo belt: default: - name: &belt Cinta transportadora - description: Transporta objectes, mantén pressionat i arrossega per a col·locar múltiples. - + name: Cinta transportadora + description: Transporta objectes, mantén pressionat i arrossega per a col·locar + múltiples. wire: default: - name: &wire Cable + name: Cable description: Permet transportar energia. - - miner: # Internal name for the Extractor + second: + name: Cable + description: Transfereix senyals, que poden ser ítems, colors o booleà. Cables + de diferents colors no es connecten entre ells. + miner: default: - name: &miner Extractor + name: Extractor description: Posa-ho damunt d'una font de figures o colors per extraure'ls. - chainable: 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 + description: Posa-ho damunt d'una font de figures o colors per extraure'ls. Pot + ser encadenat! + underground_belt: default: - name: &underground_belt Túnel + name: Túnel description: Permet transportar recursos per sota d'edificis i cintes. - tier2: name: Túnel de Nivell II description: Permet transportar recursos per sota d'edificis i cintes. - - splitter: # Internal name for the Balancer - default: - name: &splitter Distribuïdor - description: Multifuncional - Distribueix les entrades i sortides equitativament. - - compact: - name: Fusionador (compacte) - description: Fusiona dos cintes en una. - - compact-inverse: - name: Fusionador (compacte) - description: Fusiona dos cintes en una. - cutter: default: - name: &cutter Cisalla - description: Talla figures de dalt a baix i produeix les dues meitats. Si utilitzes sols una part, assegura't de destruir l'altra o es pararà! + name: Tallador + description: Talla figures de dalt a baix i produeix les dues meitats. + Si utilitzes sols una part, assegura't de destruir + l'altra o es pararà! quad: - name: Cisalla (Quàdruple) - description: Talla figures en quatre parts. Si no utilitzes totes les parts, assegura't de destruir les altres o es pararà! - - advanced_processor: - default: - name: &advanced_processor Processador avançat - description: Processament de figures avançat. - + name: Tallador (Quàdruple) + description: Talla figures en quatre parts. Si no utilitzes totes les + parts, assegura't de destruir les altres o es pararà! rotater: default: - name: &rotater Rotador + name: Rotador description: Rota formes en sentit horari 90 graus. ccw: name: Rotador (Antihorari) description: Rota formes en sentit antihorari 90 graus. - + rotate180: + name: Rotador (180) + description: Rota formes 180 graus. stacker: default: - name: &stacker Apilador - description: Fusiona o apila ambdues figures. Si no poden ser fusionades, la figura de la dreta es posarà damunt de la de l'esquerra. - + name: Apilador + description: Fusiona o apila ambdues figures. Si no poden ser fusionades, la + figura de la dreta es posarà damunt de la de l'esquerra. mixer: default: - name: &mixer Mesclador de colors + name: Mesclador de colors description: Mescla dos colors amb mescla additiva. - painter: default: - name: &painter Pintor - description: &painter_desc Pinta la figura sencera de l'esquerra amb el color de l'entrada de dalt. - + name: Pintor + description: Pinta la figura sencera de l'esquerra amb el color de l'entrada de + dalt. mirrored: name: Pintor - description: Pinta la figura sencera de l'esquerra amb el color de l'entrada de baix. - + description: Pinta la figura sencera de l'esquerra amb el color de l'entrada de + baix. double: name: Pintor (Doble) description: Pinta les figures de l'esquerra amb el color de dalt. quad: name: Pintor (Quàdruple) - description: Permet pintar cadascun dels quadrants de forma diferent. - + description: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! trash: default: - name: &trash Paperera + name: Paperera description: Acepta objectes de tots els costats i els destrueix. Permanentment. - - storage: - name: Magatzem - description: Emmagatzema objectes en excés, fins a una capacitat màxima. Es pot utilitzar com a control d'excedents. - - energy_generator: - deliver: Envia - - # This will be shown before the amount, so for example 'For 123 Energy' - toGenerateEnergy: Per a - + balancer: default: - name: &energy_generator Generador d'energia - description: Genera energia consumint figures. Cada generador requereix una figura diferent. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Equilibrador + description: Multifuncional - Reparteix uniformament totes les entrades a totes + les sortides. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Fusionador (compacte) + description: Fusiona dues cintes transportadores en una. + merger-inverse: + name: Fusionador (compacte) + description: Fusiona dues cintes transportadores en una. + splitter: + name: Divisor (compacte) + description: Divideix una cinta transportadora en dues. + splitter-inverse: + name: Divisor (compacte) + description: Divideix una cinta transportadora en dues. + storage: + default: + name: Emmagatzematge + description: Emmagatzema articles en excés fins a una capacitat determinada. + Prioritza la sortida esquerra i es pot utilitzar com a porta de + desbordament. + wire_tunnel: + default: + name: Encreuament de cablejat + description: Permet creuar dos cables sense conectar-los. + constant_signal: + default: + name: Senyal Constant + description: EEmet una senyal constant, que pot esser una forma, color o + booleana (1 / 0). + lever: + default: + name: Interruptor + description: Pot esser alternat per emetre una senyal booleana (1 / 0) a la capa + de cablejat. + logic_gate: + default: + name: Porta AND + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emet una senyal booleana "1" si les dues entrades són vertaderes. + (Vertadera significa que la senyal és una forma, un color o la + senyal booleana "1"). + xor: + name: Porta XOR + description: Emet una senyal booleana "1" si i només si una de les senyals és + vertadera. (Vertadera significa que la senyal és una forma, un + color o la senyal booleana "1"). + or: + name: Porta OR + description: Emet una senyal booleana "1" si una de les senyals és vertadera. + (Vertadera significa que la senyal és una forma, un color o la + senyal booleana "1"). + transistor: + default: + name: Transistor + description: Deixa passar la senyal inferior si la senyal lateral és vertadera + (una forma, color o "1"). + mirrored: + name: Transistor + description: Deixa passar la senyal inferior si la senyal lateral és vertadera + (una forma, color o "1"). + filter: + default: + name: Filtre + description: Conecta una senyal per redirigir tots els ítems que coincideixin + amb la senyal a la part superior, i la resta a la dreta. També + es pot controlar amb senyals booleanes. + display: + default: + name: Pantalla + description: Conecta una senyal per que es mostri a la pantalla. Pot ser una + forma, color o booleà + reader: + default: + name: Lector de cinta + description: Permet mesurar el rendiment de la cinta. Emet el darrer ítem llegit + a la capa de cablejat (un pic desbloquejada). + analyzer: + default: + name: Analitzador de formes + description: Analitza el quadrant superior dret de la capa més baixa de la forma + i retorna el color i la forma. + comparator: + default: + name: Comparador + description: Retorna una senyal booleana "1" si les dues senyals són exactament + iguales.Pot comparar formes, colors i booleans. + virtual_processor: + default: + name: Tallador virtual + description: Talla la forma virtual en dues parts. + rotater: + name: Rotador Virtual + description: Rota la forma virtual, tant en sentit horari com antihorari. + unstacker: + name: Desapilador Virtual + description: Extreu la capa superior a la sortida dreta i la resta a la sortida + esquerra. + stacker: + name: Apilador Virtual + description: Apila la figura de l'entrada dreta damunt l'entrada esquerra. + painter: + name: Pintador Virtual + description: Pinta la capa de l'entrada inferior amb la figura de la entrada + dreta. + item_producer: + default: + name: Productor d'ítems + description: Només avaliable en mode "sandbox", emet la senyal de la capa de + cablejat a la capa normal. storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Tallar figures - desc: Acabes de desbloquejar la Cisalla - talla les figures per la meitat de dalt a baix; sense importar la seva/ua orientació!

Assegura't d'eliminar les parts que no utilitzes, si no es pararà - Es per això que t'he donat una paperera, utilitza-la! - + desc: You just unlocked the cutter, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! reward_rotater: title: Rotar - desc: El Rotador s'ha desbloquejat! Rota formes en sentit horari 90 graus. - + desc: El Rotador s'ha desbloquejat! Rota formes en sentit + horari 90 graus. reward_painter: title: Pintar - desc: >- - El Pintor s'ha desbloquejat! - Extreu mena de color (de la mateixa forma que les figures) i pinta les figures amb el pintor!

- Si ets daltònic, pots activar l'opció per daltònics en les opcions! - + desc: El Pintor s'ha desbloquejat! - Extreu mena de color (de + la mateixa forma que les figures) i pinta les figures amb el + pintor!

- Si ets daltònic, pots activar l'opció per + daltònics en les opcions! reward_mixer: title: Mesclar colors - desc: El Mesclador de colors s'ha desbloquejat! - Combina dos colors utilitzant la mescla additiva amb aquest edifici! - + desc: El Mesclador de colors s'ha desbloquejat! - Combina dos + colors utilitzant la mescla additiva amb aquest + edifici! reward_stacker: title: Apilador - desc: Ara pots combinar figures amb el apilador! Ambdues entrades són combinades. Si es poden posar una vora l'altra, es fusionaran. Si no, l'entrada de la dreta s'apilarà damunt de la de l'esquerra! - + desc: Ara pots combinar figures amb el apilador! Ambdues + entrades són combinades. Si es poden posar una vora l'altra, es + fusionaran. Si no, l'entrada de la dreta + s'apilarà damunt de la de l'esquerra! reward_splitter: title: Distribuïdor - desc: El distribuïdor multifuncional s'ha desbloquejat - Pot ser utilitzat per a construir fàbriques més grans per mitjà de la separació i fusió de figures de diferents cintes!

- + desc: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! reward_tunnel: title: Túnel - desc: El túnel s'ha desbloquejat - Ara pots passar objectes a través d'edificis i cintes transportadores! - + desc: El túnel s'ha desbloquejat - Ara pots passar objectes a + través d'edificis i cintes transportadores! reward_rotater_ccw: title: Rotació antihorària - desc: Has desbloquejat una variant del rotador - Et permet rotar en sentit antihorari! Per tal de construir-lo, selecciona el rotador i pressiona 'T' per a ciclar les diferents variants! - + desc: Has desbloquejat una variant del rotador - Et permet + rotar en sentit antihorari! Per tal de construir-lo, selecciona el + rotador i pressiona 'T' per a ciclar les diferents + variants! reward_miner_chainable: title: Extractor en cadena - desc: Has desbloquejat el extractor en cadena! Pot passar els seus recursos a altres extractors perquè pugues extraure recursos més eficientment! - + desc: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" reward_underground_belt_tier_2: title: Túnel de Nivell II - desc: Has desbloquejat una nova variant del túnel - Té una major distància màxima, i ara pots mesclar tipus de túnels! - - reward_splitter_compact: - title: Distribuïdor compacte - desc: >- - Has desbloquejat una variant compacta del distribuïdor - Acepta dues entrades i les fusiona en una sola! + desc: Has desbloquejat una nova variant del túnel - Té una + major distància màxima, i ara pots mesclar tipus de + túnels! 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! - + title: Tallador quàdruple + desc: Has desbloquejat una variant de la tallador - Et permet + tallar figures en quatre parts en lloc de sols en + dos! reward_painter_double: title: Pintor doble - desc: Has desbloquejat una variant del pintor - Funciona com el pintor regular però processa dos figures alhora, consumint sols un color en lloc de dos! - - reward_painter_quad: - title: Pintor quàdruple - desc: Has desbloquejat una variant del pintor - Et permet pintar cada part de la figura individualment! - + desc: Has desbloquejat una variant del pintor - Funciona com el + pintor regular però processa dos figures alhora, + consumint sols un color en lloc de dos! reward_storage: title: Magatzem de reserva - desc: Has desbloquejat una variant de la paperera - Et permet emmagatzemar objectes fins a una capacitat màxima! - + desc: You have unlocked the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! reward_freeplay: title: Joc lliure - desc: Ho has fet! Has desbloquejat el mode de joc lliure! Això significa que les figures ara són generades aleatòriament! (No t'angoixis/es, hi ha més contingut planejat per a la versió completa - fora del web) - + desc: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. reward_blueprints: title: Plànols - desc: Ara pots copiar i apegar/enxegar parts de la teva/ua fàbrica! Selecciona una àrea (Mantén pressionat CTRL, i arrossega el ratolí), i pressiona 'C' per a copiar-la.

Apegar/enxegar-la no és gratis, necessites produir figures de plànols per a poder fer-ho! (Les que n'acabes d'enviar). - - # Special reward, which is shown when there is no reward actually + desc: Ara pots copiar i apegar/enxegar parts de la teva/ua + fàbrica! Selecciona una àrea (Mantén pressionat CTRL, i arrossega el + ratolí), i pressiona 'C' per a copiar-la.

Apegar/enxegar-la + no és gratis, necessites produir figures de + plànols per a poder fer-ho! (Les que n'acabes d'enviar). no_reward: title: Següent nivell - desc: >- - Aquest nivell no t'ha donat res, però el següent ho farà!

PD: És millor que no destrueixes la part de la fàbrica existent - Necessitaràs totes aquestes figures més tard per a desbloquejar millores! - + desc: "Aquest nivell no t'ha donat res, però el següent ho farà!

PD: És + millor que no destrueixes la part de la fàbrica existent - + Necessitaràs totes aquestes figures més tard per a + desbloquejar millores!" no_reward_freeplay: title: Següent nivell + desc: Enhorabona! Per cert, hi ha més contingut planejat per a la versió + completa - fora del web! + reward_balancer: + title: Equilibrador + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Fusionador Compacte + desc: Has desbloquejat una variant fusionadora de + l'equilibrador. Accepta dues entrades i les fusiona + en una cinta! + reward_belt_reader: + title: Lector de cinta + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotador (180 graus) + desc: Acabes de desbloquejar un altre rotador!. Et permet rotar + una forma 180 graus. + reward_display: + title: Pantalla + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Senyal constant desc: >- - Enhorabona! Per cert, hi ha més contingut planejat per a la versió completa - fora del web! - + Has desbloquejat l'emisor de senyal constant a la + capa de cables! És molt util per conectar-los a filtres + d'ítems, per exemple.

Pot emetre una + forma, color or + booleà (1 / 0). + reward_logic_gates: + title: Portes lògiques + desc: Has desbloquejat les portes lògiques! No fa falta + t'emocionis per això, però és molt guai!

Amb aquestes portes + lògiques pots computar operacions AND, OR, XOR i NOT.

També + tens disponible un transistor! + reward_virtual_processing: + title: Processament Virtual + desc: Acabes de desbloquejar un munt de nous edificis que et permeten + simular el processament de figures!

Ara + pots simular una tallador, rotador, apilador i més a la capa de + cables! Amb això ara tens tres opcions per continuar el + joc:

- Construir una màquina automàtica + que crea totes les formes demanades per el NEXE (Recoman + provar-ho!).

- Construir algo guai amb cables.

- + Continua jugant normalment.

Triis el que triis, recorda + passar-ho bé! + reward_wires_painter_and_levers: + title: Cables i Pintador Quàdruple + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Filtre d'Ítems + desc: Has desbloquejat el Filtre d'Ítems! Filtrarà els ítems a + la part superior o a la part dreta depenent de si coincideixen amb + la senyal de la capa de Cables o no.

També pots conectar-li + una senyal booleana (1 / 0) per encendra-la per complet o apagarla. + reward_demo_end: + title: Final de la Demo + desc: Has arribat al final de la Demo! settings: title: Opcions categories: - game: Joc - app: Aplicació - + general: General + userInterface: Interfície d'Usuari + advanced: Avançat + performance: Rendiment versionBadges: dev: Desenvolupament - staging: Staging + staging: Posada en escena prod: Producció buildDate: Generat - labels: uiScale: title: Escala de la interfície - description: >- - Canvia la dimensió de la interfície de l'usuari. La interfície se seguirà redimensionant depenent de la resolució del teu dispositiu, però aquesta opció controla la quantitat del redimensionat. + description: Canvia la dimensió de la interfície de l'usuari. La interfície se + seguirà redimensionant depenent de la resolució del teu + dispositiu, però aquesta opció controla la quantitat del + redimensionat. scales: super_small: Micro small: Petit regular: Estàndard large: Gran huge: Macro - autosaveInterval: title: Interval de guardat automàtic - description: >- - Controla el temps entre guardats automàtics que fa el joc, pots deshabilitar-ho des d'aquí + 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 @@ -668,178 +796,310 @@ settings: ten_minutes: 10 Minuts twenty_minutes: 20 Minuts disabled: Desactivat - scrollWheelSensitivity: - title: Zoom sensitivity - description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + title: Sensitivitat del Zoom + description: 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 - description: >- - Changes how fast the view moves when using the keyboard. + title: Velocitat de Moviment + description: 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 - description: >- - Change the language. All translations are user contributed and might be incomplete! + title: Idioma + description: Canvia l'idioma. Totes les traduccions són contribucions d'usuaris + i poden estar incompletes! enableColorBlindHelper: - title: Color Blind Mode - description: >- - Enables various tools which allow to play the game if you are color blind. + title: Mode per Daltònics + description: Habilita diverses eines que et permeten jugar si ets Daltònic. fullscreen: - title: Fullscreen - description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. + title: Pantalla Completa + description: 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 - description: >- - If enabled, mutes all sound effects. + title: Silencia els sons + description: Si està activat, silencia tots els sons. musicMuted: - title: Mute Music - description: >- - If enabled, mutes all music. + title: Silencia la música + description: Si està activat, silencia la música. theme: - title: Game theme - description: >- - Choose the game theme (light / dark). + title: Tema del joc (Visual) + description: Tria el tema visual (clar / oscur). themes: - dark: Dark - light: Light - + dark: Oscur + light: Clar refreshRate: - title: Simulation Target - 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. + title: Objectiu de Simulació + description: 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 - description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. + title: Col·locació Múltiple + description: 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 - 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. + title: Pistes i Tutorials + description: 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 - description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. This also enables to drag tunnels and excess tunnels will get removed. + title: Túnels Intel·ligents + description: 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 - description: >- - Enables the vignette which darkens the screen corners and makes text easier to read. + title: Vinyeta + description: Activa la vinyeta, que obscureix els cantons de la pantalla i + facilita la lectura de texte. 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. + title: Rotació segons el tipus d'edifici. + description: 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 - description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. + title: Informació sobre Edificis Compactes + description: 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 - description: >- - Disable the warning dialogs brought up when cutting/deleting more than 100 entities. + title: Desactiva els diàlegs de Talla/Borra + description: Desactiva els diàlegs d'advertència que es mostren en tallar / + suprimir més de 100 entitats. + soundVolume: + title: Volum de sò + description: Defineix el volum dels sons + musicVolume: + title: Volum de música + description: Defineix el volum de la música + lowQualityMapResources: + title: Map de Recursos de Baixa Qualitat + description: Simplifica la renderització dels recursos en el mapa al fer zoom + per millorar el rendiment. Fins i tot es veu més net, així que + assegureu-vos de provar-ho! + disableTileGrid: + title: Desactiva la Graella + description: Desactivar la graella pot ajudar al rendiment. També fa que el joc + es vegi més net! + clearCursorOnDeleteWhilePlacing: + title: Esborreu el cursor en fer clic amb el botó dret + description: Encés per defecte, borra el cursor quan es prem el botó dret + mentres hi ha un edifici seleccionat. Si es desactiva, pots + eliminar edificis prement amb el botó dret mentres col·loques un + altre edifici. + lowQualityTextures: + title: Textures de baixa qualitat (Molt lleig) + description: Emprar textures de baixa qualitat per millorar el rendiment. Aixó + farà que el joc sigui molt lleig! + displayChunkBorders: + title: Mostrar les vores dels Chunks + description: El joc està dividit en chunks de 16x16 caselles. Si es selecciona + aquesta opció, les vores dels chunks es mostraràn. + pickMinerOnPatch: + title: Triar el miner a la zona de recursos + description: Seleccionat per defecte, es selecciona el miner si empres la pipeta + damunt una zona de recursos. + simplifiedBelts: + title: Cintes simplificades (Lleig) + description: No renderitze els ítems de les cintes fins que passis el ratolí per + sobre, per millorar el rendiment.No recoman usar aquesta opció + si no necessites un augment de rendiment. + enableMousePan: + title: Activa el desplaçament del ratolí + description: Permet moure el mapa quan mous el cursor a les vores de la + pantalla. La velocitat de moviment depèn de la configuració de + Velocitat de Moviment. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: - title: Keybindings - hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - resetKeybindings: Reset Keybindings - + title: Combinacions de tecles + hint: "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 - - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker - - menuOpenShop: Upgrades - menuOpenStats: Statistics - - 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: 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 - menuClose: Close Menu - + 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: Apropar + mapZoomOut: Allunyar + createMarker: Crea un Marcador + menuOpenShop: Millores + menuOpenStats: Estadístiques + menuClose: Tancar Menú + toggleHud: Commutar HUD + toggleFPSInfo: Commutar FPS i Informació de Depuració + switchLayers: Canviar capes + exportScreenshot: Exportar la Base com a Imatge + belt: Cinta transportadora + underground_belt: Túnel + miner: Extractor + cutter: Tallador + rotater: Rotador + stacker: Apilador + mixer: Mesclador de colors + painter: Pintor + trash: Paperera + wire: Cable + pipette: Pipeta + rotateWhilePlacing: Rotar + rotateInverseModifier: "Modificador: 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: "Planificador: Canviar costat" + 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 + balancer: Equilibrador + storage: Emmagatzematge + constant_signal: Senyal Constant + logic_gate: Porta lògica + lever: Interruptor (regular) + filter: Filtre + wire_tunnel: Creuament de Cables + display: Pantalla + reader: Lector de cinta + virtual_processor: Tallador Virtual + transistor: Transistor + analyzer: Analitzador de Figura + comparator: Comparador + item_producer: Productor d'items (Sandbox) + copyWireValue: "Cables: Copiar valor davall el cursor" 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. -changelog: - title: Changelog + 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: 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 - - settingNotAvailable: Not available in the demo. + 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: No disponible en la versió de demostració. +tips: + - El NEXE accepta qualsevol tipus d’entrada, no només la forma actual. + - Assegureu-vos que les vostres fàbriques siguin modulars; donarà els seus + fruits. + - No construïu massa a prop del NEXE, ja que serà un enorme caos. + - Si l'apilament no funciona, proveu de canviar les entrades. + - Podeu canviar la direcció del planificador de cinturons prement R . + - Mantenir premut CTRL permet arrossegar cinturons sense orientació + automàtica. + - Les proporcions continuen igual, sempre que totes les millores de + velocitat es facin al mateix nivell. + - L’execució en sèrie és més eficient que la paral·lela. + - Desbloquejaràs més variants d’edificis més endavant en el joc. + - Podeu utilitzar T per canviar entre diferents variants. + - La simetria és clau! + - Podeu teixir diferents nivells de túnels. + - "Intenteu construir fàbriques compactes: donarà els seus fruits!" + - El pintor té una variant reflectida que podeu seleccionar amb T + - Tenir les relacions constructives adequades maximitzarà l’eficiència. + - Al nivell màxim, 5 extractors ompliran un sol cinturó. + - No us oblideu dels túnels! + - No cal dividir els articles de manera uniforme per obtenir una eficiència + completa. + - Mantenint premut SHIFT s’activarà el planificador de cinturons, + cosa que us permetrà col·locar llargues línies de cinturons fàcilment. + - Els talladors sempre tallen verticalment, independentment de la seva + orientació. + - Per obtenir blanc barregeu els tres colors primaris. + - La memòria intermèdia d’emmagatzematge prioritza la primera sortida. + - "Invertiu temps per crear dissenys repetibles: val la pena." + - Si mantingueu CTRL permet col·locar diversos edificis. + - Podeu mantenir premut ALT per invertir la direcció dels cinturons + col·locats. + - L’eficiència és clau! + - Les formes geomètriques que apareixen més lluny del NEXE són més complexes. + - Les màquines tenen una velocitat limitada, dividiu-les per obtenir la + màxima eficiència. + - Utilitzeu equilibradors per maximitzar la vostra eficiència. + - L’organització és important. Intenteu no creuar massa els transportadors. + - Planifiqueu amb antelació, o serà un enorme caos! + - No borreu les vostres antigues fàbriques! Les necessitareu per + desbloquejar actualitzacions. + - Proveu de superar el nivell 20 pel vostre compte abans de buscar ajuda. + - No compliqueu les coses, intenteu ser senzill i arribareu molt lluny. + - És possible que hàgiu de tornar a utilitzar fàbriques més endavant del + joc. Planifiqueu les vostres fàbriques de forma que puguin ser + reutilitzables. + - De vegades, podeu trobar una forma necessària al mapa sense crear-la amb + apiladors. + - Els molins de vent o molins de vent complets mai no poden generar de forma + natural. + - Pinteu les formes abans de tallar per obtenir la màxima eficiència. + - Amb els mòduls, l’espai és només una percepció; una preocupació per als + homes mortals. + - Feu una fàbrica de plànols independent. Són importants per als mòduls. + - Feu una ullada més de prop al mesclador de colors i les vostres preguntes + seran contestades. + - Utilitzeu CTRL + Feu clic per seleccionar una àrea. + - Construir massa a prop del centre pot dificultar els projectes posteriors. + - La icona de fixació situada al costat de cada forma de la llista + d'actualitzacions la fixa a la pantalla. + - Barregeu tots els colors primaris per fer blanc. + - Teniu un mapa infinit, no restringiu la vostra fàbrica, amplieu-la. + - També proveu Factorio! És el meu joc preferit. + - El tallador de quadres talla en sentit horari a partir de la part superior + dreta. + - Podeu descarregar els vostres jocs desats al menú principal. + - Aquest joc té moltes combinacions de tecles útils. Assegureu-vos de + consultar el fitxer pàgina de configuració. + - Aquest joc té moltes opcions de configuració, no oblideu consultar-les. + - El marcador del concentrador té una petita brúixola per indicar-ne la + direcció. + - Per netejar els cinturons, talleu la zona i enganxeu-la al mateix lloc. + - Premeu F4 per mostrar la vostra tarifa FPS i Tick. + - Premeu F4 dues vegades per mostrar el mosaic del ratolí i la càmera. + - Podeu fer clic a una forma fixada al costat esquerre per desenganxar-la. diff --git a/translations/base-cz.yaml b/translations/base-cz.yaml index e722a7ee..147237d6 100644 --- a/translations/base-cz.yaml +++ b/translations/base-cz.yaml @@ -1,92 +1,60 @@ -# 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ě. + shortText: shapez.io je hra o stavbě továren na automatizaci výroby a + kombinování čím dál složitějších tvarů na nekonečné mapě. + discordLinkShort: Oficiální Discord + intro: >- + Máte rádi automatizaci? Tak to jste na správném místě! - # 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 relaxační hra, ve které musíte stavět továrny na automatizaci výroby geometrických tvarů. Jak se zvyšuje úroveň, tvary se stávají stále složitějšími a vy se musíte rozšířit po nekonečné mapě. - 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 jako by to nestačilo, musíte také produkovat exponenciálně více, abyste uspokojili požadavky - jediná věc, která pomáhá, je škálování! Zatímco na začátku tvary pouze zpracováváte, později je musíte obarvit - těžbou a mícháním barev! - 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]! - - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! + Koupením hry na platformě Steam získáte přístup k plné verzi hry, ale také můžete nejdříve hrát demo verzi na shapez.io a až potom se rozhodnout! + title_advantages: Výhody samostatné verze hry + advantages: + - 12 Nových úrovní z celkových 26 úrovní + - 18 Nových budov pro plně automatizovanou továrnu! + - 20 Řad vylepšení pro mnoho hodin zábavy! + - Wires Update pro zcela novou dimenzi! + - Tmavý mód! + - Neomezený počet uložených her + - Neomezené značky + - Podpořte mě! ❤️ + title_future: Plánovaný obsah + planned: + - Blueprintová knihovna + - Steam Achievements + - Puzzle mód + - Minimapa + - Módy + - Sandbox mód + - ... a mnohem více! + title_open_source: Tato hra je open source! + text_open_source: >- + Kdokoli může přispět, jsem aktivně zapojený do komunity, pokouším se + zkontrolovat všechny návrhy a vzít v úvahu zpětnou vazbu všude, kde je + to možné. + Nezapomeňte se podívat na můj trello board pro kompletní plán! + title_links: Odkazy + links: + discord: Oficiální Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Zdrojový kód (GitHub) + translate: Pomozte přeložit hru! global: - loading: Načítám + loading: Načítání error: Chyba - - # 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. + decimalSeparator: "," suffix: thousands: k millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: nekonečno - time: - # Used for formatting past time dates oneSecondAgo: před sekundou xSecondsAgo: před sekundami oneMinuteAgo: před minutou @@ -95,14 +63,10 @@ global: xHoursAgo: před hodinami oneDayAgo: včera xDaysAgo: před dny - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s hoursAndMinutesShort: h m - xMinutes: minut - keys: tab: TAB control: CTRL @@ -110,34 +74,26 @@ global: escape: ESC shift: SHIFT space: SPACE - demoBanners: - # This is the "advertisement" shown in the main menu and other various places title: Demo verze - intro: >- - Získejte plnou verzi pro odemknutí všech funkcí! - + intro: Získejte plnou verzi pro odemknutí všech funkcí a obsahu! mainMenu: play: Hrát - changelog: Změny + continue: Pokračovat + newGame: Nová hra + changelog: Seznam změn + subreddit: Reddit importSavegame: Importovat openSourceHint: Tato hra je open source! discordLink: Oficiální Discord Server helpTranslate: Pomozte přeložit hru! - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - Hrajete v nepodporovaném prohlížeči, je možné že hra poběží pomalu! Pořiďte si samostatnou verzi nebo vyzkoušejte prohlížeč Chrome pro plnohodnotný zážitek. - + madeBy: Vytvořil + browserWarning: Promiňte, ale víme, že hra poběží pomalu ve vašem prohlížeči! + Pořiďte si samostatnou verzi nebo si stáhněte Google Chrome pro + plnohodnotný zážitek. savegameLevel: Úroveň savegameLevelUnknown: Neznámá úroveň - - - continue: Pokračovat - newGame: Nová hra - madeBy: Vytvořil - subreddit: Reddit - + savegameUnnamed: Nepojmenovaný dialogs: buttons: ok: OK @@ -146,118 +102,109 @@ dialogs: later: Později restart: Restart reset: Reset - getStandalone: Získejte Plnou verzi - deleteGame: Vím co dělám + getStandalone: Získejte plnou verzi + deleteGame: Vím, co dělám viewUpdate: Zobrazit aktualizaci showUpgrades: Zobrazit vylepšení showKeybindings: Zobrazit klávesové zkratky - importSavegameError: title: Chyba Importu - text: >- - Nepovedlo se importovat vaši uloženou hru: - + text: "Nepovedlo se importovat vaši uloženou hru:" importSavegameSuccess: title: Uložená hra importována - text: >- - Vaše uložená hra byla úspěšně importována. - + text: Vaše uložená hra byla úspěšně importována. gameLoadFailure: title: Uložená hra je poškozená - text: >- - Nepovedlo se načíst vaši uloženou hru: - + text: "Nepovedlo se načíst vaši uloženou hru:" confirmSavegameDelete: title: Potvrdit smazání - text: >- - Opravdu chcete smazat hru? - + text: Jste si jisti, že chcete smazat tuto uloženou hru?

+ '' s úrovní

Tato akce je + nevratná! savegameDeletionError: title: Chyba mazání - text: >- - Nepovedlo se smazat vaši uloženou hru: - + text: "Nepovedlo se smazat vaši uloženou hru:" restartRequired: title: Vyžadován restart - text: >- - Pro aplikování nastavení musíte restartovat hru. - + text: Pro aplikování nastavení musíte restartovat hru. editKeybinding: title: Změna klávesové zkratky - desc: Zmáčkněte klávesu nebo tlačítko na myši pro přiřazení nebo Escape pro zrušení. - + desc: Zmáčkněte klávesu nebo tlačítko myši pro přiřazení nebo Escape pro + zrušení. resetKeybindingsConfirmation: title: Reset klávesových zkratek - desc: Opravdu chcete vrátit klávesové zkratky zpět do původního nastavení? - + desc: Toto vrátí všechny klávesové zkratky do původního nastavení. Prosím + potvrďte. keybindingsResetOk: title: Reset klávesových zkratek - desc: Vaše klávesové zkratky byly resetovány do původního nastavení! - + desc: Všechny klávesové zkratky byly vráceny do původního nastavení! featureRestriction: title: Demo verze - desc: Zkoušíte použít funkci (), která není v demo verzi. Pořiďte si plnou verzi pro lepší zážitek! - + desc: Zkoušíte použít funkci (), která není v demo verzi. Zvažte + pořízení plné verze pro kompletní zážitek! oneSavegameLimit: title: Omezené ukládání - desc: Ve zkušební verzi můžete mít pouze jednu uloženou hru. Odstraňte stávající uloženou hru nebo si pořiďte plnou verzi! - + desc: Ve demo verzi můžete mít pouze jednu uloženou hru. Odstraňte stávající + uloženou hru nebo si pořiďte plnou verzi! updateSummary: title: Nová aktualizace! - desc: >- - Tady jsou změny od posledně: - + desc: "Zde jsou změny od doby, kdy jste naposledy hráli:" upgradesIntroduction: title: Odemknout vylepšení - desc: >- - Všechny tvary, které vytvoříte, lze použít k odemčení vylepšení - Neničte své staré továrny! - Karta vylepšení se nachází v pravém horním rohu obrazovky. - + desc: Všechny tvary, které vytvoříte, lze použít k odemčení vylepšení - + Neničte své staré továrny! Kartu vylepšení lze + najít v pravém horním rohu obrazovky. massDeleteConfirm: title: Potvrdit smazání - desc: >- - Odstraňujete spoustu budov (přesněji )! Opravdu je chcete smazat? - - blueprintsNotUnlocked: - title: Zatím neodemčeno - desc: >- - Plány ještě nebyly odemčeny! Chcete-li je odemknout, dokončete úroveň 12. - - keybindingsIntroduction: - title: Užitečné klávesové zkratky - desc: >- - Hra má spoustu klávesových zkratek, které usnadňují stavbu velkých továren. - Zde jsou některé, ale nezapomeňte se podívat i na ostatní klávesové zkratky!

- CTRL + Táhnout: Vybrání oblasti.
- SHIFT: Podržením můžete umístit více budov za sebout.
- ALT: Změnit orientaci umístěných pásů.
- - 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 - - markerDemoLimit: - desc: V ukázce můžete vytvořit pouze dvě značky. Získejte plnou verzi pro neomezený počet značek! + desc: Odstraňujete spoustu budov (přesněji )! Opravdu je chcete smazat? massCutConfirm: title: Potvrdit vyjmutí - desc: >- - Chceš vyjmout spoustu budov (přesněji řečeno )! Vážně to - chceš udělat? - + desc: Vyjímáte spoustu budov (přesněji )! Opravdu je chcete vyjmout? + massCutInsufficientConfirm: + title: Potvrdit vyjmutí + desc: Nemůžete si dovolit vložení této oblasti! Opravdu ji chcete vyjmout? + blueprintsNotUnlocked: + title: Zatím neodemčeno + desc: Dokončete úroveň 12 pro odemčení Plánů! + keybindingsIntroduction: + title: Užitečné klávesové zkratky + desc: "Tato hra má spoustu klávesových zkratek, které usnadňují stavbu velkých + továren. Zde jsou některé, ale nezapomeňte se podívat i na + ostatní klávesové zkratky!

CTRL + Táhnout: Vybrání oblasti.
SHIFT: Podržením můžete umístit více budov + za sebou.
ALT: Změnit orientaci + umístěných pásů.
" + createMarker: + title: Nová značka + titleEdit: Upravit značku + desc: Použijte smysluplný název, můžete také zahrnout krátký + klíč tvaru (Ten můžete vygenerovat zde) + editSignal: + title: Nastavte signál + descItems: "Vyberte předdefinovanou položku:" + descShortKey: ... nebo zadejte krátký klíč tvaru (Ten můžete + vygenerovat zde) + markerDemoLimit: + desc: V demo verzi můžete vytvořit pouze dvě značky. Pořiďte si plnou verzi pro + neomezený počet značek! exportScreenshotWarning: title: Exportuj snímek obrazovky - desc: >- - Zažádal jsi o exportování své základny jako obrázek. Měj prosím na paměti, že to - 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? - + desc: Chcete exportovat svou základnu jako snímek obrazovky. Mějte prosím na + paměti, že to bude docela pomalé u větších základen a může dokonce + dojít k pádu hry! + renameSavegame: + title: Přejmenovat uloženou hru + desc: Zde můžete přejmenovat svoji uloženou hru. + tutorialVideoAvailable: + title: Dostupný tutoriál + desc: Pro tuto úroveň je k dispozici tutoriál! Chtěli byste se na + něj podívat? + tutorialVideoAvailableForeignLanguage: + title: Dostupný tutoriál + desc: Pro tuto úroveň je k dispozici tutoriál, ale je dostupný + pouze v angličtině. Chtěli byste se na něj podívat? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Posun mapy selectBuildings: Vybrat oblast @@ -274,22 +221,13 @@ ingame: lockBeltDirection: Zamknout směr pásu plannerSwitchSide: Otočit strany plánovače cutSelection: Vyjmout - copySelection: Kopířovat + copySelection: Kopírovat clearSelection: Zrušit výběr pipette: Kapátko - switchLayers: Switch layers - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + switchLayers: Změnit vrstvy 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: Zmáčkněte pro přepínání mezi variantami. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Klávesová zkratka: - + hotkeyLabel: "Klávesová zkratka: " infoTexts: speed: Rychlost range: Dosah @@ -297,36 +235,21 @@ ingame: oneItemPerSecond: 1 tvar / sekundu itemsPerSecond: tvarů / s itemsPerSecondDouble: (x2) - tiles: dílků - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Úroveň completed: Dokončeno unlockText: "Odemčeno: !" buttonNextLevel: Další úroveň - - # Notifications on the lower right notifications: - newUpgrade: Nová aktualizace je k dispozici! + newUpgrade: Nové vylepšení je k dispozici! gameSaved: Hra byla uložena. - - # The "Upgrades" window + freeplayLevelComplete: Level byl dokončen! shop: title: Vylepšení buttonUnlock: Vylepšit - - # Gets replaced to e.g. "Tier IX" tier: Úroveň - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXIMÁLNÍ ÚROVEŇ (Rychlost x) - - # The "Statistics" window statistics: title: Statistiky dataSources: @@ -335,55 +258,70 @@ ingame: description: Tvary uložené ve vaší centrální budově. produced: title: Vyprodukováno - description: Tvary která vaše továrna produkuje, včetně meziproduktů. + description: Tvary, která vaše továrna produkuje, včetně meziproduktů. delivered: title: Dodáno - description: Tvary které jsou dodávány do vaší centrální budovy. + description: Tvary, které jsou dodávány do vaší centrální budovy. noShapesProduced: Žádné tvary zatím nebyly vyprodukovány. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Herní čas - buildingsPlaced: Budovy beltsPlaced: Pásy - - buttons: - continue: Pokračovat - settings: Nastavení - menu: Návrat do menu - - # Bottom left tutorial hints tutorialHints: title: Potřebujete pomoct? showHint: Zobrazit nápovědu hideHint: Zavřít - - # When placing a blueprint blueprintPlacer: cost: Cena - - # Map markers waypoints: waypoints: Značky hub: HUB - description: Klepnutím levým tlačítkem myši na značku se přesunete na její umístění, klepnutím pravým tlačítkem ji odstraníte.

Stisknutím klávesy vytvoříte značku na aktuálním místě, nebo klepnutím pravým tlačítkem vytvoříte značku na vybraném místě na mapě. + description: Klepnutím levým tlačítkem myši na značku se přesunete na její + umístění, klepnutím pravým tlačítkem ji + odstraníte.

Stisknutím klávesy vytvoříte značku + na aktuálním místě, nebo klepnutím pravým tlačítkem + vytvoříte značku na vybraném místě na mapě. creationSuccessNotification: Značka byla vytvořena. - - # Interactive tutorial interactiveTutorial: title: Tutoriál hints: - 1_1_extractor: Umístěte extraktor na nalezištěkruhového tvaru a vytěžte jej! - 1_2_conveyor: >- - Připojte extraktor pomocí dopravníkového pásu k vašemu HUBu!

Tip: Klikněte a táhněte myší pro položení více pásů! - - 1_3_expand: >- - Toto NENÍ hra o čekání! Sestavte další extraktory a pásy, abyste dosáhli cíle rychleji.

Tip: Chcete-li umístit více extraktorů, podržte SHIFT. Pomocí R je můžete otočit. - + 1_1_extractor: Umístěte extraktor na nalezištěkruhového + tvaru a vytěžte jej! + 1_2_conveyor: "Připojte extraktor pomocí dopravníkového pásu k + vašemu HUBu!

Tip: Klikněte a táhněte + myší pro položení více pásů!" + 1_3_expand: "Toto NENÍ hra o čekání! Postavte další extraktory + a pásy, abyste dosáhli cíle rychleji.

Tip: Chcete-li + umístit více extraktorů, podržte SHIFT. Pomocí + R je můžete otočit." + 2_1_place_cutter: "Teď umístěte pilu k rozřezání kruhového tvaru na dvě + poloviny!

PS: Pila řeže tvary vždy svisle na + poloviny bez ohledu na její orientaci." + 2_2_place_trash: Pila se může zaseknout a zastavit vaši produkci!

Použijte + koš ke smazání (!) nepotřebných + částí tvarů. + 2_3_more_cutters: "Dobrá práce! Teď postavte více pil pro zrychlení + tohoto pomalého procesu!

PS: Použijte 0-9 + na klávesnici pro rychlejší přístup k budovám!" + 3_1_rectangles: "Teď vytěžte nějaké obdelníkové tvary! Postavte 4 + extraktory a připojte je k HUBu.

PS: + Podržením klávesy SHIFT a tažením pásu aktivujete + plánovač pásů!" + 21_1_place_quad_painter: Postavte čtyřnásobný barvič a získejte nějaké + kruhové tvary, bílou a + červenou barvu! + 21_2_switch_to_wires: Změňte vrstvy na vrstvu kabelů stisknutím klávesy + E!

Pak připojte všechny čtyři + vstupy barviče s pomocí kabelů! + 21_3_place_button: Úžasné! Teď postavte přepínač a připojte ho + pomocí kabelů! + 21_4_press_button: "Stiskněte přepínač pro změnu vysílaného logického + signálu a tím aktivujte barvič.

PS: Nemusíte + připojit veškeré vstupy! Zkuste spojit pouze dva." colors: red: Červená green: Zelená @@ -393,16 +331,50 @@ ingame: cyan: Tyrkysová white: Bílá uncolored: Bez barvy - black: Black + black: Černá shapeViewer: title: Vrstvy empty: Prázdné - copyKey: Copy Key - -# All shop upgrades + copyKey: Zkopírovat klíč + connectedMiners: + one_miner: 1 Extraktor + n_miners: Extraktorů + limited_items: Limit je + watermark: + title: Demo verze + desc: Kliknutím sem zobrazíte výhody Steam verze! + get_on_steam: Získejte na steamu + standaloneAdvantages: + title: Získejte plnou verzi! + no_thanks: Ne, děkuji! + points: + levels: + title: 12 Nových úrovní + desc: Celkem 26 úrovní! + buildings: + title: 18 Nových budov + desc: Plně automatizujte svou továrnu! + savegames: + title: ∞ Uložených her + desc: Tolik, kolik vaše srdce touží! + upgrades: + title: 20 vylepšení + desc: Tato demo verze má pouze 5! + markers: + title: ∞ Značek + desc: Nikdy se neztraťte ve své továrně! + wires: + title: Kabely + desc: Zcela nový rozměr! + darkmode: + title: Dark Mode + desc: Přestanou vás bolet oči! + support: + title: Podpořte mě + desc: Vyvíjím to ve svém volném čase! shopUpgrades: belt: - name: Pásy, distribuce & tunely + name: Pásy, distribuce a tunely description: Rychlost x → x miner: name: Extrakce @@ -413,282 +385,415 @@ shopUpgrades: painting: name: Míchání a barvení description: Rychlost x → x - -# Buildings and their name / description buildings: hub: deliver: Dodejte toUnlock: pro odemčení levelShortcut: LVL - + endOfDemo: konec Demo verze belt: default: - name: &belt Dopravníkový pás - description: Přepravuje tvary a barvy, přidržením můžete umístit více pásů za sebe tahem. - - miner: # Internal name for the Extractor + name: Dopravníkový pás + description: Přepravuje tvary a barvy, přidržením můžete tahem umístit více pásů + za sebou. + miner: default: - name: &miner Extraktor - description: Umístěte na náleziště tvaru nebo barvy pro zahájení těžby. - + name: Extraktor + description: Umístěte na naleziště tvaru nebo barvy pro zahájení těžby. chainable: name: Extraktor (Navazující) - description: Umístěte na náleziště tvaru nebo barvy pro zahájení těžby. Lze zapojit po skupinách. - - underground_belt: # Internal name for the Tunnel + description: Umístěte na naleziště tvaru nebo barvy pro zahájení těžby. Lze + zapojit po skupinách. + underground_belt: default: - name: &underground_belt Tunel + name: Tunel description: Umožňuje vézt suroviny pod budovami a pásy. - tier2: name: Tunel II. úrovně description: Umožňuje vézt suroviny pod budovami a pásy. - - splitter: # Internal name for the Balancer - default: - name: &splitter Balancer - description: Multifunkční - Rozděluje vstupy do výstupů. - - compact: - name: Spojka (levá) - description: Spojí dva pásy do jednoho. - - compact-inverse: - name: Spojka (pravá) - description: Spojí dva pásy do jednoho. - cutter: default: - name: &cutter Pila - description: Rozřízne tvar svisle na dvě části. Pokud použijete jen jednu půlku, nezapomeňte druhou smazat, jinak se vám produkce zasekne! + name: Pila + description: Rozřízne tvar svisle na dvě části. Pokud použijete jen + jednu půlku, nezapomeňte druhou smazat, jinak se vám produkce + zasekne! quad: name: Rozebírač - description: Rozebere tvar na čtyři části. Pokud použijete jen některé části, nezapomeňte ostatní smazat, jinak se vám produkce zasekne! - + description: Rozebere tvar na čtyři části. Pokud použijete jen některé + části, nezapomeňte ostatní smazat, jinak se vám produkce + zasekne! rotater: default: - name: &rotater Rotor + name: Rotor description: Otáčí tvary o 90 stupňů po směru hodinových ručiček. ccw: name: Rotor (opačný) - description: Otáčí tvary o 90 stupňů proti směru hodinových ručiček - + description: Otáčí tvary o 90 stupňů proti směru hodinových ručiček. + rotate180: + name: Rotor (180°) + description: Otáčí tvary o 180 stupňů. stacker: default: - name: &stacker Kombinátor - description: Spojí tvary dohromady. Pokud nemohou být spojeny, pravý tvar je položen na levý. - + name: Kombinátor + description: Spojí tvary dohromady. Pokud nemohou být spojeny, pravý tvar je + položen na levý. mixer: default: - name: &mixer Mixér na barvy + name: Mixér na barvy description: Smíchá dvě barvy. - painter: default: - name: &painter Barvič - description: &painter_desc Obarví celý tvar v levém vstupu barvou z pravého vstupu. + name: Barvič + description: Obarví celý tvar v levém vstupu barvou z pravého vstupu. double: name: Barvič (dvojnásobný) description: Obarví tvary z levých vstupů barvou z horního vstupu. quad: name: Barvič (čtyřnásobný) - description: Umožňuje obarvit každý dílek tvaru samostatně. + description: Umožnuje obarvit každou čtvrtinu tvaru individuálně. Jen čtvrtiny + se vstupy barev s logickým signálem na vrstvě + kabelů budou obarveny! mirrored: - name: *painter - description: *painter_desc - + name: Barvič + description: Obarví celý tvar v levém vstupu barvou z pravého vstupu. trash: default: - name: &trash Koš - description: Příjmá tvary a barvy ze všech stran a smaže je. Navždy. - - storage: - name: Sklad - description: Skladuje věci navíc až do naplnění kapacity. Může být použit na skladování surovin navíc. + name: Koš + description: Přijímá tvary a barvy ze všech stran a smaže je. Navždy. wire: default: - name: Energy Wire - description: Allows you to transport energy. - advanced_processor: + name: Kabel + description: Dovoluje přenos energie. + second: + name: Kabel + description: Dovoluje přenos energie. + balancer: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For - default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Vyvažovač + description: Multifunkční - Rovnoměrně rozděluje vstupy na výstupech. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Spojovač (kompaktní) + description: Spojí dva pásy do jednoho. + merger-inverse: + name: Spojovač (kompaktní) + description: Spojí dva pásy do jednoho. + splitter: + name: Rozdělovač (kompaktní) + description: Rozdělí jeden pás na dva. + splitter-inverse: + name: Rozdělovač (kompaktní) + description: Rozdělí jeden pás na dva. + storage: + default: + name: Sklad + description: Skladuje přebytečné věci až do naplnění kapacity. Může být použit + na skladování surovin navíc. + wire_tunnel: + default: + name: Křížení kabelů + description: Umožňuje křížení dvou kabelů bez jejich spojení. + constant_signal: + default: + name: Konstantní signál + description: Vydává konstantní signál, který může mít tvar, barvu nebo logickou + hodnotu (1 / 0). + lever: + default: + name: Přepínač + description: Lze přepínat, aby vydával signál (1/0) na vrstvě vodičů, pomocí + kterého lze například ovládat filtr tvarů a barev. + logic_gate: + default: + name: AND Gate + description: Vysílá signál "1" pokud oba vstupy vysílají signál. + not: + name: NOT Gate + description: Vysílá signál "1" pokud oba vstupy nevysílají signál. + xor: + name: XOR Gate + description: Vysílá signál "1" pokud jeden vstup vysílá signál, ale druhý vstup + nevysílá signál. + or: + name: OR Gate + description: Vysílá signál "1" pokud jeden vstup vysílá signál. + transistor: + default: + name: Tranzistor + description: Přeposílá spodní vstup, pokud boční vstup vysílá signál. + mirrored: + name: Tranzistor + description: Přeposílá spodní vstup, pokud boční vstup vysílá signál. + filter: + default: + name: Filtr + description: Připojte signál k třídění tvarů a barev. + display: + default: + name: Display + description: Připojte signál a zobrazte jej na displeji - může to být tvar nebo + barva. + reader: + default: + name: Čtečka pásů + description: Umožňuje změřit průměrnou propustnost pásu. Výstup čte poslední + položku ve vrstvě kabelů. + analyzer: + default: + name: Analyzátor tvarů + description: Analyzuje pravou horní část nejnižší vrstvy tvaru a vrací tvar a + barvu. + comparator: + default: + name: Porovnávač + description: Vrátí signál „1“, pokud jsou oba signály přesně stejné. Může + srovnávat tvary, předměty a signály. + virtual_processor: + default: + name: Virtuální pila + description: Virtuálně rozřízne tvar svisle na dvě části. + rotater: + name: Virtuální rotor + description: Virtuálně otáčí tvary o 90 stupňů po směru hodinových ručiček. + unstacker: + name: Virtuální extrahátor + description: Virtuálně extrahuje nejvyšší vrstvu do pravého výstupu a zbývající + do levé. + stacker: + name: Virtuální kombinátor + description: Virtuálně Spojí tvary dohromady. Pokud nemohou být spojeny, pravý + tvar je položen na levý. + painter: + name: Virtual barvič + description: Virtuálně obarví celý tvar v levém vstupu barvou z pravého vstupu. + item_producer: + default: + name: Výrobník předmětů + description: Dostupný pouze v sandboxovém módu, vydává daný signál z vrstvy + kabelů na běžnou vrstvu. storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Řezání tvarů - desc: Právě jste odemknuli pilu - řeže tvary svisle bez ohledu na svou orientaci!

Nezapomeňte se zbavovat odpadu, jinak se vám zasekne produkce - pro tento účel jsem vám odemknul koš, který můžete použít na mazání odpadu! - + desc: Právě jste odemkli pilu, která řeže tvary svisle na + poloviny bez ohledu na její + orientaci!

Nezapoměňte se zbavit zbytku tvarů, jinak + se vám produkce zasekne - za tímto účelem jsem vám + dal koš, který smaže vše, co do něj vložíte! reward_rotater: title: Otáčení - desc: Rotor byl právě odemčen! Otáčí tvary po směru hodinových ručiček o 90 stupňů. - + desc: Rotor byl právě odemčen! Otáčí tvary po směru hodinových + ručiček o 90 stupňů. 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! - + desc: "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 - desc: Mixér byl právě odemčen - zkombinuje dvě barvy pomocí aditivního míchání! - + desc: Mixér byl právě odemčen - zkombinuje dvě barvy pomocí + aditivního míchání! reward_stacker: title: Kombinátor - desc: Nyní můžete spojovat tvary pomocí kombinátor! Pokud to jde, oba tvary se slepí k sobě. Pokud ne, tvar vpravo se nalepí na tvar vlevo! - + desc: Nyní můžete spojovat tvary pomocí kombinátor! Pokud to + jde, oba tvary se slepí k sobě. Pokud ne, tvar + vpravo se nalepí na tvar vlevo! reward_splitter: - title: Rozřazování/Spojování pásu - desc: Multifuknční balancer byl právě odemčen - Může být použít pro stavbu větších továren díky tomu, že rozřazuje tvary mezi dva pásy!

- + title: Kompaktní rozdělovač + desc: Právě jste odemkli rozdělovací variantu + vyvažovače - Přijímá jeden vstup a rozdělí ho na + dva! reward_tunnel: title: Tunel - desc: Tunel byl právě odemčen - Umožňuje vézt suroviny pod budovami a pásy. - + desc: Tunel byl právě odemčen - Umožňuje vézt suroviny pod + budovami a pásy. reward_rotater_ccw: title: Otáčení II - desc: Odemknuli jste variantu rotoru - Umožňuje vám otáčet proti směru hodinových ručiček. Vyberte rotor a zmáčkněte 'T' pro přepnutí mezi variantami! - + desc: Odemknuli jste variantu rotoru - Umožňuje vám otáčet + proti směru hodinových ručiček. Vyberte rotor a zmáčkněte + 'T' pro přepnutí mezi variantami! reward_miner_chainable: title: Napojovací extraktor - desc: Odemknuli jste variantu extraktoru! Může přesměrovat vytěžené zdroje do dalších extraktorů pro efektivnější těžbu! - + desc: "Právě jste odemkli napojovací extraktor! Může + předat své zdroje ostatním extraktorům, čímž můžete + efektivněji těžit více zdrojů!

PS: Starý extraktor bude od + teď nahrazen ve vašem panelu nástrojů!" reward_underground_belt_tier_2: title: Tunel II. úrovně - desc: Odemknuli jste tunel II. úrovně - Má delší dosah a také můžete nyní míchat tunely dohromady! - - reward_splitter_compact: - title: Kompaktní spojka - desc: >- - Odemknuli jste variantu balanceru - Spojuje dva pásy do jednoho! - + desc: Odemknuli jste tunel II. úrovně - Má delší + dosah a také můžete nyní míchat tunely dohromady! reward_cutter_quad: title: Řezání na čtvrtiny - desc: Odemknuli jste variantu pily - Rozebírač vám umožňuje rozdělit tvary na čtvrtiny místo na poloviny! - + desc: Odemknuli jste variantu pily - Rozebírač vám umožňuje + rozdělit tvary na čtvrtiny místo na poloviny! reward_painter_double: title: Dvojité barvení - 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 - desc: Odemknuli jste variantu painter - Umožní vám nabarvit každou čtvrtinu tvaru jinou barvou! - + desc: Odemknuli jste variantu barviče - Funguje stejně jako + normální, ale nabarví dva tvary naráz pomocí jedné + barvy! reward_storage: title: Sklad - desc: Odemknuli jste variantu koše - Umožňuje vám skladovat věci až do určité kapacity! - + desc: Právě jste odemkli sklad - Umožnuje skladovat přebytečné + věci až do naplnění kapacity!

Dává prioritu levému výstupu, + takže ho také můžete použít jako průtokovou bránu! reward_freeplay: title: Volná hra - desc: Dokázali jste to! Odemknuli jste volnou hru! Další tvary jsou již náhodně generované! (pro plnou verzi plánujeme více obsahu!) - + desc: Zvládli jste to! Odemkli jste mód volné hry! To znamená, + budou od teď náhodně generovány!

Vzhledem k + tomu, že Hub nadále potřebuje propustnost , + především doporučuji postavit továrnu, která automaticky doručí + požadovaný tvar!

Hub vysílá požadovaný tvar na vrstvu + kabelů, takže jediné co musíte udělat, je analyzovat tvar a + automaticky nastavit svou továrnu dle této analýzy. reward_blueprints: title: Plány - desc: Nyní můžete kopírovat a vkládat části továrny! Vyberte oblast (Držte CTRL a táhněte myší) a zmáčkněte 'C' pro zkopírování.

Vkládání není zadarmo, potřebujete produkovat tvary pro plány na výstavbu! (Jsou to ty které jste právě dodali). - - # Special reward, which is shown when there is no reward actually + desc: Nyní můžete kopírovat a vkládat části továrny! Vyberte + oblast (Držte CTRL a táhněte myší) a zmáčkněte 'C' pro + zkopírování.

Vkládání není zadarmo, + potřebujete produkovat tvary pro plány na výstavbu! + (Jsou to ty které jste právě dodali). no_reward: title: Další úroveň - desc: >- - Tato úroveň vám nic neodemknula, ale s další to přijde!

PS: Radši neničte vaše stávající továrny - budete potřebovat všechny produkované tvary později na odemčení vylepšení! - + desc: "Tato úroveň vám nic neodemknula, ale s další to přijde!

PS: + Radši neničte vaše stávající továrny - budete potřebovat + všechny produkované tvary později na + odemčení vylepšení!" no_reward_freeplay: title: Další úroveň - desc: >- - Gratuluji! Mimochodem, více obsahu najdete v plné verzi! - + desc: Gratuluji! Mimochodem, více obsahu najdete v plné verzi! + reward_balancer: + title: Vyvažovač + desc: Multifunkční vyvažovač byl odemknut - Může + být použit ke zvětšení vašich továren rozdělováním a spojováním + předmětů na několik pásu! + reward_merger: + title: Kompaktní spojovač + desc: Právě jste odemkli spojovací variantu + vyvažovače - Přijímá dva vstupy a spojí je do + jednoho! + reward_belt_reader: + title: Čtečka pásů + desc: Právě jste odemkli čtečku pásů! Umožnuje vám změřit + propustnost pásu.

A počkejte na odemčení kabelů - později to + bude velmi užitečné! + reward_rotater_180: + title: Rotor (180°) + desc: Právě jste odemkli 180 stupňoví rotor! - Umožňuje vám + otáčet tvar o 180 stupňů! + reward_display: + title: Display + desc: "Právě jste odemkli Display - Připojte signál ve vrstvě + kabelů pro vizualizaci!

PS: Všimli jste si, že čtečka pásů a + sklad vysílájí jejich poslední přečtěný předmět? Zkuste ho ukázat na + displeji!" + reward_constant_signal: + title: Konstantní signál + desc: Právě jste odemkli konstantní signál na vrstvě kabelů! + Tohle je například užitečné pro připojení k filtrům + předmětů .

Konstantní signál může vysílat + tvar, barvu nebo logickou + hodnotu (1 / 0). + reward_logic_gates: + title: Logické brány + desc: Právě jste odemkli logické brány! Nemusíte být zrovna + nadšení, ale ve skutečnosti je to celkem cool!

S těmito + bránami můžete propočítat AND, OR, XOR a NOT operace.

Jako + bonus navíc vám také zpřístupním tranzistor! + reward_virtual_processing: + title: Virtuální zpracování + desc: Právě jsem zpřístupnil spoustu nových budov, které vám umožní + simulovat výrobu různých tvarů!

Můžete teď + také simulovat pilu, rotor, kombinátor a mnoho dalšího na vrstvě + kabelů! Nadále máte tři možnosti, jak pokračovat ve hře:

- + Postavit automatickou továrnu k vytvoření + jakéhokoliv tvaru požadovaného Hubem (Doporučuji to alespoň + vyzkoušet!).

- Postavit něco zajímavého s použitím + kabelů.

- Pokračovat ve hře pravidelně.

Bez ohledu + na tvou volbu, nezapomeň si svou hru užít! + reward_wires_painter_and_levers: + title: Kabely a 4x-barvič + desc: "Právě jste odemkli vrstvu kabelů: Je to samostatná + vrstva navíc oproti běžné vrstvě a představuje spoustu nových + možností!

Do začátku jsem zpřístupnil čtyřnásobný + barvič - Připojte vstupy, které byste chtěli obarvit + na vrstvě kabelů!

Pro přepnutí mezi vrstvami stiskněte klávesu + E.

PS: Aktivujte nápovědy v + nastavení pro spuštění tutoriálu o kabelech!" + reward_filter: + title: Filtr předmětů + desc: Právě jste odemkli filtr předmětů! Nasměruje předměty buď + na horní nebo pravý výstup podle toho, zda se shodují nebo neshodují + se signálem na vrstvě kabelů.

Také můžete vyslat logickou + hodnotu (1 / 0) pro zapnutí nebo kompletní vypnutí filtru. + reward_demo_end: + title: Konec demo verze + desc: Právě jste dosáhli konce demo verze! settings: title: Nastavení categories: - game: Hra - app: Aplikace - + general: Obecné + userInterface: Uživatelské rozhraní + advanced: Rozšířené + performance: Výkon versionBadges: dev: Vývojová verze staging: Testovací verze prod: Produkční verze buildDate: Sestaveno - labels: uiScale: title: Škálování UI - description: >- - Změní velikost uživatelského rozhraní. Rozhraní se bude stále přizpůsobovoat rozlišení vaší obrazovky, toto nastavení pouze mění jeho škálu. + description: Změní velikost uživatelského rozhraní. Rozhraní se bude stále + přizpůsobovat rozlišení vaší obrazovky, toto nastavení pouze + mění jeho škálu. scales: super_small: Velmi malé small: Malé regular: Normální large: Velké huge: Obrovské - scrollWheelSensitivity: - title: Citlivost přibížení - description: >- - Změní citlivost přiblížení (kolečkem myši nebo trackpadem). + title: Citlivost přiblížení + description: Změní citlivost přiblížení (kolečkem myši nebo trackpadem). sensitivity: super_slow: Hodně pomalé slow: Pomalé regular: Normální fast: Rychlé super_fast: Hodně rychlé - language: title: Jazyk - description: >- - Změní jazyk. Všechny překlady jsou vytvářeny komunitou a nemusí být kompletní. - + description: Změní jazyk. Všechny překlady jsou vytvářeny komunitou a nemusí být + kompletní. fullscreen: title: Celá obrazovka - description: >- - Doporučujeme hrát v režimu celé obrazovky pro nejlepší zážitek. Dostupné pouze v plné verzi. - + description: Doporučujeme hrát v režimu celé obrazovky pro nejlepší zážitek. + Dostupné pouze v plné verzi. soundsMuted: title: Ztlumit zvuky - description: >- - Ztlumí všechny zvuky. - + description: Ztlumí všechny zvuky. musicMuted: title: Ztlumit hudbu - description: >- - Ztlumí veškerou hudbu. - + description: Ztlumí veškerou hudbu. theme: title: Motiv - description: >- - Vybere motiv (světlý / tmavý). - + description: Vybere motiv (světlý / tmavý). themes: dark: Tmavý light: Světlý - refreshRate: title: Obnovovací frekvence - description: >- - Pokud máte 144 Hz monitor, změňte si rychlost obnovování obrazu. Toto nastavení může snížit FPS, pokud máte pomalý počítač. - + description: Pokud máte 144 Hz monitor, změňte si rychlost obnovování obrazu. + Toto nastavení může snížit FPS, pokud máte pomalý počítač. alwaysMultiplace: title: Několikanásobné pokládání - description: >- - Pokud bude zapnuté, zůstanou budovy vybrané i po postavení do té doby než je zrušíte. Má to stejný efekt jako držení klávesy SHIFT. - + description: Pokud bude zapnuté, zůstanou budovy vybrané i po postavení do té + doby, než je zrušíte. Má to stejný efekt jako držení klávesy + SHIFT. offerHints: title: Tipy & Nápovědy - description: >- - Pokud zapnuté, budou se ve hře zobrazovat tipy a nápovědy. Také schová určité elementy na obrazovce pro jednodušší dostání se do hry. - + description: Pokud zapnuté, budou se ve hře zobrazovat tipy a nápovědy. Také + schová určité elementy na obrazovce pro jednodušší dostání se do + hry. movementSpeed: title: Rychlost kamery description: Mění, jak rychle se kamera posouvá při použití klávesnice. @@ -697,22 +802,21 @@ settings: slow: Pomalá regular: Normální fast: Rychlá - super_fast: Hodně Rychlá - extremely_fast: Extrémně Rychlá + super_fast: Hodně rychlá + extremely_fast: Extrémně rychlá enableTunnelSmartplace: title: Chytré tunely - description: >- - Pokládání tunelů po zapnutí bude samo odstraňovat nepotřebné pásy. - Umožňuje také potahování tunelů a nadbytečné tunely budou odstraněny. + description: Pokládání tunelů po zapnutí bude samo odstraňovat nepotřebné pásy. + Umožňuje také potahování tunelů a nadbytečné tunely budou + odstraněny. vignette: title: Viněta - description: >- - Zapne vinětu, která ztmaví rohy obrazovky, což umožňuje lepší čtení textu. - + description: Zapne vinětu, která ztmaví rohy obrazovky, což umožňuje lepší čtení + textu. autosaveInterval: title: Interval automatického ukládání - description: >- - Určuje jak často se hra automaticky ukládá. Lze ji zde také úplně zakázat. + description: Určuje jak často se hra automaticky ukládá. Lze ji zde také úplně + zakázat. intervals: one_minute: 1 minuta two_minutes: 2 minuty @@ -720,36 +824,79 @@ settings: ten_minutes: 10 minut twenty_minutes: 20 minut disabled: Zrušeno - compactBuildingInfo: title: Kompaktní informace o stavbách - description: >- - Zkrátí informační políčka pro budovy tím, že pouze ukáže jejich koeficient. - V opačném případě zobrazí popis a obrázek. - + description: Zkrátí informační políčka pro budovy tím, že pouze ukáže jejich + koeficient. V opačném případě zobrazí popis a obrázek. disableCutDeleteWarnings: title: Zakázat upozornění o vyjmutí nebo odstranění - description: >- - Deaktivujte varovná dialogová okna vyvolaná při vymutí/mazání více než 100 - entit. - + description: Deaktivujte varovná dialogová okna vyvolaná při vyjmutí/mazání více + než 100 entit. enableColorBlindHelper: title: Režim pro barvoslepé - description: Zapné různé nástroje, které vám umožní hrát hru i pokud jste barvoslepí. + description: Zapne různé nástroje, které vám umožní hrát hru i pokud jste + barvoslepí. 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. - + title: Rotace dle typu budov + description: Každý typ budovy si zapamatuje poslední rotaci, na kterou jste je + individuálně nastavili. Tohle může být pohodlnější pokud často + přepínáte mezi pokládáním budov různých typů. + soundVolume: + title: Hlasitost zvuků + description: Nastavte hlasitost zvukových efektů + musicVolume: + title: Hlasitost hudby + description: Nastavte hlasitost hudby + lowQualityMapResources: + title: Nižší kvalita zdrojů na mapě + description: Zjednoduší vykreslování zdrojů na mapě při přiblížení pro zlepšení + výkonu. Také to zlepšuje vzhled hry, takže neváhejte toto + nastavení vyzkoušet! + disableTileGrid: + title: Vypnout mřížku + description: Vypnutí mřížky částic může pomoct s výkonem. Toto nastavení + zlepšuje vzhled hry! + clearCursorOnDeleteWhilePlacing: + title: Uvolní kurzor při kliknutím pravým tlačitkem + description: Povoleno dle výchozího nastavení, uvolní kurzor pokaždé co kliknete + pravým tlačítkem, když máte budovu vybranou pro pokládání. Při + vypnutí, můžete smazat budovy při kliknutí pravým tlačikem spolu + s položením dalších budov. + lowQualityTextures: + title: Nižší kvalita textur (Horší vzhled) + description: Používá nižší kvalitu textur pro zlepšení výkonu. Toto nastavení + zhorší vzhled hry! + displayChunkBorders: + title: Zobrazit hranice oblastí + description: Hra je rozdělena na oblasti 16x16 částic. Pokud je toto nastavení + povolené, zobrazí se hranice těchto oblastí. + pickMinerOnPatch: + title: Vybrat extraktor na naležistě zdrojů + description: Povoleno dle výchozího nastavení, vybere extraktor, pokud použijete + kapátko pro kliknutí na nalezistě zdrojů. + simplifiedBelts: + title: Zjednodušené pásy (Horší vzhled) + description: Nevykresluje předměty na pásech, pokud nad nimi nepřejíždíte + kurzorem, pro ušetření výkonu. Nedoporučuji hrát s tímto + nastavením, pokud opravdu nepotřebujete ušetřit výkon. + enableMousePan: + title: Posouvání myší + description: Umožnuje posouvání po mapě, pokud myší přejedete na okraj + obrazovky. Rychlost žáleží na nastavení rychlosti pohybu. + zoomToCursor: + title: Přiblížení ke kurzoru + description: Při zapnutí dojde k přibližování ve směru polohy + kurzoru, jinak ve středu obrazovky. + mapResourcesScale: + title: Velikost zdrojů na mapě + description: Určuje velikost ikon tvarů na náhledu mapy (při + oddálení). + rangeSliderPercentage: % keybindings: title: Klávesové zkratky - hint: >- - Tip: Nezapomeňte používat CTRL, SHIFT a ALT! Díky nim můžete měnit způsob stavění. - + hint: "Tip: Nezapomeňte používat CTRL, SHIFT a ALT! Díky nim můžete měnit způsob + stavění." resetKeybindings: Resetovat nastavení klávesových zkratek - categoryLabels: general: Aplikace ingame: Hra @@ -758,7 +905,6 @@ keybindings: massSelect: Hromadný výběr buildings: Zkratky pro stavbu placementModifiers: Modifikátory umístění - mappings: confirm: Potvrdit back: Zpět @@ -768,38 +914,30 @@ keybindings: mapMoveLeft: Posun doleva mapMoveFaster: Rychlejší posun centerMap: Vycentrovat mapu - mapZoomIn: Přiblížit mapZoomOut: Oddálit createMarker: Vytvořit značku - menuOpenShop: Vylepšení menuOpenStats: Statistiky - toggleHud: Přepnout HUD toggleFPSInfo: Přepnout zobrazení FPS a ladících informací - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + belt: Dopravníkový pás + underground_belt: Tunel + miner: Extraktor + cutter: Pila + rotater: Rotor + stacker: Kombinátor + mixer: Mixér na barvy + painter: Barvič + trash: Koš rotateWhilePlacing: Otočit - rotateInverseModifier: >- - Modifikátor: Otočit proti směru hodinových ručiček + rotateInverseModifier: "Modifikátor: Otočit proti směru hodinových ručiček" cycleBuildingVariants: Změnit variantu confirmMassDelete: Potvrdit hromadné smazání cycleBuildings: Změnit budovu - massSelectStart: Držte a táhněte pro vybrání oblasti massSelectSelectMultiple: Vybrat více oblastí massSelectCopy: Zkopírovat oblast - placementDisableAutoOrientation: Zrušit automatickou orientaci placeMultiple: Zůstat ve stavebním módu placeInverse: Přepnout automatickou orientaci pásů @@ -809,35 +947,40 @@ keybindings: lockBeltDirection: Zamknout směr pásu switchDirectionLockSide: Otočit strany zámku plánovače pipette: Kapátko - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire - + menuClose: Zavřít menu + switchLayers: Změnit vrstvy + wire: Kabel + balancer: Vyvažovač + storage: Sklad + constant_signal: Konstantní signál + logic_gate: Logická brána + lever: Přepínač (běžný) + filter: Filtr + wire_tunnel: Křížení kabelů + display: Display + reader: Čtečka pásů + virtual_processor: Virtuální pila + transistor: Tranzistor + analyzer: Analyzátor tvarů + comparator: Porovnávač + item_producer: Výrobník předmětů (Sandbox) + copyWireValue: "Kabely: Zkopírovat hodnotu pod kurzorem" about: title: O hře body: >- - Tato hra je open source a je vyvíjená Tobiasem Springerem (česky neumí, ale je to fakt frajer :) ).

+ Tato hra je open source. Je vyvíjená Tobiasem Springerem + (česky neumí, ale je fakt frajer :) ).

- Pokud se chceš na hře podílet, podívej se na shapez.io na githubu.

+ 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 - okolo Tobiasových her - Vážně by ses měl přijít mrknout na discord server!

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

- Soundtrack udělal Peppsen - Je úžasnej.

- - V neposlední řadě by Tobias (já jen tlumočím) rád poděkoval skvělému kamarádovi Niklasi - Bez hodin strávených - u factoria by tato hra nikdy neexistovala. + Soundtrack udělal Peppsen - Je úžasnej.

+ V neposlední řadě by Tobias (já jen tlumočím) rád poděkoval skvělému kamarádovi Niklasi - Bez hodin strávených u factoria by tato hra nikdy neexistovala. changelog: title: Seznam změn - demo: features: restoringGames: Nahrávání uložených her @@ -845,5 +988,74 @@ demo: oneGameLimit: Omezeno pouze na jednu uloženou hru customizeKeybindings: Změna klávesových zkratek exportingBase: Exportovat celou základnu jako obrázek - settingNotAvailable: Nedostupné v demo verzi. +tips: + - Hub přijímá vstup jakéhokoliv tvaru, nejen právě požadovaný tvar! + - Ujistěte se, že vaše továrny jsou rozšiřitelné - vyplatí se to! + - Nestavte přilíš blízko Hubu nebo vznikne velký chaos! + - Pokud skládání nefunguje, zkuste prohodit vstupy. + - Směr plánovače pásů můžete změnit stisknutím klávesy R. + - Držení klávesy CTRL umožnuje natažení pásů bez auto-orientace. + - Poměry zůstávají stejné, dokud jsou všechny vylepšení na stejné úrovní. + - Sériové zapojení je efektivnější nez paralelní. + - V průběhu hry později odemknete další varianty mnoha budov! + - Můžete použít klávesu T k přepnutí mezi různými variantami. + - Symetrie je klíčová! + - Můžete proplétat různé úrovně tunelů. + - Snažte se postavit kompaktní továrny - vyplatí se to! + - Barvič má zrcadlově otočenou variantu, kterou můžete vybrat klávesou + T + - Užití správné kombinace vylepšení maximalizuje efektivitu. + - Na maximální úrovní, 5 extraktorů zaplní jeden celý pás. + - Nezapomeňte na tunely! + - Pro plnou efektivitu nemusíte rozdělovat předměty rovnoměrně. + - Držení klávesy SHIFT spolu s pásy aktivuje plánovač pásy, který vám + snadno umožní postavit dlouhé řady pásů. + - Pily řežou vždy svisle, bez ohledu na jejich orientaci. + - Smícháním všech 3 barev získáte bílou barvu. + - Sklad preferuje levý výstup. + - Investujte čas pro vytvoření opakovatelných designů - ulehčí vám to + pozdější expanzy! + - Držení klávesy CTRL umožnuje postavit více budov stejného typu. + - Můžete podržet klávesu ALT k obrácení směru pokládaných pásů. + - Efektivita je klíčová! + - Nalezistě zdrojů, které jsou více vzdálené od Hubu, jsou větší. + - Továrny mají omezenou rychlost, rozdělte předměty pro vyšší efektivitu. + - Použijte vyvažovače pro maximalizaci efektivity. + - Organizace je důležitá. Zkuste nekřížit příliš mnoho pásů. + - Plánujte dopředu, abyste předešli vzniku velkého chaosu! + - Neodstraňujte své staré továrny! Budete je potřebovat pro další vylepšení. + - Před vyhledáním pomoci zkuste sami porazit úroveň 20! + - Snažte se věci nekomplikovat, zůstaňtě u jednoduchých designů a dostanete + se daleko. + - Možná budete muset použít stejné továrny i v budoucnu. Vytvořte své + továrny takovým stylem, abyste je mohli použít i v dalších případech. + - V nektěrých případech můžete najít celý požadovaný tvar bez nutnosti jeho + výroby s pomocí kombinátorů. + - Celý tvar typu mlýnu se na mapě nikdy nevyskytne. + - Obarvěte své tvary před řezáním pro zvýšení efektivity. + - S moduly, prostor je pouze vnímáním; starost pro smrtelníky. + - Vytvořtě si samostatnou továrnu jen na plány (blueprinty). Jsou důležité + pro moduly. + - Podívejte se zblízka na míchač barev, a vaše otázky budou odpovězeny. + - Použijte klávesu CTRL a myš pro označení oblasti. + - Pokud stavíte příliš blízko Hubu, v budoucnu můžete narazit na problémy s + dalšími projekty. + - Ikona připínáčku vedle každého tvaru vám umožnuje připnout tvar, čímž se + vám bude neustále zobrazovat vlevo na obrazovce. + - Smíchejte všechny základní barvy pro vytvoření bílé barvy! + - Vaše mapa je nekonečná, nesnažte se postavit továrnu na malinkém prostoru, + rozšiřte se do okolí! + - Neváhejte vyzkoušet hru Factorio! Je to má oblíbená hra. + - Rozebírač funguje po směru hodinových ručiček, počínaje pravým horním + rohem! + - V hlavním menu můžete stáhnout své uložené hry! + - Tato hra má spoustu užitečných klávesových zkratek! Určitě si je projděte + v nastavení. + - Tato hra má spoustu nastavení, určitě si je projděte! + - Značka Hubu má vedle sebe malý kompas, který ukazuje směr k Hubu! + - Pro vyčistění pásů, vyjměte budovy z prostoru a pak je zkopírujte zpět na + stejné místo. + - Stisknutím F4 zobrazíte FPS a rychlost ticků. + - Stisknutím F4 dvakrát zobrazíte častici myši a kamery. + - Můžete kliknout na připínáček vlevo vedle připnutého tvaru k jeho odepnutí. diff --git a/translations/base-da.yaml b/translations/base-da.yaml index a87f7587..f0b5f4e3 100644 --- a/translations/base-da.yaml +++ b/translations/base-da.yaml @@ -1,866 +1,1070 @@ -# -# 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 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. + discordLinkShort: Official Discord + intro: >- + Shapez.io er et afslapet spil hvor du skal bygge fabrikker for at + automatisere productionen af geometriske figurer. - # 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] + Jo længer du når, jo mere kompliseret bliver figurene, og du bliver nød til at spræde dig ud på den grænseløse spilleflade. - 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. + og hvis det ikke var nok, så skal du også producere eksponentielt flere figurer for at måde behovene spillet giver dig - det eneste der virker er skalering! - 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]! + Mens du i starten kun laver former, skal du senere farve lægge dem - for at gøre dette skal du udvinde og blande farver! - 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. + At købe spllet på Steam, giver dig adgang til det fulde spil, men du kan også spille en demo version på shapez.io og vælge senere! + title_advantages: Steam version Fordele + advantages: + - 12 Nye Niveauer for i alt 26 niveauer + - 18 Nye Byginger for en fuldt autmaticeret fabrik! + - 20 Upgraderings Niveauer for mange timers sjov! + - Wires Update for an entirely new dimension! + - Dark Mode! + - Unlimited Savegames + - Uendelige Markører + - Hjælp med at støtte mig! ❤️ + title_future: Planned Content + planned: + - Blueprint Library (Standalone Exclusive) + - Steam Achievements + - Puzzle Mode + - Minimap + - Mods + - Sandbox mode + - ... and a lot more! + title_open_source: This game is open source! + title_links: Links + links: + discord: Official Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Help translate + text_open_source: >- + Anybody can contribute, I'm actively involved in the community and + attempt to review all suggestions and take feedback into consideration + where possible. - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! - global: - loading: Loading - error: Error - - # 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. + loading: Indlæser + error: Fejl + thousandsDivider: . + decimalSeparator: "," suffix: thousands: k - millions: M - billions: B - trillions: T - - # Shown for infinitely big numbers - infinite: inf - + millions: mio + billions: mia + trillions: bio + 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 - - # Short formats for times, e.g. '5h 23m' + 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 secondsShort: s minutesAndSecondsShort: m s - hoursAndMinutesShort: h m - - xMinutes: minutes - + hoursAndMinutesShort: t m + xMinutes: minutter keys: tab: TAB control: CTRL alt: ALT escape: ESC - shift: SHIFT - space: SPACE - + shift: SKIFT/SHIFT + 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! - + intro: 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 - - # 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 - - - + importSavegame: Importér + openSourceHint: Dette spil er open source! + discordLink: Officiel Discord Server + helpTranslate: Hjælp med at oversætte! + madeBy: Lavet af + browserWarning: 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 + savegameUnnamed: Unnamed 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 - text: >- - Failed to import your savegame: - + title: Import Fejl + text: "Importering af gemt spil fejlede:" importSavegameSuccess: - title: Savegame Imported - text: >- - Your savegame has been successfully imported. - + title: Gemt spil Importeret + text: Dit gemte spil blev importet. gameLoadFailure: - title: Game is broken - text: >- - Failed to load your savegame: - + title: Spillet er i stykker + text: "Det lykkedes ikke at åbne dit gemte spil:" confirmSavegameDelete: - title: Confirm deletion - text: >- - Are you sure you want to delete the game? - + title: Bekræft sletning + text: Are you sure you want to delete the following game?

+ '' at level

This can not be + undone! savegameDeletionError: - title: Failed to delete - text: >- - Failed to delete the savegame: - + title: Sletning fejlede + text: "Det lykkedes ikke at slette dit gemte spil:" restartRequired: - title: Restart required - text: >- - You need to restart the game to apply the settings. - + title: Genstart er nødvendig + text: 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! - desc: >- - Here are the changes since you last played: - + title: Ny opdatering! + desc: "Dette har ændret sig siden sidst du spillede:" upgradesIntroduction: - title: Unlock Upgrades - 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. - + title: Få Opgraderinger + desc: 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 - desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? - + title: Bekræft sletning + desc: 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 - desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you want to do this? - + title: Bekræft klip + desc: 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 - desc: >- - Complete level 12 to unlock Blueprints! - + title: Ikke tilgængeligt endnu + desc: Gennemfør Niveau 12 for at bruge arbejdstegninger! keybindingsIntroduction: - title: Useful 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.
- + title: Brugbare keybindings + desc: "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: Give it a meaningful name, you can also include a short + key of a shape (Which you can generate here) + 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? + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: Rename Savegame + desc: You can rename your savegame here. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? 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 - - # Names of the colors, used for the color blind mode + switchLayers: Skift Lag 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 - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + white: Hvid + uncolored: Ingen farve + black: Sort 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. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - + cycleBuildingVariants: Tryk for at vælge type. + 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 - - # The notification when completing a level + tiles: flader levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: Level - completed: Completed - unlockText: Unlocked ! - buttonNextLevel: Next Level - - # Notifications on the lower right + levelTitle: Niveau + completed: Klaret + unlockText: er nu tilgængelig! + buttonNextLevel: Næste Niveau notifications: - newUpgrade: A new upgrade is available! - gameSaved: Your game has been saved. - - # The "Upgrades" window + newUpgrade: En ny opgradering er tilgængelig! + gameSaved: Dit spil er gemt. + freeplayLevelComplete: Level has been completed! shop: - title: Upgrades - buttonUnlock: Upgrade - - # Gets replaced to e.g. "Tier IX" - tier: Tier - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - - maximumLevel: MAXIMUM LEVEL (Speed x) - - # The "Statistics" window + title: Opgraderinger + buttonUnlock: Opgrader + tier: Trin + maximumLevel: HØJESTE NIVEAU (Speed x) 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. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + title: Afleveret + description: Viser figurer som er afleveret til din centrale bygning. + noShapesProduced: Ingen figurer er blevet produceret indtil videre. + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: - playtime: Playtime - - buildingsPlaced: Buildings - beltsPlaced: Belts - - buttons: - continue: Continue - settings: Settings - menu: Return to menu - - # Bottom left tutorial hints + playtime: Spilletid + buildingsPlaced: Bygninger + beltsPlaced: Bælter tutorialHints: - title: Need help? - showHint: Show hint - hideHint: Close - - # When placing a blueprint + title: Har du brug for hjælp? + showHint: Vis hint + hideHint: Luk blueprintPlacer: - cost: Cost - - # Map markers + cost: Pris 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. - - # Shape viewer + 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. shapeViewer: - title: Layers - empty: Empty - copyKey: Copy Key - - # Interactive tutorial + title: Lag + empty: Tom + copyKey: Kopier Kode interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! - 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. - -# All shop upgrades + 1_1_extractor: Sæt en udvinder på toppen af + encirkelfigur for at begynde produktion af den! + 1_2_conveyor: "Forbind udvinderen til din hub med et + transportbælte!

Tip: Tryk og + træk bæltet med din mus!" + 1_3_expand: "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." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limited to + watermark: + title: Demo version + desc: Click here to see the Steam version advantages! + get_on_steam: Get on steam + standaloneAdvantages: + title: Get the full version! + no_thanks: No, thanks! + points: + levels: + title: 12 New Levels + desc: For a total of 26 levels! + buildings: + title: 18 New Buildings + desc: Fully automate your factory! + savegames: + title: ∞ Savegames + desc: As many as your heart desires! + upgrades: + title: 20 Upgrade Tiers + desc: This demo version has only 5! + markers: + title: ∞ Markers + desc: Never get lost in your factory! + wires: + title: Wires + desc: An entirely new dimension! + darkmode: + title: Dark Mode + desc: Stop hurting your eyes! + support: + title: Support me + desc: I develop it in my spare time! 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 - -# Buildings and their name / description + name: Blanding & Maling + description: Fart x → x buildings: hub: - deliver: Deliver - toUnlock: to unlock - levelShortcut: LVL - + deliver: Aflever + toUnlock: for at få adgang til + levelShortcut: NIV + endOfDemo: End of Demo belt: default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. - - miner: # Internal name for the Extractor + name: Transportbælte + description: Transporterer figurer, hold og træk for at sætte flere. + miner: default: - name: &miner Extractor - description: Place over a shape or color to extract it. - + name: 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. - - underground_belt: # Internal name for the Tunnel + name: Udvinder (Kæde) + description: Placer over en figur eller farve for at udvinde den. Kan kædes. + underground_belt: default: - name: &underground_belt Tunnel - description: Allows to tunnel resources under buildings and belts. - + name: Tunnel + description: Laver tunneller under bygninger og bælter. 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. - + name: Tunnel Trin II + description: Laver tunneller under bygninger og bælter. 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: 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: 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. + rotate180: + name: Rotate (180) + description: Rotates shapes by 180 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. - + name: 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: 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: Maler + description: Farver hele figuren fra venstre side med farven fra toppen. mirrored: - name: *painter - description: *painter_desc - + name: Maler + description: Farver hele figuren fra venstre side med farven fra toppen. 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: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! 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. - - energy_generator: - deliver: Deliver - toGenerateEnergy: For energy - - default: - name: &energy_generator Energy Generator - description: Generates energy by consuming shapes. Each energy generator requires a different shapes. + name: Skraldespand + description: Tillader input fra alle sider og ødelægger dem. For evigt. wire: default: - name: Energy Wire - description: Allows you to transport energy. - advanced_processor: + name: Energiledning + description: Lader dig transportere energi. + second: + name: Wire + description: Transfers signals, which can be items, colors or booleans (1 / 0). + Different colored wires do not connect. + balancer: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Merger (compact) + description: Merges two conveyor belts into one. + merger-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + storage: + default: + name: Storage + description: Stores excess items, up to a given capacity. Prioritizes the left + output and can be used as an overflow gate. + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: Switch + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means + shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. + (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means + shape, color or boolean "1") + transistor: + default: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + mirrored: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: Belt Reader + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: Virtual Cutter + description: Virtually cuts the shape into two halves. + rotater: + name: Virtual Rotater + description: Virtually rotates the shape, both clockwise and counter-clockwise. + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the + remaining ones to the left. + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the shape on + the right input. + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the + wires layer on the regular layer. 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: You just unlocked the cutter, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! 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 - 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! - + title: Maling + desc: "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: The mixer has been unlocked - It mixes two colors using + additive blending! 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: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! 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: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" 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! - - 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! - + 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_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! - - 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: 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_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: You have unlocked the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! 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: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. 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). - - # Special reward, which is shown when there is no reward actually + 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). 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! - + title: Næste niveau + desc: "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 - desc: >- - Congratulations! By the way, more content is planned for the standalone! - + title: Næste niveau + desc: Tillykke! Forresten er mere indhold planlagt for den betalte version! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: End of Demo + desc: You have reached the end of the demo version! settings: - title: Settings + title: Indstillinger categories: - game: Game - app: Application - + general: Generelt + userInterface: Brugerflade + advanced: Avanceret + performance: Performance versionBadges: - dev: Development - staging: Staging - prod: Production - buildDate: Built - + dev: Udvikling + staging: Iscenesættelse + prod: Produktion + buildDate: Bygget labels: 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. + title: Grænseflade størrelse + description: Æ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 - description: >- - Controls how often the game saves automatically. You can also disable it entirely here. - + title: Autogem Interval + description: Æ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 - description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + title: Zoom følsomhed + description: Æ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 - description: >- - Changes how fast the view moves when using the keyboard. + title: Bevægelseshastighed + description: Æ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 - description: >- - Change the language. All translations are user contributed and might be incomplete! - + title: Sprog + description: Ændrer sproget. All oversættelser er lavet af fælleskabet og kan + være ufuldstændige! enableColorBlindHelper: - title: Color Blind Mode - description: >- - Enables various tools which allow to play the game if you are color blind. - + title: Farveblindstilstand + description: Aktiverer forskellige redskaber der lader dig spille, selv hvis du + er farveblind. fullscreen: - title: Fullscreen - description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. - + title: Fuld skærm + description: 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 - description: >- - If enabled, mutes all sound effects. - + title: Slå lydeffekterne fra + description: Aktiver for at slå alle lydeffekter fra. musicMuted: - title: Mute Music - description: >- - If enabled, mutes all music. - + title: Slå musik fra + description: Aktiver for at slå al musik fra. theme: - title: Game theme - description: >- - Choose the game theme (light / dark). + title: Tema + description: Vælg tema (lys / mørk). themes: - dark: Dark - light: Light - + dark: Mørk + light: Lys refreshRate: - title: Simulation Target - 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. - + title: Simulationsmål + description: 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 - description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. - + title: Multiplacér + description: 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 - 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. - + title: Hints & Vejledning + description: 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 - description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. This also enables to drag tunnels and excess tunnels will get removed. - + title: Smarte Tunneller + description: 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. - + description: Aktiverer vignette hvilket mørkner kanterne af skærmen og gør + teksten nemmere at læse. 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. - + title: Rotation baseret på bygningstype + description: 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 - description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. - + title: Kompakt Bygningsinfo + description: 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 - description: >- - Disable the warning dialogs brought up when cutting/deleting more than 100 entities. - + title: Slå klip/slet advarsler fra + description: Slå advarselsboksene, der dukker op når mere end 100 ting slettes, + fra. + soundVolume: + title: Sound Volume + description: Set the volume for sound effects + musicVolume: + title: Music Volume + description: Set the volume for music + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: Keybindings - hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - - resetKeybindings: Reset Keybindings - + hint: "Tip: Husk at bruge CTRL, SKIFT og ALT! De byder på forskellige + placeringsmuligheder." + 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 - - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker - - menuOpenShop: Upgrades - menuOpenStats: Statistics - - 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 - rotater: *rotater - stacker: *stacker - mixer: *mixer - energy_generator: *energy_generator - painter: *painter - trash: *trash - + 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 ind + mapZoomOut: Zoom ud + createMarker: Lav Markør + menuOpenShop: Opgraderinger + menuOpenStats: Statistikker + toggleHud: Slå HUD til/fra + toggleFPSInfo: Slå FPS og Debug Info til/fra + switchLayers: Skift lag + exportScreenshot: Eksporter hele basen som et billede + belt: Transportbælte + underground_belt: Tunnel + miner: Udvinder + cutter: Klipper + rotater: Drejer + stacker: Stabler + mixer: Farveblander + painter: Maler + trash: Skraldespand pipette: Pipette - rotateWhilePlacing: Rotate - rotateInverseModifier: >- - Modifier: Rotate CCW instead - cycleBuildingVariants: Cycle Variants - 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 - menuClose: Close Menu - advanced_processor: Color Inverter - wire: Energy Wire - + rotateWhilePlacing: Roter + rotateInverseModifier: "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: Skift side" + massSelectStart: Hold og træk for at starte + massSelectSelectMultiple: Vælg flere områder + massSelectCopy: Kopier område + massSelectCut: Klip område + placementDisableAutoOrientation: Slå automatisk rotation fra + placeMultiple: Bliv i placeringstilstand + placeInverse: Spejlvend automatisk bælteorientering + menuClose: Luk Menu + wire: Energiledning + balancer: Balancer + storage: Storage + constant_signal: Constant Signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" 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.

- - Finally, huge thanks to my best friend Niklas - Without our factorio sessions this game would never have existed. + Lydsporet er lavet af Peppsen - Han er fantastisk.

+ 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 - - settingNotAvailable: Not available in the demo. + restoringGames: Genopretter gem + importingGames: Importerer gem + oneGameLimit: Afgrænset til et gem + customizeKeybindings: Tilpasser Keybindings + exportingBase: Eksportere hele basen som et billede + settingNotAvailable: Ikke tilgængelig i demoen. +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-de.yaml b/translations/base-de.yaml index 0df29973..e2792e1b 100644 --- a/translations/base-de.yaml +++ b/translations/base-de.yaml @@ -1,111 +1,57 @@ -# -# 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: In shapez.io nutzt du die vorhandenen Ressourcen, um mit deinen Maschinen durch Kombination immer komplexere Formen zu erschaffen. + shortText: In shapez.io nutzt du die vorhandenen Ressourcen, um mit deinen + Maschinen durch Kombination immer komplexere Formen zu erschaffen. + discordLinkShort: Offizieller Discord + intro: >- + Du magst Automatisierungsspiele? Dann bist du hier genau richtig! - # This is the text shown above the discord link - discordLink: Offizieller Discord - Hier kannst du mit mir schreiben! + shapez.io ist ein entspanntes Spiel, in dem du Fabriken zur automatisierten Produktion von geometrischen Formen bauen musst. - # 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] + Mit steigendem Level werden die Formen immer komplexer, und du musst dich auf der unendlich großen Karte ausbreiten. Das ist noch nicht alles, denn du musst exponentiell mehr produzieren, um die Anforderungen zu erfüllen - Da hilft nur skalieren! - 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]! - - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] + Während du am Anfang nur Formen verarbeitest, musst du diese später auch einfärben - Dafür musst du Farben extrahieren und mischen! Der Kauf des Spiels auf Steam gibt dir Zugriff auf die Vollversion, aber du kannst auch zuerst die Demo auf shapez.io spielen und dich später entscheiden! + title_advantages: Vorteile der Vollversion + advantages: + - 12 Neue Level für insgesamt 26 Level + - 18 Neue Gebäude für eine komplett automatisierte Fabrik! + - 20 Upgrade-Stufen für viele Stunden Spielspaß + - Wires-Update für eine komplett neue Dimension! + - Dark-Mode! + - Unbegrenzte Speicherstände + - Unbegrenzte Wegpunkte + - Unterstütze mich! ❤️ + title_future: Geplante Inhalte + planned: + - Blaupausen-Bibliothek + - Errungenschaften auf Steam + - Puzzel-Modus + - Minimap + - Modunterstützung + - Sandkastenmodus + - ... und noch viel mehr! + title_open_source: Dieses Spiel ist quelloffen! + text_open_source: Jeder kann etwas zum Spiel beitragen! Ich engagiere mich aktiv + in der Community und versuche alle Vorschläge zu berücksichtigen. Die + vollständige Roadmap findet ihr auf meinem Trello-Board! + title_links: Links + links: + discord: Offizieller Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Quellcode (GitHub) + translate: Hilf beim Übersetzen global: loading: Laden error: Fehler - - # 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" + thousandsDivider: . decimalSeparator: "," - - # The suffix for large numbers, e.g. 1.3k, 400.2M, etc. suffix: thousands: k millions: M billions: G trillions: T - - # Shown for infinitely big numbers - infinite: unend - + infinite: ∞ time: - # Used for formatting past time dates oneSecondAgo: vor einer Sekunde xSecondsAgo: vor Sekunden oneMinuteAgo: vor einer Minute @@ -114,14 +60,10 @@ global: xHoursAgo: vor Stunden oneDayAgo: vor einem Tag xDaysAgo: vor Tagen - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s hoursAndMinutesShort: h m - xMinutes: Minuten - keys: tab: TAB control: STRG @@ -129,34 +71,26 @@ global: escape: ESC shift: UMSCH space: LEER - demoBanners: - # This is the "advertisement" shown in the main menu and other various places - title: Demo Version - intro: >- - Kauf die Standalone für alle Features! - + title: Demo-Version + intro: Kauf die Vollversion für alle Features! mainMenu: play: Spielen - changelog: Änderungshistorie - importSavegame: Importieren - openSourceHint: Dieses Spiel ist Open Source! - discordLink: Offizieller Discord Server - - # 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! - - savegameLevel: Level - savegameLevelUnknown: Unbekanntes Level - - - helpTranslate: Hilf beim Übersetzen! continue: Fortsetzen newGame: Neues Spiel - madeBy: Ein Spiel von + changelog: Änderungsprotokoll subreddit: Reddit - + importSavegame: Importieren + openSourceHint: Dieses Spiel ist quelloffen! + discordLink: Offizieller Discord Server + helpTranslate: Hilf beim Übersetzen! + madeBy: Ein Spiel von + browserWarning: Sorry, aber das Spiel wird in deinem Browser langsamer laufen! + Kaufe die Vollversion oder verwende Google Chrome für die beste + Erfahrung! + savegameLevel: Level + savegameLevelUnknown: Unbekanntes Level + savegameUnnamed: Unbenannt dialogs: buttons: ok: OK @@ -165,116 +99,111 @@ dialogs: later: Später restart: Neustart reset: Zurücksetzen - getStandalone: Standalone Ansehen + getStandalone: Zur Vollversion deleteGame: Ich weiß, was ich tue viewUpdate: Update anzeigen showUpgrades: Upgrades anzeigen showKeybindings: Kürzel anzeigen - importSavegameError: - title: Importierfehler - text: >- - Fehler beim Importieren deines Spielstands: - + title: Importfehler + text: "Fehler beim Importieren deines Speicherstands:" importSavegameSuccess: - title: Spielstand importieren - text: >- - Dein Spielstand wurde erfolgreich importiert. - + title: Speicherstand importiert + text: Dein Speicherstand wurde erfolgreich importiert. gameLoadFailure: - title: Der Spielstand ist kaputt - text: >- - Der Spielstand konnte nicht geladen werden. - + title: Der Speicherstand ist kaputt + text: Der Speicherstand konnte nicht geladen werden. Sorry! confirmSavegameDelete: title: Löschen bestätigen - text: >- - Bist du sicher, dass du den Spielstand löschen willst? - + text: Bist du sicher, dass du folgenden Speicherstand löschen willst?

+ '' auf Level

Das kann nicht + rückgängig gemacht werden! savegameDeletionError: - title: Löschen gescheitert - text: >- - Das Löschen des Spiels ist gescheitert: - + title: Löschen fehlgeschlagen + text: "Das Löschen des Speicherstands ist fehlgeschlagen:" restartRequired: - title: Neustart benötigt - text: >- - Du muss das Spiel neu starten, um die Einstellungen anzuwenden. - + title: Neustart nötig + text: 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 zum Abbrechen. 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 desc: Die Tastenbelegung wurde auf den Standard zurückgesetzt! - featureRestriction: title: Demo-Version - desc: Du hast ein Feature gefunden (), welches nicht in der Demo enthalten ist. Erwerbe die Standalone für das volle Erlebnis! - + desc: Du hast ein Feature benutzt (), welches nicht in der Demo + enthalten ist. Erwerbe die Vollversion für das volle Erlebnis! oneSavegameLimit: - title: Begrenzte Spielstände - desc: Du kannst in der Demo nur einen Spielstand haben. Bitte lösche den existierenden Spielstand oder hole dir die Standalone! - + title: Begrenzte Speicherstände + desc: Du kannst in der Demo nur einen Speicherstand haben. Bitte lösche den + existierenden oder hole dir die Vollversion! updateSummary: title: Neues Update! - desc: >- - Hier sind die Änderungen, seit dem du das letzte Mal gespielt hast: - + desc: "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. - + title: Upgrades freischalten + desc: Viele deiner Formen können noch benutzt werden, um Upgrades freizuschalten + - Zerstöre deine alten Fabriken nicht! 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? - + desc: Du löscht viele Gebäude ( um genau zu sein)! Bist du dir sicher? + massCutConfirm: + title: Ausschneiden bestätigen + desc: Du schneidest viele Gebäude aus ( um genau zu sein)! Bist du dir + sicher? + massCutInsufficientConfirm: + title: Ausschneiden bestätigen + desc: Du wirst dir das Einfügen nicht leisten können! Bist du sicher, dass du + trotzdem Ausschneiden möchtest? blueprintsNotUnlocked: title: Noch nicht freigeschaltet - desc: >- - Blueprints werden erst in Level 12 freigeschaltet! - + desc: Blaupausen werden erst in Level 12 freigeschaltet! keybindingsIntroduction: title: Nützliche Hotkeys desc: >- - Dieses Spiel hat viele Hotkeys, die den Bau von Fabriken vereinfachen und beschleunigen. - Hier sind ein paar, aber prüfe am besten die Tastenbelegung-Einstellungen!

- STRG + Ziehen: Wähle Areal aus.
+ Dieses Spiel hat viele Hotkeys, die den Bau von Fabriken + vereinfachen und beschleunigen. Hier sind ein paar Beispiele, aber + prüfe am besten die + Tastenbelegung-Einstellungen!

+ STRG + Ziehen: Wähle Bereich aus.
UMSCH: Halten, um mehrere Gebäude zu platzieren.
- ALT: Invertiere die Platzierungsrichtung der Förderbänder.
- + ALT: Invertiere die Platzierungsrichtung der Fließbänder.
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 + desc: Gib ihm einen griffigen Namen. Du kannst auch den + Kurz-Code einer Form eingeben (Welchen du + hier generieren kannst). + editSignal: + title: Signal setzen + descItems: "Wähle ein vordefiniertes Item:" + descShortKey: ... oder gib den Kurz-Code einer Form an (Welchen + du hier generieren kannst). 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. Hole dir die Vollversion, 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! + renameSavegame: + title: Speicherstand umbenennen + desc: Hier kannst du deinen Speicherstand umbenennen. + tutorialVideoAvailable: + title: Tutorial verfügbar + desc: Für dieses Level ist ein Tutorial-Video verfügbar. Willst du es anschauen? + tutorialVideoAvailableForeignLanguage: + title: Tutorial verfügbar + desc: Für dieses Level ist ein Tutorial-Video verfügbar, allerdings nur auf + Englisch. Willst du es trotzdem anschauen? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Bewegen selectBuildings: Areal markieren @@ -294,19 +223,20 @@ ingame: copySelection: Kopieren clearSelection: Auswahl aufheben pipette: Pipette - switchLayers: Switch layers - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + switchLayers: Ebenen wechseln + colors: + red: Rot + green: Grün + blue: Blau + yellow: Gelb + purple: Magenta + cyan: Cyan + white: Weiß + black: Schwarz + uncolored: Grau 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: Wechsle Variante - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Taste: - + cycleBuildingVariants: Drücke zum Wechseln + hotkeyLabel: "Taste: " infoTexts: speed: Geschw. range: Reichweite @@ -314,112 +244,137 @@ ingame: oneItemPerSecond: 1 Item / s itemsPerSecond: Items / s itemsPerSecondDouble: (x2) - tiles: Felder - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Level completed: Abgeschlossen unlockText: freigeschaltet! buttonNextLevel: Nächstes Level - - # Notifications on the lower right notifications: newUpgrade: Ein neues Upgrade ist verfügbar! gameSaved: Dein Spiel wurde gespeichert. - - # The "Upgrades" window + freeplayLevelComplete: Level abgeschlossen! shop: title: Upgrades buttonUnlock: Upgrade - - # Gets replaced to e.g. "Tier IX" tier: Stufe - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXIMALE STUFE (Geschw. x) - - # The "Statistics" window statistics: title: Statistiken dataSources: stored: title: Gelagert - description: Zeigt die Menge an Formen, die im zentralen Gebäude gelagert sind. + description: Alle im Hub gelagerten Formen. produced: title: Produziert - description: Zeigt die Menge an Formen, die deine gesamte Fabrik produziert (inkl. Zwischenprodukte). + description: Alle in deiner Fabrik hergestellten Formen inkl. Zwischenprodukte. delivered: - title: Abgeliefert - description: Zeigt die Menge an Formen, die im zentralen Gebäude abgeliefert werden. - noShapesProduced: Bisher wurden keine Formen produziert. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + title: Geliefert + description: An den Hub gelieferte Formen. + noShapesProduced: Es werden noch keine Formen produziert oder geliefert. + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Spielzeit - buildingsPlaced: Gebäude - beltsPlaced: Förderbänder - - buttons: - continue: Weiter - settings: Einstellungen - menu: Zurück zum Menü - - # Bottom left tutorial hints + beltsPlaced: Fließbänder tutorialHints: title: Brauchst du Hilfe? showHint: Hinweis hideHint: Schließen - - # When placing a blueprint blueprintPlacer: cost: Kosten - - # 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. + waypoints: Marker + 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. - - # Interactive tutorial - interactiveTutorial: - title: Tutorial - hints: - 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! - - 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 - -# All shop upgrades + copyKey: Schlüssel kopieren + interactiveTutorial: + title: Einführung + hints: + 1_1_extractor: Platziere einen Extrahierer auf der + Kreisform, um sie zu extrahieren! + 1_2_conveyor: "Verbinde den Extrahierer mit einem Fließband und + schließe ihn am Hub an!

Tipp: Drücke und + ziehe das Fließband mit der Maus!" + 1_3_expand: "Dies ist KEIN Idle-Game! Baue mehr Extrahierer und + Fließbänder, um das Ziel schneller zu erreichen.

Tipp: + Halte UMSCH, um mehrere Gebäude zu platzieren + und nutze R, um sie zu rotieren." + 2_1_place_cutter: "Platziere nun einen Schneider um die Kreise + in zwei Hälften zu zerteilen.

Übrigens: Der Schneider + schneidet immer von oben nach unten, unabhängig + seiner Orientierung!" + 2_2_place_trash: Der Schneider kann verstopfen!

Benutze + einen Mülleimer um den aktuell (!) nicht + benötigten Rest loszuwerden. + 2_3_more_cutters: "Gut gemacht! Platziere noch 2 mehr Schneider + um das ganze zu beschleunigen.

Übrigens: Benutze die + Tasten 0-9 um Gebäude schneller auszuwählen!" + 3_1_rectangles: "Lass uns ein paar Quadrate extrahieren! Baue 4 + Extrahierer und verbinde sie mit deinem HUB.

+ PS: Halte SHIFT während du ein Fließband + ziehst, um den Fließbandplaner zu aktivieren!" + 21_1_place_quad_painter: Platzier den Vierfach-Färber und + organisier ein paar Kreise, + weiße und rote Farbe! + 21_2_switch_to_wires: Wechsle in die Wires-Ebene indem du E + drückst!

Verbinde danach alle vier + Eingänge mit Signalkabeln! + 21_3_place_button: Perfekt! Platziere jetzt einen Schalter und + verbinde ihn mit Signalkabeln. + 21_4_press_button: "Drücke den Schalter damit er ein wahres + Signal ausgibt, und damit den Färber aktiviert.

+ PS: Du musst nicht alle Eingänge verbinden! Probiere mal nur 2 + aus." + connectedMiners: + one_miner: Ein Extrahierer + n_miners: Extrahierer + limited_items: Begrenzt auf + watermark: + title: Demo-Version + desc: Klicke hier, um die Vorteile der Vollversion zu sehen! + get_on_steam: Zur Vollversion + standaloneAdvantages: + title: Vorteile der Vollversion + no_thanks: Nein, danke! + points: + levels: + title: 12 Neue Level + desc: Für insgesamt 26 Level! + buildings: + title: 18 Neue Gebäude + desc: Automatisiere deine Fabrik! + savegames: + title: ∞ Speicherstände + desc: So viele dein Herz begehrt! + upgrades: + title: 20 Upgrade-Stufen + desc: Diese Demo hat nur 5! + markers: + title: ∞ Marker + desc: Verliere nie den Überblick! + wires: + title: Wires-Ebene + desc: Eine ganz neue Dimension! + darkmode: + title: Dark-Mode + desc: Werde nicht mehr geblendet! + support: + title: Unterstütze Mich + desc: Ich entwickle in meiner Freizeit! shopUpgrades: belt: - name: Förderbänder, Verteiler & Tunnel + name: Fließbänder, Verteiler & Tunnel description: Geschw. x → x miner: name: Extrahierer @@ -430,311 +385,413 @@ shopUpgrades: painting: name: Mischer & Färber description: Geschw. x → x - -# Buildings and their name / description buildings: - belt: - default: - name: &belt Förderband - description: Transportiert Items. Halte und ziehe um mehrere zu platzieren. - - miner: # Internal name for the Extractor - default: - name: &miner Extrahierer - 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. - - underground_belt: # Internal name for the Tunnel - default: - name: &underground_belt Tunnel - description: Erlaubt dir, Formen und Farbe unter Gebäuden und Förderbändern durchzuleiten. - - tier2: - 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 - default: - name: &splitter Verteiler - description: Multifunktional - Verteilt gleichmäßig vom Eingang auf den Ausgang. - - compact: - name: Kombinierer (Kompakt) - description: Vereint zwei Förderbänder zu einem. - - compact-inverse: - name: Kombinierer (Kompakt) - description: Vereint zwei Förderbänder zu einem. - - cutter: - default: - name: &cutter Schneider - description: Zerschneidet Formen von oben nach unten. Benutze oder zerstöre beide Hälften, sonst verstopft die Maschine! - quad: - name: Schneider (4-fach) - description: Zerschneidet Formen in vier Teile. Benutze oder zerstöre alle Viertel, sonst verstopft die Maschine! - - rotater: - default: - name: &rotater Rotierer - description: Rotiert Formen im Uhrzeigersinn um 90 Grad. - - ccw: - name: Rotierer (CCW) - description: Rotiert Formen gegen den Uhrzeigersinn um 90 Grad. - - stacker: - default: - name: &stacker Stapler - description: Stapelt beide Formen. Wenn beide nicht vereint werden können, wird die rechte Form auf die linke Form gestapelt. - - mixer: - default: - name: &mixer Farbmischer - description: Mischt zwei Farben auf Basis der additiven Farbmischung. - - painter: - default: - 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 - - trash: - default: - name: &trash Mülleimer - description: Akzeptiert Formen und Farben aus jeder Richtung und zerstört sie. Für immer ... - - storage: - name: Lager - description: Lagert den Überschuss bis zu einer gegebenen Kapazität. Kann als Überlauftor agieren. - hub: deliver: Liefere - toUnlock: >- - Für folgende Belohnung: + toUnlock: "und schalte frei:" levelShortcut: LVL + endOfDemo: Ende der Demo + belt: + default: + name: Fließband + description: Transportiert Items. Halte und ziehe, um mehrere zu platzieren. + miner: + default: + name: Extrahierer + 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. + underground_belt: + default: + name: Tunnel + description: Erlaubt dir, Formen und Farbe unter Gebäuden und Fließbändern + durchzuleiten. + tier2: + name: Tunnel Stufe II + description: Erlaubt dir, Formen und Farbe unter Gebäuden und Fließbändern + durchzuleiten. Höhere Reichweite. + balancer: + default: + name: Verteiler + description: Multifunktional - Verteilt alle Eingänge gleichmäßig auf die + Ausgänge. + merger: + name: Kombinierer (kompakt) + description: Kombiniert zwei Eingänge gleichmäßig zu einem Ausgang. + merger-inverse: + name: Kombinierer (kompakt) + description: Kombiniert zwei Eingänge gleichmäßig zu einem Ausgang. + splitter: + name: Aufteiler (kompakt) + description: Teilt einen Eingang gleichmäßig in zwei Ausgänge auf. + splitter-inverse: + name: Aufteiler (kompakt) + description: Teilt einen Eingang gleichmäßig in zwei Ausgänge auf. + cutter: + default: + name: Schneider + description: Zerschneidet Formen von oben nach unten. Benutze oder + zerstöre beide Hälften, sonst verstopft die Maschine! + quad: + name: Schneider (vierfach) + description: Zerschneidet Formen in vier Teile. Benutze oder zerstöre + alle Viertel, sonst verstopft die Maschine! + rotater: + default: + name: Rotierer (90°) + description: Rotiert Formen im Uhrzeigersinn um 90 Grad. + ccw: + name: Rotierer (-90°) + description: Rotiert Formen gegen den Uhrzeigersinn um 90 Grad. + rotate180: + name: Rotierer (180°) + description: Rotiert formen um 180 Grad. + stacker: + default: + name: Stapler + description: Stapelt beide Formen. Wenn beide nicht vereint werden können, wird + die rechte Form auf die linke Form gestapelt. + mixer: + default: + name: Farbmischer + description: Mischt zwei Farben auf Basis der additiven Farbmischung. + painter: + default: + name: Färber + description: Färbt die ganze Form aus dem linken Eingang mit der Farbe aus dem + oberen Eingang. + mirrored: + name: Färber + description: Färbt die ganze Form aus dem linken Eingang mit der Farbe aus dem + oberen Eingang. + double: + name: Färber (zweifach) + description: Färbt beide Formen aus dem linken Eingang mit der Farbe aus dem + oberen Eingang. + quad: + name: Färber (vierfach) + description: Erlaubt dir, jeden Quadranten der Form individuell zu färben. Nur + Quadranten mit einem wahren Signal (Form, Farbe + oder "1") auf der Wires-Ebene werden angemalt! + trash: + default: + name: Mülleimer + description: Akzeptiert Formen und Farben aus jeder Richtung und zerstört sie. + Für immer ... + storage: + default: + name: Speicher + description: Speichert überschüssige Gegenstände, bis zu einer bestimmten + Kapazität. Priorisiert den linken Ausgang und kann als + Überlauftor verwendet werden. wire: default: - name: Energy Wire - description: Allows you to transport energy. - advanced_processor: + name: Signalkabel + description: Erlaubt den Transport von Signalen. Das sind Items, Farben oder + Wahrheitswerte (1 oder 0). Unterschiedlich gefärbte Kabel + verbinden sich nicht. + second: + name: Signalkabel + description: Erlaubt den Transport von Signalen. Das sind Items, Farben oder + Wahrheitswerte (1 oder 0). Unterschiedlich gefärbte Kabel + verbinden sich nicht. + wire_tunnel: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For + name: Kabelkreuzung + description: Erschafft eine isolierte Kreuzung zweier Kabel. + constant_signal: default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: + name: Signalgeber + description: Sendet ein konstantes Signal. Du wählst zwischen Formen, Farben und + Wahrheitswerten (1 oder 0). + lever: default: - name: Wire Splitter - description: Splits a energy wire into two. - merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Schalter + description: Sendet einen Wahrheitswert (1 oder 0) auf der Wires-Ebene abhängig + von seiner Stellung, welcher dann z.B. zur Steuerung eines + Filters verwendet werden kann. + logic_gate: + default: + name: UND-Gatter + description: Gibt eine "1" aus, wenn beide Eingänge wahr (Form, Farbe oder "1") + sind. + not: + name: NICHT-Gatter + description: Gibt eine "1" aus, wenn beide Eingänge nicht wahr (kein Signal oder + "0") sind. + xor: + name: XODER-Gatter + description: Gibt eine "1" aus, wenn genau einer der Eingänge wahr (Form, Farbe + oder "1") ist. + or: + name: ODER-Gatter + description: Gibt eine "1" aus, wenn mindestens einer der Eingänge wahr (Form, + Farbe oder "1") ist. + transistor: + default: + name: Transistor + description: Lässt den unteren Eingang passieren, wenn der seitliche Eingang + wahr (Form, Farbe oder "1") ist. + mirrored: + name: Transistor + description: Lässt den unteren Eingang passieren, wenn der seitliche Eingang + wahr (Form, Farbe oder "1") ist. + filter: + default: + name: Itemfilter + description: Lässt nur die Items durch, die dem eingespeisten Signal entsprechen + und sortiert die restlichen aus. Mit Wahrheitswerten + konfiguriert fungiert er als Schranke. + display: + default: + name: Anzeige + description: Verbinde ein Signal, um es auf der Anzeige darzustellen. Es kann + eine Form, Farbe oder ein Wahrheitswert sein. + reader: + default: + name: Fließbandkontrolle + description: Misst den gemittelten Durchsatz des Fließbandes. Gibt zuätzlich den + zuletzt passierten Gegenstand auf der Wires-Ebene aus (sobald + freigeschaltet). + analyzer: + default: + name: Formanalyse + description: Analysiert den oberen rechten Quadranten der untersten Schicht + einer Form und gibt sowohl Form als auch Farbe aus. + comparator: + default: + name: Vergleich + description: Gibt eine "1" zurück, wenn beide Signale genau gleich sind. Kann + Formen, Farben und Wahrheitswerte vergleichen. + virtual_processor: + default: + name: Virtueller Schneider + description: Schneidet die Form virtuell in zwei Hälften. + rotater: + name: Virtueller Rotierer + description: Dreht die Form virtuell im Uhrzeigersinn. + unstacker: + name: Virtueller Entstapler + description: Extrahiert virtuell die oberste Ebene nach rechts und die + restlichen Ebenen nach links. + stacker: + name: Virtueller Stapler + description: Stapelt virtuell die rechte Form auf die linke. + painter: + name: Virtueller Färber + description: Färbt virtuell die Form vom unteren Eingang mit der Farbe aus dem + rechten Eingang. + item_producer: + default: + name: Item-Produzent + description: Nur im Sandkastenmodus verfügbar. Gibt das Signal aus der + Wires-Ebene als Item aus. 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 gerade den Schneider freigeschaltet, der Formen + in zwei Hälften schneidet, von oben nach unten, unabhängig der + Orientierung!

Achte darauf, den Abfall loszuwerden, oder + er wird verstopfen und blockieren - Zu diesem Zweck habe ich + dir den Mülleimer gegeben, der alles entsorgt, was + du hineintust! 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! - + desc: "Der Färber wurde freigeschaltet! Extrahiere ein paar + Farben (genauso wie bei Formen) und lasse damit eine Form im Färber + bemalen.

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! - - reward_splitter: - title: Verteiler/Kombinierer - desc: Der multifunktionale Verteiler wurde freigeschaltet! Er ermöglicht die Konstruktion größerer Fabriken, indem er Items auf mehrere Förderbänder verteilt oder diese zusammenführt!

- + 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_balancer: + title: Verteiler + desc: Der multifunktionale Verteiler wurde freigeschaltet! Er + kann benutzt werden, um größere Fabriken zu bauen, indem Fließbänder + aufgeteilt oder zusammengelegt werden! 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 Fließbä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) - desc: Du hast den Extrahierer (Kette) freigeschaltet! Damit können die Ressourcen an den Nächsten weitergegeben werden, um Ressourcen effizienter zu extrahieren. - + desc: "Du hast den Kettenextrahierer freigeschaltet! Er kann + seine Ressourcen an andere Extrahierer + weiterleiten.

PS: Der alte Extrahierer + wurde jetzt in deiner Symbolleiste ersetzt!" 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! - - reward_splitter_compact: + desc: Du hast eine neue Variante des Tunnels freigeschaltet! + Dieser hat eine höhere Reichweite und du kannst + beide Tunnel miteinander mischen. + reward_merger: 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! - + desc: Du hast eine kompakte Variante des + Verteilers freigeschaltet! Der Kombinierer vereint + zwei Eingänge zu einem Ausgang. + reward_splitter: + title: Kompakter Aufteiler + desc: Du hast eine kompakte Variante des + Verteilers freigeschaltet! Der Aufteiler spaltet + einen Eingang in zwei Aufgänge auf. + reward_belt_reader: + title: Fließbandkontrolle + desc: Du hast nun die Fließbandkontrolle freigeschaltet! Damit + kannst du dir den Durchsatz eines Fließbandes anzeigen + lassen.

Wenn du Stromkabel freischaltest, wird er um eine + sehr nützliche Funktion ergänzt! 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! - + title: Schneider (vierfach) + 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! - - 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! - + title: Färber (zweifach) + 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_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! - - reward_freeplay: - title: Freies Spiel - 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: Lager + desc: Du hast das Lager freigeschaltet! Es erlaubt dir, + Gegenstände bis zu einer bestimmten Kapazität zu speichern!

+ Es priorisiert den linken Ausgang, also kannst du es auch als + Überlauftor benutzen! reward_blueprints: - title: Blaupause - desc: Jetzt kannst du Teile deiner Fabrik kopieren und einfügen! Wähle ein Areal aus (Halte STRG und ziehe mit deiner Maus) und drücke 'C', um zu kopieren.

Einfügen ist nicht kostenlos, du musst Blaupausenformen produzieren, um die Kopierkosten zu decken (Welche du gerade produziert hast)! - - # Special reward, which is shown when there is no reward actually + title: Blaupausen + desc: Jetzt kannst du Teile deiner Fabrik kopieren und + einfügen! Wähle einen Bereich aus (Halte STRG und ziehe mit + deiner Maus) und drücke 'C', um zu kopieren.

Einfügen ist + nicht kostenlos! Du musst + Blaupausenformen produzieren, um die Kopierkosten + zu decken (Welche du gerade produziert hast). + reward_rotater_180: + title: Rotierer (180°) + desc: Du hast eine weitere Variante des Rotierers + freigeschaltet! Mit ihm kannst du Formen um 180° drehen + (Überraschung! :D). + reward_wires_painter_and_levers: + title: Wires-Ebene & vierfacher Färber + desc: "Du hast soeben die Wires-Ebene freigeschaltet! Diese + separate Ebene befindet sich unter deinen Gebäuden und gibt dir + viele neue Möglichkeiten.

Für den Anfang bekommst du einen + vierfachen Färber. Schließe die Eingänge, mit denen + du die Quadranten färben möchtest, an ein Signalkabel auf der + Wires-Ebene an!

Mit E wechselst du zwischen + den Ebenen.

PS: Aktiviere Hinweise in den + Einstellungen um das Tutorial anzuzeigen!" + reward_filter: + title: Itemfilter + desc: Du hast den Itemfilter freigeschaltet! Items, die dem + eingespeisten Signal entsprechen, lässt er passieren. Den Rest + zweigt er nach rechts ab.

Du kannst z.B. nach Farbe und Form + sortieren oder mit Wahrheitswerten (1 oder 0) Items nur auf + Knopfdruck passieren lassen. + reward_display: + title: Anzeige + desc: Du hast die Anzeige freigeschaltet! Jedes eingespeiste + Signal kann damit dargestellt werden.

Apropos, ist dir schon + aufgefallen, dass Fließbandkontrolle und Lager das zuletzt passierte + Item ausgeben können? Lasse es dir doch gleich mal anzeigen! + reward_constant_signal: + title: Signalgeber + desc: Du hast den Signalgeber freigeschaltet! Du kannst das + Gebäude auf der Wires-Ebene platzieren und z.B. mit einem + Itemfilter verbinden.

Der Signalgeber kann + dir Formen, Farben oder + Wahrheitswerte (1 oder 0) zur Verfügung stellen. + reward_logic_gates: + title: Logikgatter + desc: Du hast nun eine Reihe an Logikgattern freigeschaltet! + Das muss dich jetzt nicht nervös machen, die Funktionsweise ist + simpel und ziemlich cool.

Mit Logikgattern kannst du UND-, + ODER-, XODER- und NICHT-Operationen ausführen.

Als + Sahnehäubchen obendrauf stelle ich dir noch einen + Transistor zur Verfügung. Houston, wir sind + Turing-vollständig! + reward_virtual_processing: + title: Virtuelle Verarbeitung + desc: "Du hast gerade eine Menge neue Gebäude freigeschaltet! Mit ihnen kannst + du die Verarbeitung von Formen komplett + simulieren.

Das beinhaltet einen Schneider, + Rotierer, Stapler und mehr für die Wires-Ebene! Damit bleiben dir ab + jetzt drei Optionen offen:

- Ich empfehle dir, eine + automatisierte Maschine zu bauen, die jede + beliebige Form am Hub abgreift und herstellt. (Probiere es + wenigstens!)

- Werde kreativ und lasse dir etwas Cooles + einfallen, das du auf der Wires-Ebene umsetzen kannst. (Und teile es + auf dem Discord!)

- Spiele dich weiter durch die Level. Auf + deine Art!

Das Wichstigste an deiner Entscheidung ist: + Vergiss nicht, dabei Spaß zu haben!" 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! - + desc: "Dieses Level hat dir keine Belohnung gegeben, aber im Nächsten gibt es + eine!

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 - desc: >- - Herzlichen Glückwunsch! Apropos, in der Standalone-Version ist noch vieles mehr geplant! - + desc: Du hast das nächste Level freigeschaltet! + reward_freeplay: + title: Freies Spiel + desc: Du hast es geschafft! Du bist im Freispiel-Modus + angekommen! Das bedeutet, dass die abzuliefernden Formen jetzt + zufällig erzeugt werden!

Da der Hub ab + jetzt einen bestimmten Durchsatz benötigt, empfehle + ich dringend, eine Maschine zu bauen, die automatisch die gewünschte + Form liefert!

Der Hub gibt die gewünschte Form auf der + Wires-Ebene aus. Also musst du sie nur analysieren und basierend + darauf automatisch deine Fabrik konfigurieren. + reward_demo_end: + title: Ende der Demo + desc: Du bist am Ende der Demo angekommen! settings: title: Einstellungen categories: - game: Spiel - app: Applikation - + general: Allgemein + userInterface: Benutzeroberfläche + advanced: Erweitert + performance: Leistung versionBadges: dev: Entwicklung staging: Beta prod: Produktion buildDate: Gebaut am - + rangeSliderPercentage: % labels: uiScale: title: HUD Größe - description: >- - Ändert die Größe der Benutzeroberfläche, basierend auf der Bildschirmauflösung. + description: Ändert die Größe der Benutzeroberfläche, basierend auf der + Bildschirmauflösung. scales: super_small: Sehr klein small: Klein regular: Normal large: Groß huge: Riesig - - scrollWheelSensitivity: - title: Zoomempfindlichkeit - description: >- - Ändert die Sensitivität des Zooms (Sowohl Mausrad, als auch Trackpad). - sensitivity: - super_slow: Sehr langsam - slow: Langsam - regular: Normal - fast: Schnell - super_fast: Sehr schnell - - fullscreen: - title: Vollbild - description: >- - Für das beste Erlebnis im Spiel wird der Vollbildmodus empfohlen (Nur in der Standalone-Version verfügbar). - - soundsMuted: - title: Geräusche stummschalten - description: >- - Bei Aktivierung werden alle Geräusche stummgeschaltet. - - musicMuted: - title: Musik stummschalten - description: >- - Bei Aktivierung wird die Musik stummgeschaltet. - - theme: - title: Farbmodus - description: >- - Wähle zwischen dunklem und hellem Farbmodus. - - themes: - dark: Dunkel - light: Hell - refreshRate: - title: Zielbildwiederholrate - 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. - - 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. - - 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. - 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. + 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 @@ -742,44 +799,157 @@ settings: ten_minutes: 10 Minuten twenty_minutes: 20 Minuten disabled: Deaktiviert - - compactBuildingInfo: - title: Kompakte Gebäudeinformationen - description: >- - 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. - + scrollWheelSensitivity: + title: Zoomempfindlichkeit + description: Ändert die Empfindlichkeit des Zooms (Sowohl Mausrad, als auch + Trackpad). + sensitivity: + super_slow: Sehr langsam + slow: Langsam + regular: Normal + fast: Schnell + super_fast: Sehr schnell + movementSpeed: + title: Bewegungsgeschwindigkeit + description: Ändert die Geschwindigkeit, mit welcher 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. + description: Aktiviert verschiedene Werkzeuge, welche dir das Spielen trotz + Farbenblindheit ermöglichen. + fullscreen: + title: Vollbild + description: Für das beste Erlebnis im Spiel wird der Vollbildmodus empfohlen + (Nur in der Standalone-Version verfügbar). + soundsMuted: + title: Geräusche stummschalten + description: Bei Aktivierung werden alle Geräusche stummgeschaltet. + musicMuted: + title: Musik stummschalten + 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 dem dunklen und dem hellen Farbmodus. + themes: + dark: Dunkel + light: Hell + refreshRate: + title: Tickrate + description: 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 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. + enableTunnelSmartplace: + title: Intelligente Tunnel + description: Aktiviert das automatische Entfernen von überflüssigen Fließbä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. 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. - + description: Jeder Gebäudetyp merkt sich eigenständig, 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. + disableCutDeleteWarnings: + title: Deaktiviere Warnungsdialog beim Löschen + description: Deaktiviert die Warnung, welche beim Löschen und Ausschneiden von + mehr als 100 Feldern angezeigt wird. + lowQualityMapResources: + title: Minimalistische Ressourcen + description: Vereinfacht die Darstellung der Ressourcen auf der hereingezoomten + Karte zur Verbesserung der Leistung. Die Darstellung ist + übersichtlicher, also probiere es ruhig aus! + disableTileGrid: + title: Gitter deaktivieren + description: Das Deaktivieren des Gitters kann deine Leistung verbessern. + Außerdem vereinfacht es die Darstellung! + clearCursorOnDeleteWhilePlacing: + title: Abwählen mit Rechtsklick + description: Standardmäßig eingeschaltet, wählt es das aktuelle, zur Platzierung + ausgewählte Gebäude ab, wenn du die rechte Masutaste drückst. + Wenn du es abschaltest, kannst du mit der rechten Maustaste + Gebäude löschen, während du im Platzierungsmodus bist. + lowQualityTextures: + title: Niedrige Texturqualität (Unschön) + description: Das Spiel verwendet eine niedrigere Auflösung bei den Texturen. + Allerdings leidet die Grafik des Spiels sehr darunter! + displayChunkBorders: + title: Chunk-Ränder anzeigen + description: Das Spiel ist in Blöcke (Chunks) aus je 16x16 Feldern aufgeteilt. + Diese Einstellung lässt dich die Grenzen zwischen den Chunks + anzeigen. + pickMinerOnPatch: + title: Automatisch Extrahierer auswählen + description: Standardmäßig eingeschaltet, wählst du automatisch den Extrahierer, + wenn du mit der Pipette auf einen Ressourcenfleck zeigst + simplifiedBelts: + title: Minimalistische Fließbänder (Unschön) + description: Zur Verbesserung der Leistung werden die Items auf Fließbändern nur + angezeigt, wenn du deine Maus darüber bewegst. Hier leidet + sowohl die Grafik, also auch dein Spielerlebnis. Benutze die + Funktion nur, wenn du auf die Leistung wirklich angewiesen bist! + enableMousePan: + title: Scrollen am Bildschirmrand + description: Damit kannst du dich über die Karte bewegen, indem du deinen + Mauszeiger am Bildschirmrand platzierst. Die Geschwindigkeit + stimmt dabei mit den Tasten überein. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). keybindings: title: Tastenbelegung - hint: >- - Tipp: Benutze STRG, UMSCH and ALT! Sie aktivieren verschiedene Platzierungsoptionen. - - resetKeybindings: Tastenbelegung zurücksetzen. - + hint: "Tipp: Benutze STRG, UMSCH and ALT! Sie aktivieren verschiedene + Platzierungsoptionen." + resetKeybindings: Tastenbelegung zurücksetzen categoryLabels: - general: Applikation + general: Anwendung ingame: Spiel navigation: Navigation placement: Platzierung massSelect: Bereichsauswahl buildings: Gebäude placementModifiers: Platzierungsmodifikatoren - mappings: confirm: Bestätigen back: Zurück @@ -787,78 +957,76 @@ keybindings: mapMoveRight: Nach rechts bewegen mapMoveDown: Nach unten bewegen mapMoveLeft: Nach links bewegen + mapMoveFaster: Schneller bewegen centerMap: Karte zentrieren - - mapZoomIn: Hineinzoomen - mapZoomOut: Herauszoomen - createMarker: Markierung erstellen - + mapZoomIn: Reinzoomen + mapZoomOut: Rauszoomen + createMarker: Marker erstellen menuOpenShop: Upgrades menuOpenStats: Statistiken - + menuClose: Menü schließen toggleHud: HUD an/aus toggleFPSInfo: FPS und Debug-Info an/aus - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + switchLayers: Ebenen wechseln + exportScreenshot: Ganze Fabrik als Foto exportieren + belt: Fließband + balancer: Verteiler + underground_belt: Tunnel + miner: Extrahierer + cutter: Schneider + rotater: Rotierer (90°) + stacker: Stapler + mixer: Farbmischer + painter: Färber + trash: Mülleimer + storage: Lager + wire: Stromkabel + constant_signal: Signalgeber + logic_gate: Logikgatter + lever: Schalter (regulär) + filter: Filter + wire_tunnel: Kabelkreuzung + display: Anzeige + reader: Fließbandkontrolle + virtual_processor: Virtueller Schneider + transistor: Transistor + analyzer: Formanalyse + comparator: Vergleich + item_producer: Item-Produzent (Sandkastenmodus) + pipette: Pipette rotateWhilePlacing: Rotieren - rotateInverseModifier: >- - Modifikator: stattdessen gegen den UZS rotieren - cycleBuildingVariants: Variante wählen - confirmMassDelete: Massenlöschung bestätigen - cycleBuildings: Gebäude rotieren - + rotateInverseModifier: "Modifikator: stattdessen gegen den UZS rotieren" + cycleBuildingVariants: Nächste Variante auswählen + confirmMassDelete: Löschen bestätigen + pasteLastBlueprint: Letzte Blaupause einfügen + cycleBuildings: Nächstes Gebäude auswählen + lockBeltDirection: Bandplaner aktivieren + switchDirectionLockSide: "Bandplaner: Seite wechseln" + copyWireValue: "Kabel: Wert unter Mauszeiger kopieren" 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 - + placeInverse: Automatische Fließbandorientierung invertieren about: title: Über dieses Spiel - body: >- - Dieses Spiel hat einen offenen Quellcode (Open Source) und wurde von Tobias Springer (das bin ich!) entwickelt.

- - Wenn du etwas zum Spiel beitragen möchtest, dann schaue dir shapez.io auf GitHub an.

- - Das Spiel wurde erst durch die großartige Discord-Community - um meine Spiele möglich gemacht. Komm doch einfach mal auf dem Discord-Server vorbei!

- - 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. - + body: Dieses Spiel ist quelloffen (Open Source) und wurde von Tobias Springer + (das bin ich!) entwickelt.

Wenn du etwas zum Spiel beitragen + möchtest, dann schaue dir shapez.io auf GitHub an.

Das Spiel wurde + erst durch die großartige Discord-Community um meine Spiele möglich + gemacht. Komm doch einfach mal auf dem Discord-Server vorbei!

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. changelog: title: Änderungen - demo: features: restoringGames: Spiele wiederherstellen @@ -866,5 +1034,82 @@ demo: oneGameLimit: Beschränkt auf einen Spielstand customizeKeybindings: Tastenbelegung anpassen exportingBase: Ganze Fabrik als Foto exportieren - settingNotAvailable: Nicht verfügbar in der Demo. +tips: + - Der Hub akzeptiert alle Formen, nicht nur die aktuell geforderten! + - Stelle sicher, dass deine Fabriken modular sind. Es zahlt sich irgendwann + aus! + - Baue nicht zu nah am Hub, sonst entsteht ein riesiges Chaos! + - Wenn der Stapler nicht die richtige Form ausspuckt, wechsle doch mal die + Eingänge. + - Du kannst mit R die Richtung des Bandplaners umkehren. + - Halte STRG, um die Fließbänder ohne automatische Orientierung zu + platzieren. + - Die Verhältnisse der Maschinen bleiben gleich, wenn du die Upgrades + gleichmäßig kaufst. + - Serielle Ausführung ist effizienter als parallele. + - Für viele Gebäude wirst du im Spielverlauf neue Varianten freischalten! + - Du kanst T drücken, um auf andere Varianten des Gebäudes zu + wechseln. + - Symmetrie ist der Schlüssel! + - Du kannst verschiedene Arten von Tunneln miteinander verweben. + - Versuche kompakte Fabriken zu bauen. Es zahlt sich aus! + - Der Färber hat eine spiegelverkehrte Variante, die du mit T + auswählen kannst. + - Das richtige Verhältnis der Gebäude maximiert die Effizienz. + - Auf der gleichen Upgrade-Stufe genügen 5 Extrahierer für ein ganzes + Fließband. + - Vergiss die Tunnel nicht! + - Für maximale Effizienz musst du die Items nicht gleichmässig aufteilen. + - Das Halten von UMSCH aktiviert den Bandplaner, der lange + Fließbänder ganz einfach platziert. + - Schneider teilen die Form immer vertikal, unabhängig von der Orientierung. + - Weiß erhälst du aus der Kombination aller 3 Grundfarben. + - Das Lager gibt Items immer zuerst am linken Ausgang ab. + - Es lohnt sich, Zeit in den Bau von wiederverwendbaren Designs zu stecken! + - Das Halten von STRG ermöglicht dir, mehrere Gebäude zu platzieren. + - Du kanst ALT gedrückt halten, um die Richtung der Fließbänder + umzukehren. + - Effizienz ist entscheidend! + - Abbaubare Formen werden komplexer, je weiter sie vom Hub entfernt sind. + - Gebäude haben eine limitierte Geschwindigkeit. Teile die Last zwischen + mehreren auf. + - Benutze Aufteiler, um deine Effizienz zu maximieren. + - Organisation ist wichtig! Verheddere dich nicht in einem Gewirr aus + Fließbändern. + - Plane vorher und lasse dir Platz für Reserven, oder es gibt ein riesiges + Chaos! + - Lösche deine alten Fabriken nicht! Du benötigst sie um Upgrades + freizuschalten. + - Versuche Level 20 alleine zu meistern, bevor du nach Hilfe suchst! + - Mache es dir nicht zu kompliziert! Auch mit einfachen Konzepten kommst du + hier sehr weit. + - Manche Fabriken musst du später wiederverwenden. Also baue sie so, damit + du genau das kannst. + - Manchmal kannst du die gewünschte Form auf der Karte finden, ohne sie + herstellen zu müssen. + - Vollständige Windmühlen werden nicht natürlich generiert. + - Färbe deine Formen vor dem Schneiden! Das geht viel schneller. + - Mit Modulen wird Platz nur noch zum Begriff; eine Sorge für Sterbliche. + - Stelle deinen Nachschub an Blaupausen sicher. Ohne sie sind Module nutzlos. + - Schau dir den Farbmischer genauer an und du wirst deine Antwort finden. + - Benutze STRG + Rechtsklick, um einen Bereich zu selektieren. + - Zu nahe am Hub zu bauen, kann späteren Projekten im Weg stehen. + - Die Reißzwecke neben Formen in der Upgrade-Liste lässt sie dich am + Bildschirm anheften. + - Mische alle drei Grundfarben, um Weiß zu erhalten! + - Du hast eine unendlich grosse Karte, nutze den Platz und expandiere! + - Probier auch mal Factorio! Es ist mein Lieblingsspiel. + - Der Vierfachschneider schneidet im Uhrzeigersinn von oben rechts beginnend! + - Du kannst deine Speicherstände im Hauptmenü herunterladen! + - Diese Spiel hat viele nützliche Tastenbelegungen! Schau sie dir in den + Einstellungen an. + - Dieses Spiel hat eine Menge Einstellungen, schaue sie dir einmal an! + - Die Richtung zu deinem Hub ist oben rechts mit einer kleinen Kompassnadel + markiert! + - Um alle Fließbänder zu leeren, schneide den Bereich aus und füge ihn auf + der selben Position wieder ein. + - Drücke F4 um deine FPS und Tickrate anzuzeigen. + - Drücke doppelt F4 um den Standort des Mauszeigers und der Kamera zu + bestimmen. + - Du kannst die angehefteten Formen am linken Rand wieder entfernen. diff --git a/translations/base-el.yaml b/translations/base-el.yaml index 90430f6a..08edd918 100644 --- a/translations/base-el.yaml +++ b/translations/base-el.yaml @@ -1,127 +1,76 @@ -# -# 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 is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. + shortText: Στο shapez.io χτήζεις εργοστάσια για να αυτοματοποιήσεις την + δημιουργία και τον συνδιασμό σχημάτων αυξανόμενης πολυπλοκότητας σε έναν + ατέλειωτο χάρτη. + discordLinkShort: Official Discord + intro: >- + Shapez.io is a relaxed game in which you have to build factories for the + automated production of geometric shapes. - # 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] + As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map. - 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. + And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! - 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]! + While you only process shapes at the beginning, you have to color them later - for this you have to extract and mix colors! - 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. + Buying the game on Steam gives you access to the full version, but you can also play a demo on shapez.io first and decide later! + title_advantages: Standalone Advantages + advantages: + - 12 New Level for a total of 26 levels + - 18 New Buildings for a fully automated factory! + - 20 Upgrade Tiers for many hours of fun! + - Wires Update for an entirely new dimension! + - Dark Mode! + - Unlimited Savegames + - Unlimited Markers + - Support me! ❤️ + title_future: Planned Content + planned: + - Blueprint Library (Standalone Exclusive) + - Steam Achievements + - Puzzle Mode + - Minimap + - Mods + - Sandbox mode + - ... and a lot more! + title_open_source: This game is open source! + title_links: Links + links: + discord: Official Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Help translate + text_open_source: >- + Anybody can contribute, I'm actively involved in the community and + attempt to review all suggestions and take feedback into consideration + where possible. - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! - global: - loading: Loading - error: Error - - # How big numbers are rendered, e.g. "10,000" + loading: Φόρτωση + error: Σφάλμα 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. + decimalSeparator: . suffix: - thousands: k - millions: M - billions: B - trillions: T - - # Shown for infinitely big numbers - infinite: inf - + thousands: χλ. + millions: εκ. + billions: δισ. + trillions: τρισ. + 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 - - # Short formats for times, e.g. '5h 23m' - secondsShort: s - minutesAndSecondsShort: m s - hoursAndMinutesShort: h s - - xMinutes: minutes - + oneSecondAgo: πριν ένα δευτερόλεπτο + xSecondsAgo: πριν δευτερόλεπτα + oneMinuteAgo: πριν ένα λεπτό + xMinutesAgo: πριν λεπτά + oneHourAgo: πριν μία ώρα + xHoursAgo: πριν ώρες + oneDayAgo: πριν μία ημέρα + xDaysAgo: πριν ημέρες + secondsShort: δ + minutesAndSecondsShort: λ δ + hoursAndMinutesShort: ω λ + xMinutes: λεπτά keys: tab: TAB control: CTRL @@ -129,742 +78,1024 @@ global: escape: ESC shift: SHIFT space: SPACE - 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! - + intro: Get the standalone to unlock all features! mainMenu: - play: Play + play: Παίξε changelog: Changelog - importSavegame: Import - openSourceHint: This game is open source! - discordLink: Official Discord Server - helpTranslate: Help translate! - - # 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 - - - continue: Continue - newGame: New Game + importSavegame: Εισαγωγή αποθηκευμένου παιχνιδιού + openSourceHint: Αυτό το παιχνίδι είναι ανοιχτού κώδικα! + discordLink: Επίσημο Discord Server + helpTranslate: Βοήθησε με μεταφράσεις! + browserWarning: Δυστυχώς, το παιχνίδι τρέχει αργά στο πρόγραμμα περιήγησής σας! + Αποκτήστε την αυτόνομη έκδοση ή κατεβάστε το chrome για την πλήρη + εμπειρία. + savegameLevel: Επίπεδο + savegameLevelUnknown: Άγνωστο Επίπεδο + continue: Συνέχεια + newGame: Καινούριο παιχνίδι madeBy: Made by subreddit: Reddit - + savegameUnnamed: Unnamed 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: Διαγραφή + cancel: Άκυρο + later: Αργότερα + restart: Επανεκκίνηση + reset: Επαναφορά + getStandalone: Απόκτησε την Αυτόνομη έκδοση + deleteGame: Ξέρω τί κάνω + viewUpdate: Προβολή ενημέρωσης + showUpgrades: Εμφάνιση αναβαθμίσεων + showKeybindings: Συνδυασμοί πλήκτρων importSavegameError: - title: Import Error - text: >- - Failed to import your savegame: - + title: Σφάλμα εισαγωγής + text: "Αποτυχία εισαγωγής του αποθηκευμένου παιχνιδιού:" importSavegameSuccess: - title: Savegame Imported - text: >- - Your savegame has been successfully imported. - + title: Εισαγωγή αποθηκευμένου παιχνιδιού + text: Η Εισαγωγή του αποθηκευμένου παιχνιδιού ήταν επιτυχής. gameLoadFailure: - title: Game is broken - text: >- - Failed to load your savegame: - + title: Το παιχνίδι είναι κατεστραμμένο + text: "Η φώρτοση του αποθηκευμένου παιχνιδιού ήταν αποτυχής:" confirmSavegameDelete: - title: Confirm deletion - text: >- - Are you sure you want to delete the game? - + title: Επιβεβαίωση διαγραφής + text: Are you sure you want to delete the following game?

+ '' at level

This can not be + undone! savegameDeletionError: - title: Failed to delete - text: >- - Failed to delete the savegame: - + title: Αποτυχία διαγραφής + text: "Η διαγραφή του αποθηκευμένου παιχνιδιού ήταν αποτυχής:" restartRequired: - title: Restart required - text: >- - You need to restart the game to apply the settings. - + title: Χρειάζεται επανεκκίνηση + text: Πρέπει να επανεκκινήσεις το παιχνίδι για να εφαρμόσεις τις ρυθμίσεις. 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 to get the standalone for the full experience! - + title: Έκδοση Demo + 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! - + title: Περιορισμένα αποθηκευμένα παιχνίδια + desc: Στην demo έκδοση μπορείς να έχεις μόνο ένα αποθηκευμένο παιχνίδι. Παρακαλώ + διάγραψε το υπάρχον αποθηκευμένο παιχνίδι ή απόκτησε την αθτόνομη + έκδοση! updateSummary: - title: New update! - desc: >- - Here are the changes since you last played: - + title: Νέα αναβάθμιση! + desc: "Αυτές είναι οι αλλαγές από την τελευταία φορά που έπαιξες:" upgradesIntroduction: - title: Unlock Upgrades - 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. - + title: Ξεκλείδωμα αναβαθμίσεων + desc: Όλα τα σχήματα που παράγεις μπορούν να χρησιμοποιηθούν για να ξεκλειδώσεις + αναβαθμίσεις - Μην καταστρέψεις τα παλιά σου εργοστάσια! + Η καρτέλα αναβαθμίσεων βρίσκεται στην επάνω δεξιά γωνία + της οθόνης. massDeleteConfirm: - title: Confirm delete - desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? - + title: Επιβεβαίωση διαγραφής + desc: Ετοιμάζεσαι να διαγράψεις πολλά κτήρια ( για την ακρίβεια)! Είσαι + βέβαιος/η ότι θέλεις να το κάνεις αυτό; blueprintsNotUnlocked: - title: Not unlocked yet - desc: >- - Blueprints have not been unlocked yet! Complete more levels to unlock them. - + title: Αυτή η δυνατότητα δεν έχει ξεκλειδωθεί ακόμα + desc: Τα σχεδιαγράμματα δεν έχουν ξεκλειδωθεί ακόμα! Ολοκλήρωσε περισσότερα + επίπεδα για να τα ξεκλειδώσεις. keybindingsIntroduction: - title: Useful 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 area to copy / delete.
- SHIFT: Hold to place multiple of one building.
- ALT: Invert orientation of placed belts.
- + title: Χρήσιμοι Συνδιασμοί πλήκτρων + desc: "Αυτό το παιχνίδι έχει πολλούς συνδιασμούς πλήκτρων που διευκολύνουν στο + χτήσιμο μεγάλων εργοστασίων. Εδώ είναι μερικοί από αυτούς. Για τους + υπόλοιπους αναφέρσου στην ενότητα Συνδιασμοί + πλήκτρων

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: Νέο Σημάδι + desc: Give it a meaningful name, you can also include a short + key of a shape (Which you can generate here) + titleEdit: Επεξεργασία Σημαδιού markerDemoLimit: - desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! + desc: Στην έκδωση demo μπορείς να βάλεις μέχρι δύο σημάδια στον χάρτη. + Αποκτήστε την αυτόνομη έκδοση για να μπορείς να βάλεις απεριόριστα + σημάδια στον χάρτη! massCutConfirm: - title: Confirm cut - desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you - want to do this? - + title: Επιβεβαίωση αποκοπής + desc: Ετοιμάζεσαι να αποκόψεις πολλά κτήρια ( φια την ακρίβεια)! Είσαι + βέβαιος/η ότι θέλεις να το κάνεις αυτό; 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: Ζήτησες να εξαγάγεις τη βάση σου ως στιγμιότυπο οθόνης. Λάβε υπόψη ότι + αυτό μπορεί να είναι αρκετά αργό για μια μεγάλη βάση και μπορεί + ακόμη και να διακόψει (crash) το παιχνίδι σου! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? - + title: Επιβεβαίωση αποκοπής + desc: Δεν έχεις τους πόρους να επικολλήσεις αυτήν την περιοχή! Είσαι βέβαιος/η + ότι θέλεις να την αποκόψεις; + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: Rename Savegame + desc: You can rename your savegame here. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? 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 - plannerSwitchSide: Flip planner side - cutSelection: Cut - copySelection: Copy - clearSelection: Clear Selection - pipette: Pipette - switchLayers: Switch layers - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + moveMap: Κίνηση + selectBuildings: Επιλογή περιοχής + stopPlacement: Διακοπή τοποθέτησης + rotateBuilding: Περιστροφή κτηρίου + placeMultiple: Τοποθέτηση πολλαπλών κτηρίων + reverseOrientation: Αντιστροφή προσανατολισμού ιμάντα + disableAutoOrientation: Απενεργοποίηση αυτόματου προσανατολισμού + toggleHud: Εναλλαγή HUD + placeBuilding: Τοποθέτηση κτηρίου + createMarker: Δημιουργία σημαδιού + delete: Διαγραφή + pasteLastBlueprint: Επικόλληση τελευταίου σχεδιαγράμματος + lockBeltDirection: Ενεργοποίηση σχεδιαστή ιμάντα + plannerSwitchSide: Αλλαγή πλευράς σχεδιαστή + cutSelection: Αποκοπή + copySelection: Αντιγραφή + clearSelection: Εκκαθαρισμός επιλογής + pipette: Σταγονόμετρο + switchLayers: Εναλλαγή στρώματος 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. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - + cycleBuildingVariants: Πάτησε για εναλλαγή μεταξύ παραλλαγών. + 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 - - # The notification when completing a level + tiles: πλακάκια levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: Level - completed: Completed - unlockText: Unlocked ! - buttonNextLevel: Next Level - - # Notifications on the lower right + levelTitle: Επίπεδο + completed: Ολοκληρώθηκε + unlockText: Ξεκλειδώθηκε ! + buttonNextLevel: Επόμενο επίπεδο notifications: - newUpgrade: A new upgrade is available! - gameSaved: Your game has been saved. - - # The "Upgrades" window + newUpgrade: Μια νέα αναβάθμιση είναι διαθέσιμη! + gameSaved: Το παιχνίδι έχει αποθηκευτεί. + freeplayLevelComplete: Level has been completed! shop: - title: Upgrades - buttonUnlock: Upgrade - - # Gets replaced to e.g. "Tier IX" - tier: Tier - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - - maximumLevel: MAXIMUM LEVEL (Speed x) - - # The "Statistics" window + title: Αναβαθμίσεις + buttonUnlock: Αναβάθμιση + tier: Βαθμίδα + maximumLevel: ΜΕΓΙΣΤΟ ΕΠΙΠΕΔΟ (Ταχύτητα x) 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. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + title: Παραδωμένα + description: Εμφάνιση σχημάτων που παραδίδονται στο κεντρικό σου κτήριο. + noShapesProduced: Δεν έχεις παράξει σχήματα ακόμα. + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: - playtime: Playtime - - buildingsPlaced: Buildings - beltsPlaced: Belts - - buttons: - continue: Continue - settings: Settings - menu: Return to menu - - # Bottom left tutorial hints + playtime: Χρόνος που έπαιξες + buildingsPlaced: Κτήρια + beltsPlaced: Ιμάντες tutorialHints: - title: Need help? - showHint: Show hint - hideHint: Close - - # When placing a blueprint + title: Χρειάζεσε βοήθεια; + showHint: Εμφάνιση υπόδειξης + hideHint: Kλείσιμο blueprintPlacer: - cost: Cost - - # Map markers + cost: Κόστος waypoints: - waypoints: Markers + waypoints: Σημάδι 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. - - # Interactive tutorial + description: Κάνε αριστερό κλικ σε ένα σημάδι για να μεταβείς σε αυτό, κάνε δεξί + κλικ για να το διαγράψεις.

Πάτησε για να + δημιουργήσεις ένα σημάδι από την τρέχουσα προβολή ή δεξί + κλικ για να δημιουργήσεις ένα σημάδι στην επιλεγμένη + τοποθεσία. + creationSuccessNotification: Το σημάδι δημιουργήθηκε. interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! - 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. - + 1_1_extractor: Τοποθέτησε έναν αποσπαστή πάνω από ένα + σχήμα κύκλου για να το αποσπάεις! + 1_2_conveyor: "Σύνδεσε τον αποσπαστή με έναν μεταφορικό ιμάντα + στο κεντρικό σου κτήριο!

Συμβουλή: Κάνε κλικ και + σύρε τη ζώνη με το ποντίκι σου!" + 1_3_expand: "Αυτό ΔΕΝ είναι ένα αδρανές παιχνίδι! Δημιούργησε + περισσότερους αποσπαστές και ιμάντες για να ολοκληρώσεις τον + στόχο σου πιο γρήγορα.

Συμβουλή: Κράτησε το πλήκτρο + SHIFT για να τοποθετήσεις πολλούς αποσπαστές + και χρησιμοποιήστε το R για να τους + περιστρέψεις." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." colors: - red: Red - green: Green - blue: Blue - yellow: Yellow - purple: Purple - cyan: Cyan - white: White - uncolored: No color - black: Black + red: Κόκκινο + green: Πράσινο + blue: Μπλε + yellow: Κίτρινο + purple: Μωβ + cyan: Γαλάζιο + white: Λευκό + uncolored: Χωρίς χρώμα + black: Μαύρο shapeViewer: - title: Layers - empty: Empty - copyKey: Copy Key - -# All shop upgrades + title: Στρώματα + empty: Κενό + copyKey: Αντιγραφή κώδικα + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limited to + watermark: + title: Demo version + desc: Click here to see the Steam version advantages! + get_on_steam: Get on steam + standaloneAdvantages: + title: Get the full version! + no_thanks: No, thanks! + points: + levels: + title: 12 New Levels + desc: For a total of 26 levels! + buildings: + title: 18 New Buildings + desc: Fully automate your factory! + savegames: + title: ∞ Savegames + desc: As many as your heart desires! + upgrades: + title: 20 Upgrade Tiers + desc: This demo version has only 5! + markers: + title: ∞ Markers + desc: Never get lost in your factory! + wires: + title: Wires + desc: An entirely new dimension! + darkmode: + title: Dark Mode + desc: Stop hurting your eyes! + support: + title: Support me + desc: I develop it in my spare time! 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 - -# Buildings and their name / description + name: Ανάμειξη & Βαφή + description: Ταχύτητα x → x buildings: belt: default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. - - miner: # Internal name for the Extractor + name: Μεταφορικός Ιμάντας + description: Μεταφέρει είδη. Κράτα πατημένο και σύρε για να τοποθετήσεις + πολλαπλούς ιμάντες. + miner: default: - name: &miner Extractor - description: Place over a shape or color to extract it. - + name: Αποσπαστής + description: Τοποθέτησε πάνω από ένα σχήμα ή χρώμα για να το αποσπάσεις. chainable: - name: Extractor (Chain) - description: Place over a shape or color to extract it. Can be chained. - - underground_belt: # Internal name for the Tunnel + name: Αποσπαστής (Αλυσιδωτός) + description: Τοποθέτησε πάνω από ένα σχήμα ή χρώμα για να το αποσπάσεις. Μπορούν + να συνδεθούν σε σειρά. + underground_belt: default: - name: &underground_belt Tunnel - description: Allows to tunnel resources under buildings and belts. - + name: Σήραγγα + description: Μεταφέρει είδη κάτω από κτήρια και μεταφορικούς ιμάντες. 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. - + name: Σήραγγα Βαθμίδα II + description: Μεταφέρει είδη κάτω από κτήρια και μεταφορικούς ιμάντες. 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: Κόπτης + description: Κόβει σχήματα από πάνω προς τα κάτω και παράγει και τα δύο μισά. + Εάν χρησιμοποιείς μόνο το ένα κομμάτι, φρόντισε να + καταστρέψεις το άλλο κομμάτι, διαφορετικά η λειτουργία θα + σταματήσει! 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: Κόπτης (Τετάρτων) + description: Κόβει σχήματα σε τέσσερα κομμάτια. Εάν χρησιμοποιείς μόνο + το ένα κομμάτι, φρόντισε να καταστρέψεις τα άλλα κομμάτια, + διαφορετικά η λειτουργία θα σταματήσει! rotater: default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. + name: Περιστροφέας + description: Περιστρέφει τα σχήματα δεξιόστροφα κατά 90 μοίρες. ccw: - name: Rotate (CCW) - description: Rotates shapes counter clockwise by 90 degrees. - + name: Περιστροφέας (Αρστ.) + description: Περιστρέφει τα σχήματα αριστερόστροφα κατά 90 μοίρες. + rotate180: + name: Rotate (180) + description: Rotates shapes by 180 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. - + name: Στοίβαχτής + description: Στοιβάζει και τα δύο είδη. Εάν δεν μπορούν να συγχωνευτούν, το δεξί + είδος τοποθετείται πάνω από το αριστερό είδος. mixer: default: - name: &mixer Color Mixer - description: Mixes two colors using additive blending. - + name: Αναμείκτης Χρωμάτων + description: Αναμειγνύει δύο χρώματα χρησιμοποιώντας ανάμιξη πρόσθετων. painter: default: - name: &painter Painter - description: &painter_desc Colors the whole shape on the left input with the color from the right input. + name: Βαφέας + description: Χρωματίζει ολόκληρο το σχήμα στην αριστερή είσοδο με το χρώμα από + τη δεξιά είσοδο. 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 to color each quadrant of the shape with a different color. + name: Βαφέας (Τετάρτων) + description: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! mirrored: - name: *painter - description: *painter_desc - + name: Βαφέας + description: Χρωματίζει ολόκληρο το σχήμα στην αριστερή είσοδο με το χρώμα από + τη δεξιά είσοδο. 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. - + name: Κάδος απορριμμάτων + description: Δέχεται είδη από όλες τις πλευρές και τα καταστρέφει. Για πάντα. hub: - deliver: Deliver - toUnlock: to unlock + deliver: Παράδωσε + toUnlock: για να ξεκλειδώσεις levelShortcut: LVL + endOfDemo: End of Demo wire: default: - name: Energy Wire - description: Allows you to transport energy. - advanced_processor: + name: Καλώδιο ενέργειας + description: Σου επιτρέπει να μεταφέρεις ενέργεια. + second: + name: Wire + description: Transfers signals, which can be items, colors or booleans (1 / 0). + Different colored wires do not connect. + balancer: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For - default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Merger (compact) + description: Merges two conveyor belts into one. + merger-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + storage: + default: + name: Storage + description: Stores excess items, up to a given capacity. Prioritizes the left + output and can be used as an overflow gate. + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: Switch + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means + shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. + (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means + shape, color or boolean "1") + transistor: + default: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + mirrored: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: Belt Reader + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: Virtual Cutter + description: Virtually cuts the shape into two halves. + rotater: + name: Virtual Rotater + description: Virtually rotates the shape, both clockwise and counter-clockwise. + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the + remaining ones to the left. + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the shape on + the right input. + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the + wires layer on the regular layer. 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: You just unlocked the cutter, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! reward_rotater: - title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. - + title: Περιστροφή + desc: Ο Περιστροφέας ξεκλειδώθηκε! Το κτήριο αυτό περιστρέφει + τα σχήματα δεξιόστροφα κατά 90 μοίρες. 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! - + title: Βαφή + desc: "Μόλις ξεκλειδώθηκε ο Βαφέας - Απόσπασε μερικά χρώματα + (όπως κάνεις με τα σχήματα) και συνδύασέ τα με ένα σχήμα στον βαφέα + για να τα χρωματίσεις!

PS: Εάν πάσχεις από αχρωματοψία, + τυφλοί, υπάρχει η λειτουργία αχρωματοψίας στις + ρυθμίσεις!" 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: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! reward_tunnel: - title: Tunnel - desc: The tunnel has been unlocked - You can now pipe 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 to rotate counter clockwise! To build it, select the rotater and press 'T' to cycle 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: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" 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! - - 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! - + title: Σήραγγα Βαθμίδα II + desc: Ξεκλείδωσες μια νέα παραλλαγή της Σήραγγας - Καλύπτει + μεγαλύτερη απόσταση και επιτρέπει το "πλέξιμο" + διαφορετικών βαθμίδων σήραγγας! 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! - - 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: Διπλός Βαφέας + desc: Ξεκλείδωσες μια παραλλαγή του Βαφέα - Λειτουργεί όπως ο + κανονικός βαφέας, αλλά επεξεργάζεται δύο σχήματα + ταυτόχρονα, καταναλώνοντας μόνο ένα χρώμα αντί για δύο! 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: Αποθηκευτικός χώρος + desc: You have unlocked the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! 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: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. 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). - - # Special reward, which is shown when there is no reward actually + title: Σχεδιαγράμματα + desc: Μπορείς πλέον να κάνεις αντιγραφή και επικόλληση στα μέρη + του εργοστασίου σου! Επίλεξε μια περιοχή (Κράτα πατημένο το CTRL, + και τράβα το ποντίκι σου), και πάτησε 'C' για να αντιγράψεις τα + κτήρια στην επιλεγμένη περιοχή.

Η επικόλληση δεν + είναι δωρεάν, θα πρέπει να παράγεις σχήματα + σχεδιαγράμματος για να χρησημοποιήσεις αυτή την δυνατότητα! + (Τα σχήματα που μόλις παρέδωσες). 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! - + title: Επόμενο Επίπεδο + desc: "Αυτό το επίπεδο δεν σου παρήχε κάποια αμοιβή, άλλα το επόμενο επίπεδο θα + σου δώσει!

Υ.Γ.: Καλύτερα μην καταστρέψεις το υπάρχον σου + εργοστάσιο - θα χρειαστείς όλα αυτά τα σχήματα ξανά + αργότερα για να ξεκλειδώσεις αναβαθμίσεις!" no_reward_freeplay: - title: Next level - desc: >- - Congratulations! By the way, more content is planned for the standalone! - + title: Επόμενο Επίπεδο + desc: Συγχαριτήρια! Παρεμπιπτόντως, περισσότερο περιεχόμενο θα έρθει σύντομα + στην αυτόνομη έκδοση! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: End of Demo + desc: You have reached the end of the demo version! settings: - title: Settings + title: Ρυθμίσεις categories: - game: Game - app: Application - + general: Γενικές + userInterface: Περιβάλλον χρήστη + advanced: Προχωρημένα + performance: Performance versionBadges: dev: Development staging: Staging prod: Production buildDate: Built - labels: 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. + title: Κλίμακα περιβάλλοντος χρήστη + description: Αλλάζει το μέγεθος του περιβάλλοντος χρήστη. Το περιβάλλον χρήστη + θα κλιμακωθεί με βάση την ανάλυση της συσκευής σας, αλλά αυτή η + ρύθμιση ελέγχει το μέγεθος εντώς αυτής της κλίμακας. scales: - super_small: Super small - small: Small - regular: Regular - large: Large - huge: Huge - + super_small: Πολύ μικρό + small: Μικρό + regular: Κανονικό + large: Μεγάλο + huge: Πολύ μεγάλο scrollWheelSensitivity: - title: Zoom sensitivity - description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + title: Ευαισθησία ζουμ + description: Αλλάζει πόσο ευαίσθητο είναι το ζουμ (Είτε με τον τροχό ποντικιού ή + με trackpad). sensitivity: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super fast - + super_slow: Πολύ αργό + slow: Αργό + regular: Κανονικό + fast: Γρήγορο + super_fast: Πολύ γρήγορο language: - title: Language - description: >- - Change the language. All translations are user contributed and might be incomplete! - + title: Γλώσσα + description: Αλλάξτε τη γλώσσα. Γιά όλες τις μεταφράσεις έχουν συνεισφέρει + χρήστες. Μερικές μεταφράσεις ενδέχεται να είναι ελλιπείς! fullscreen: - title: Fullscreen - description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. - + title: Λειτουργία πλήρους οθόνης + description: Για την καλύτερη δυνατή εμπειρία συνιστάται η λειτουργία πλήρους + οθόνης. Διατίθεται μόνο στην αυτόνομη έκδοση. soundsMuted: - title: Mute Sounds - description: >- - If enabled, mutes all sound effects. - + title: Σίγαση ήχων + description: Εάν είναι ενεργοποιημένο, σβήνει όλα τα ηχητικά εφέ. musicMuted: - title: Mute Music - description: >- - If enabled, mutes all music. - + title: Σίγαση μουσικής + description: Εάν είναι ενεργοποιημένο, σβήνει την μουσική. theme: - title: Game theme - description: >- - Choose the game theme (light / dark). - + title: Λειτουργία παιχνιδιού + description: Επίλεξε το την λειτουργία του παιχνιδιού (Φωτεινή / Σκοτεινή). themes: - dark: Dark - light: Light - + dark: Σκοτεινή + light: Φωτεινή refreshRate: - title: Simulation Target - 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. - + title: Στόχος Προσομοίωσης + description: Εάν έχεις οθόνη 144hz, άλλαξε τον ρυθμό ανανέωσης εδώ, ώστε το + παιχνίδι να προσομοιωθεί σωστά σε υψηλότερους ρυθμούς ανανέωσης. + Μπορεί να μειώσει τα FPS εάν ο υπολογιστής σου είναι πολύ αργός. alwaysMultiplace: - title: Multiplace - description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. - + title: Πολλαπλή τοποθέτηση + description: Εάν είναι ενεργοποιημένο, όλα τα κτίρια θα παραμείνουν επιλεγμένα + μετά την τοποθέτηση έως ότου ακυρώσεις την επιλογή. Αυτό + ισοδυναμεί με μόνιμο κράτημα του SHIFT. 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. - + title: Συμβουλές & Οδηγίες + description: Αν θέλεις να προσφέρονται συμβουλές και οδηγίες ενώ παίζεις. Επίσης + κρύβει ορισμένα στοιχεία του περιβάλλοντος χρήστη έως ένα + δεδομένο επίπεδο, για να διευκολύνει το παιχνίδι για νέους + χρήστες. movementSpeed: - title: Movement speed - description: Changes how fast the view moves when using the keyboard. + title: Ταχύτητα κίνησης + description: Αλλάζει την ταχύτητα κίνησης όταν χρησιμοποιείς το πληκτρολόγιο. 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: Πάρα πολύ γρήγορη 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. + title: Έξυπνες σήραγγες + description: Όταν ενεργοποιηθεί, η τοποθέτηση σηράγγων θα αφαιρέσει αυτόματα τις + περιττές ζώνες. Αυτό σου επιτρέπει επίσης να σύρεις το ποντίκι + με την σήραγγα επιλεγμένη, και οι περιττές σήραγγες θα + αφαιρεθούν. vignette: - title: Vignette - description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. - + title: Βινιέτα + description: Ενεργοποιεί την Βιωιέτα, που σκουραίνει τις γωνίες της οθόνης και + διευκολύνει την ανάγνωση του κειμένου. autosaveInterval: - title: Autosave Interval - description: >- - Controls how often the game saves automatically. You can also disable it - entirely here. + title: Διάστημα μεταξύ αυτόματων αποθηκεύσεων + description: Ελέγχει πόσο συχνά το παιχνίδι αποθηκεύεται αυτόματα. Εδώ μπορείς + επίσης να απενεργοποιήσεις την λειτουργία εντελώς. 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: Απενεργοποιημένο compactBuildingInfo: - title: Compact Building Infos - description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a - description and image is shown. - + title: Σύντομες πληροφορίες κτηρίων + description: Συντομεύει τα πλαίσια πληροφοριών για κτίρια δείχνοντας μόνο την + ταχύτητα λειτουργίας τους. Διαφορετικά εμφανίζεται μια περιγραφή + και εικόνα. disableCutDeleteWarnings: - title: Disable Cut/Delete Warnings - description: >- - Disable the warning dialogs brought up when cutting/deleting more than 100 - entities. - + title: Απενεργοποίηση προειδοποιήσεων αποκοπής / διαγραφής + description: Απενεργοποιεί τους διαλόγους προειδοποίησης που εμφανίζονται όταν + κόβεις / διαγράφεις περισσότερα από 100 κτήρια. enableColorBlindHelper: - title: Color Blind Mode - description: Enables various tools which allow to play the game if you are color blind. + title: Λειτουργία αχρωματοψίας + description: Ενεργοποιεί διάφορα εργαλεία που επιτρέπουν να παίξεiw το παιχνίδι + αν πάσχεις από αχρωματοψία. 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. - + title: Περιστροφή ανά τύπο κτιρίου + description: Κάθε τύπος κτιρίου θυμάται την περιστροφή που όρισες στην τελευταία + χρήση. Μπορεί να είναι πιο άνετο εάν κάνεις εναλλαγή κτηρίων + μεταξύ τοποθέτησης διαφορετικών τύπων κτηρίων. + soundVolume: + title: Sound Volume + description: Set the volume for sound effects + musicVolume: + title: Music Volume + description: Set the volume for music + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: - title: Keybindings - hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - - resetKeybindings: Reset Keyinbindings - + title: Συνδιασμοί πλήκτρων + hint: "Συμβουλή: Φρόντισε να χρησιμοποιήσεις τα πλήκτρα CTRL, SHIFT και ALT! + Ενεργοποιούν διαφορετικές επιλογές τοποθέτησης." + 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 - centerMap: Center Map - - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker - - menuOpenShop: Upgrades - menuOpenStats: Statistics - - toggleHud: Toggle HUD - toggleFPSInfo: Toggle FPS and Debug Info - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - - rotateWhilePlacing: Rotate - rotateInverseModifier: >- - Modifier: Rotate CCW instead - cycleBuildingVariants: Cycle Variants - confirmMassDelete: Confirm Mass Delete - cycleBuildings: Cycle Buildings - - massSelectStart: Hold and drag to start - massSelectSelectMultiple: Select multiple areas - massSelectCopy: Copy 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 - + confirm: Επιβεβαίωση + back: Πίσω + mapMoveUp: Κίνηση προς τα Πάνω + mapMoveRight: Κίνηση προς τα Δεξιά + mapMoveDown: Κίνηση προς τα Κάτω + mapMoveLeft: Κίνηση προς τα Αριστερά + centerMap: Kεντράρισμα του χάρτη + mapZoomIn: Μεγέθυνση + mapZoomOut: Σμίκρυνση + createMarker: Δημηουργία Σημαδιού + menuOpenShop: Αναβαθμίσεις + menuOpenStats: Στατιστικές + toggleHud: Εναλλαγή HUD + toggleFPSInfo: Εναλλαγή FPS και Πληροφοριών εντοπισμού σφαλμάτων + belt: Μεταφορικός Ιμάντας + underground_belt: Σήραγγα + miner: Αποσπαστής + cutter: Κόπτης + rotater: Περιστροφέας + stacker: Στοίβαχτής + mixer: Αναμείκτης Χρωμάτων + painter: Βαφέας + trash: Κάδος απορριμμάτων + rotateWhilePlacing: Περιστροφή + rotateInverseModifier: "Modifier: Αριστερόστροφη περιστροφή" + cycleBuildingVariants: Επιλογή Παραλλαγής + confirmMassDelete: Επιβεβαίωση μαζικής διαγραφής + cycleBuildings: Επιλογή Κτηρίου + massSelectStart: Κράτησε πατημένο και σείρε για να ξεκινήσεις + massSelectSelectMultiple: Επίλεξε πολλές περιοχές + massSelectCopy: Αντιγραφή περιοχής + placementDisableAutoOrientation: Απενεργοποίηση αυτόματου προσανατολισμού + placeMultiple: Παραμονή σε λειτουργία τοποθέτησης + placeInverse: Αντιστροφή αυτόματου προσανατολισμό του ιμάντα + pasteLastBlueprint: Επικόλληση τελευταίου σχεδιαγράμματος + massSelectCut: Αποκοπή περιοχής + exportScreenshot: Εξαγωγή ολόκληρης της βάσης ως εικόνα + mapMoveFaster: Ταχλυτερη κίνηση + lockBeltDirection: Ενεργοποίηση σχεδιαστή ιμάντα + switchDirectionLockSide: "Σχεδιαστής: Αλλαγή πλευράς" + pipette: Σταγονόμετρο + menuClose: Κλείσιμο μενού + switchLayers: Εναλλαγή επιπέδων + wire: Καλώδιο ενέργειας + balancer: Balancer + storage: Storage + constant_signal: Constant Signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" 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.

+ Αν θέλεις να συνεισφέρεις, δες το shapez.io στο github.

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

+ Αυτό το παιχνίδι δεν θα ήταν δυνατό χωρίς τη μεγάλη κοινότητα Discord + γύρω από τα παιχνίδια μου - Σας συνιστώ πραγματικά να εγγραφείτε στον + 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. + Το soundtrack δημιουργήθηκε από τους Peppsen - Είναι φοβεροί.

+ Τέλος, ευχαριστώ πολύ τον καλύτερο μου φίλο Niklas - Χωρίς + τις συνεδρίες μασ στο Factorio αυτό το παιχνίδι δεν θα υπήρχε. 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 - - settingNotAvailable: Not available in the demo. + restoringGames: Επαναφορά αποθηκευμένων παιχνιδιών + importingGames: Εισαγωγή αποθηκευμένων παιχνιδιών + oneGameLimit: Περιορίζεται σε ένα αποθηκευμένο παιχνίδι + customizeKeybindings: Προσαρμογή συνδιασμών πλήκτρων + exportingBase: Εξαγωγή ολόκληρης της βάσης ως εικόνα + settingNotAvailable: Δεν είναι διαθέσιμο στο demo. +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-en.yaml b/translations/base-en.yaml index 8a732442..90b6886c 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -1,5 +1,5 @@ # -# GAME TRANSLATIONS +# GAME TRANSLATIONS # # Contributing: # @@ -15,76 +15,62 @@ # # 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 - discordLink: Official Discord - Chat with me! + # This is the text shown above the Discord link + discordLinkShort: Official 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: - # - 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] + intro: >- + Do you like automation games? Then you are in the right place! - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. + shapez.io is a relaxed game in which you have to build factories for the automated production of geometric shapes. As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map. - Upon delivering the requested shapes you'll progress within the game and unlock upgrades to speed up your factory. + And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! While you only have to process shapes at the beginning, you will later have to color them - by extracting and mixing colors! - 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]! + Buying the game on Steam gives you access to the full version, but you can also play a demo at shapez.io first and decide later! - 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. + title_advantages: Standalone Advantages + advantages: + - 12 New Levels for a total of 26 levels + - 18 New Buildings for a fully automated factory! + - 20 Upgrade Tiers for many hours of fun! + - Wires Update for an entirely new dimension! + - Dark Mode! + - Unlimited Savegames + - Unlimited Markers + - Support me! ❤️ - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/b] - - 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) - [*] 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] + title_future: Planned Content + planned: + - Blueprint Library + - Steam Achievements + - Puzzle Mode + - Minimap + - Mods + - Sandbox mode + - ... and a lot more! + title_open_source: This game is open source! + text_open_source: >- 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] + Be sure to check out my trello board for the full roadmap! - [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] + title_links: Links + + links: + discord: Official Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Help translate global: loading: Loading @@ -136,7 +122,7 @@ 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! + Get the full game to unlock all features and content! mainMenu: play: Play @@ -152,10 +138,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 slowly on your browser! Get the standalone version or download Google Chrome for the full experience. savegameLevel: Level savegameLevelUnknown: Unknown Level + savegameUnnamed: Unnamed dialogs: buttons: @@ -189,7 +176,9 @@ dialogs: confirmSavegameDelete: title: Confirm deletion text: >- - Are you sure you want to delete the game? + Are you sure you want to delete the following game?

+ '' at level

+ This can not be undone! savegameDeletionError: title: Failed to delete @@ -211,7 +200,7 @@ dialogs: keybindingsResetOk: title: Keybindings reset - desc: The keybindings have been reset to their respective defaults! + desc: All keybindings have been reset to their defaults values! featureRestriction: title: Demo Version @@ -229,7 +218,7 @@ dialogs: upgradesIntroduction: title: Unlock Upgrades desc: >- - All shapes you produce can be used to unlock upgrades - Don't destroy your old factories! + 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: @@ -264,14 +253,32 @@ dialogs: createMarker: title: New Marker titleEdit: Edit Marker - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) + desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) + + editSignal: + title: Set Signal + descItems: >- + Choose a pre-defined item: + descShortKey: ... or enter the 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! 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! + desc: You requested to export your base as a screenshot. Please note that this will be quite slow for a bigger base and could potentially crash your game! + + renameSavegame: + title: Rename Savegame + desc: You can rename your savegame here. + + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to watch it? + + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only available in English. Would you like to watch it? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -303,7 +310,7 @@ ingame: green: Green blue: Blue yellow: Yellow - purple: Purple + purple: Magenta cyan: Cyan white: White black: Black @@ -323,7 +330,7 @@ ingame: infoTexts: speed: Speed range: Range - storage: Storage + storage: Capacity oneItemPerSecond: 1 item / second itemsPerSecond: items / s itemsPerSecondDouble: (x2) @@ -342,6 +349,7 @@ ingame: notifications: newUpgrade: A new upgrade is available! gameSaved: Your game has been saved. + freeplayLevelComplete: Level has been completed! # The "Upgrades" window shop: @@ -351,9 +359,6 @@ ingame: # Gets replaced to e.g. "Tier IX" tier: Tier - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXIMUM LEVEL (Speed x) # The "Statistics" window @@ -362,30 +367,27 @@ ingame: dataSources: stored: title: Stored - description: Displaying amount of stored shapes in your central building. + description: All shapes stored within the Hub. produced: title: Produced - description: Displaying all shapes your whole factory produces, including intermediate products. + description: All shapes produced within your factory, including intermediate products. delivered: title: Delivered - description: Displaying shapes which are delivered to your central building. + description: Shapes which are being delivered to the Hub. 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' + shapesDisplayUnits: + second: / s + minute: / m + hour: / h # Settings menu, when you press "ESC" settingsMenu: playtime: Playtime - buildingsPlaced: Buildings beltsPlaced: Belts - buttons: - continue: Continue - settings: Settings - menu: Return to menu - # Bottom left tutorial hints tutorialHints: title: Need help? @@ -420,6 +422,85 @@ 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. + 2_1_place_cutter: >- + Now place a Cutter to cut the circles in two halves!

+ PS: The cutter always cuts from top to bottom regardless of its orientation. + + 2_2_place_trash: >- + The cutter can clog and stall!

+ Use a trash to get rid of the currently (!) not needed waste. + + 2_3_more_cutters: >- + Good job! Now place 2 more cutters to speed up this slow process!

+ PS: Use the 0-9 hotkeys to access buildings faster! + + 3_1_rectangles: >- + Now let's extract some rectangles! Build 4 extractors and connect them to the hub.

+ PS: Hold SHIFT while dragging a belt to activate the belt planner! + + 21_1_place_quad_painter: >- + Place the quad painter and get some circles, white and red color! + + 21_2_switch_to_wires: >- + Switch to the wires layer by pressing E!

+ Then connect all four inputs of the painter with cables! + + 21_3_place_button: >- + Awesome! Now place a Switch and connect it with wires! + + 21_4_press_button: >- + Press the switch to make it emit a truthy signal and thus activate the painter.

+ PS: You don't have to connect all inputs! Try wiring only two. + + # Connected miners + connectedMiners: + one_miner: 1 Extractor + n_miners: Extractors + limited_items: Limited to + + # Pops up in the demo every few minutes + watermark: + title: Demo version + desc: Click here to see the advantages of the standalone version! + get_on_steam: Get on Steam + + standaloneAdvantages: + title: Get the full version! + no_thanks: No, thanks! + + points: + levels: + title: 12 New Levels + desc: For a total of 26 levels! + + buildings: + title: 18 New Buildings + desc: Fully automate your factory! + + savegames: + title: ∞ Savegames + desc: As many as your heart desires! + + upgrades: + title: 20 Upgrade Tiers + desc: This demo version has only 5! + + markers: + title: ∞ Markers + desc: Never get lost in your factory! + + wires: + title: Wires + desc: An entirely new dimension! + + darkmode: + title: Dark Mode + desc: Stop hurting your eyes! + + support: + title: Support me + desc: I develop it in my spare time! + # All shop upgrades shopUpgrades: belt: @@ -441,18 +522,15 @@ buildings: deliver: Deliver toUnlock: to unlock levelShortcut: LVL + endOfDemo: End of Demo belt: default: 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. @@ -461,7 +539,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. @@ -470,31 +549,35 @@ buildings: name: Tunnel Tier II description: Allows you to tunnel resources under buildings and belts. - splitter: # Internal name for the Balancer + # Balancer + balancer: default: - name: &splitter Balancer + name: &balancer Balancer description: Multifunctional - Evenly distributes all inputs onto all outputs. - compact: + merger: name: Merger (compact) description: Merges two conveyor belts into one. - compact-inverse: + merger-inverse: name: Merger (compact) description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + 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! + 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 clog and 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. + description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other parts or it will clog and stall! rotater: default: @@ -503,11 +586,14 @@ buildings: ccw: name: Rotate (CCW) description: Rotates shapes counter-clockwise by 90 degrees. + rotate180: + name: Rotate (180°) + description: Rotates shapes by 180 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. + description: Combines its inputs, on the same layer if possible, otherwise the right input is stacked on top of the left input. mixer: default: @@ -517,52 +603,133 @@ buildings: painter: default: name: &painter Painter - description: &painter_desc Colors the whole shape on the left input with the color from the top input. + description: &painter_desc Paints the whole shape on the left input with the color from the top input. mirrored: name: *painter - description: *painter_desc + description: Paints the whole shape on the left input with the color from the bottom 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 you to color each quadrant of the shape with a different color. + description: Allows you to color each quadrant of the shape individually. Only slots with a truthy signal on the wires layer will be painted! 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. - - energy_generator: - deliver: Deliver - - # This will be shown before the amount, so for example 'For 123 Energy' - toGenerateEnergy: For - + storage: default: - name: &energy_generator Energy Generator - description: Generates energy by consuming shapes. + name: &storage Storage + description: Stores excess items, up to a given capacity. Prioritizes the left output and can be used as an overflow gate. - wire_crossings: + wire: default: - name: &wire_crossings Wire Splitter - description: Splits a energy wire into two. + name: &wire Wire + description: &wire_desc Transfers signals, which can be items, colours or booleans (1 or 0). Differently-coloured wires do not connect to each other. - merger: - name: Wire Merger - description: Merges two energy wires into one. + second: + name: *wire + description: *wire_desc + + wire_tunnel: + default: + name: &wire_tunnel Wire Crossing + description: Allows two wires to cross without connecting to each other. + + constant_signal: + default: + name: &constant_signal Constant Signal + description: Emits a constant signal, which can be either a shape, color or boolean (1 or 0). + + lever: + default: + name: &lever Switch + description: Can be toggled to emit a boolean signal (1 or 0) on the wires layer, which can then be used to control components, for example an item filter. + + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means shape, color or boolean "1") + + transistor: + default: + name: &transistor Transistor + description: &transistor_desc Forwards the bottom input if the side input is truthy (a shape, color or "1"). + + mirrored: + name: *transistor + description: *transistor_desc + + filter: + default: + name: &filter Filter + description: Connect a signal to route all matching items to the top and the remaining to the right. Can be controlled with boolean signals too. + + display: + default: + name: &display Display + description: Connect a signal to show it on the display - It can be a shape, color or boolean. + + reader: + default: + name: &reader Belt Reader + description: Allows to measure the average belt throughput. Outputs the last read item on the wires layer (once unlocked). + + analyzer: + default: + name: &analyzer Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape and returns its shape and color. + + comparator: + default: + name: &comparator Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare shapes, colors and booleans. + + virtual_processor: + default: + name: &virtual_processor Virtual Cutter + description: Virtually cuts the shape into two halves. + + rotater: + name: Virtual Rotater + description: Virtually rotates the shape clockwise. + + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the remaining ones to the left. + + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the color on the right input. + + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the wires layer on the regular layer. 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, which cuts shapes in half from top to bottom regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will clog and stall - For this purpose I have given you the trash, which destroys everything you put into it! reward_rotater: title: Rotating @@ -575,19 +742,19 @@ storyRewards: reward_mixer: title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! + desc: The mixer has been unlocked - It mixes two colors using additive blending! 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: Stacker + desc: You can now combine shapes with the stacker! 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! - 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!

+ reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can be used to build bigger factories by splitting and merging items onto multiple belts! reward_tunnel: title: Tunnel - desc: The tunnel has been unlocked - You can now tunnel items through belts and buildings with it! + desc: The tunnel has been unlocked - You can now tunnel items below belts and buildings with it! reward_rotater_ccw: title: CCW Rotating @@ -595,57 +762,127 @@ storyRewards: 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! + desc: >- + You have unlocked the chained extractor! It can forward its resources to other extractors so you can more efficiently extract resources!

+ PS: The old extractor has been replaced in your toolbar now! 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! - reward_splitter_compact: - title: Compact Balancer + reward_merger: + title: Compact Merger desc: >- - You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one belt! + You have unlocked a merger variant of the balancer - It accepts two inputs and merges them into one belt! + + reward_splitter: + title: Compact Splitter + desc: >- + You have unlocked a splitter variant of the balancer - It accepts one input and splits them into two! + + reward_belt_reader: + title: Belt reader + desc: >- + You have now unlocked the belt reader! It allows you to measure the throughput of a belt.

And wait until you unlock wires - then it gets really useful! reward_cutter_quad: - title: Quad Cutting + title: Quad Cutter desc: You have unlocked a variant of the cutter - It allows you to cut shapes in four parts instead of just two! 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! - - 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: You have unlocked a variant of the painter - It works similar to the regular painter but processes two shapes at once, consuming just one color instead of two! 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! - - 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: Storage + desc: >- + You have unlocked the storage building - It allows you to store items up to a given capacity!

+ It priorities the left output, so you can also use it as an overflow gate! 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_rotater_180: + title: Rotater (180°) + desc: You just unlocked the 180 degrees rotater! - It allows you to rotate a shape by 180 degress (Surprise! :D) + + reward_wires_painter_and_levers: + title: >- + Wires & Quad Painter + desc: >- + You just unlocked the Wires Layer: It is a separate layer on top of the regular layer and introduces a lot of new mechanics!

+ For the beginning I unlocked you the Quad Painter - Connect the slots you would like to paint with on the wires layer!

+ To switch to the wires layer, press E.

+ PS: Enable hints in the settings to activate the wires tutorial! + + reward_filter: + title: >- + Item Filter + desc: >- + You unlocked the Item Filter! It will route items either to the top or the right output depending on whether they match the signal from the wires layer or not.

+ You can also pass in a boolean signal (1 or 0) to entirely activate or disable it. + + reward_display: + title: Display + desc: >- + You have unlocked the Display - Connect a signal on the wires layer to visualize it!

+ PS: Did you notice the belt reader and storage output their last read item? Try showing it on a display! + + reward_constant_signal: + title: Constant Signal + desc: >- + You unlocked the constant signal building on the wires layer! This is useful to connect it to item filters for example.

+ The constant signal can emit a shape, color or boolean (1 or 0). + + reward_logic_gates: + title: Logic Gates + desc: >- + You unlocked logic gates! You don't have to be excited about this, but it's actually super cool!

+ With logic gates you can now compute AND, OR, XOR and NOT operations.

+ As a bonus on top I also just gave you a transistor! + + reward_virtual_processing: + title: Virtual Processing + desc: >- + I just gave a whole bunch of new buildings which allow you to simulate the processing of shapes!

+ You can now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

+ - Build an automated machine to create any possible shape requested by the HUB (I recommend to try it!).

+ - Build something cool with wires.

+ - Continue to play regulary.

+ Whatever you choose, remember to have fun! + # Special reward, which is shown when there is no reward actually 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 desc: >- - Congratulations! By the way, more content is planned for the standalone! + Congratulations! + + reward_freeplay: + title: Freeplay + desc: >- + You did it! You unlocked the free-play mode! This means that shapes are now randomly generated!

+ Since the hub will require a throughput from now on, I highly recommend to build a machine which automatically delivers the requested shape!

+ The HUB outputs the requested shape on the wires layer, so all you have to do is to analyze it and automatically configure your factory based on that. + + reward_demo_end: + title: End of Demo + desc: >- + You have reached the end of the demo version! settings: title: Settings categories: - game: Game - app: Application + general: General + userInterface: User Interface + advanced: Advanced + performance: Performance versionBadges: dev: Development @@ -653,6 +890,8 @@ settings: prod: Production buildDate: Built + rangeSliderPercentage: % + labels: uiScale: title: Interface scale @@ -692,7 +931,7 @@ settings: movementSpeed: title: Movement speed description: >- - Changes how fast the view moves when using the keyboard. + Changes how fast the view moves when using the keyboard or moving the mouse to the screen borders. speeds: super_slow: Super slow slow: Slow @@ -726,6 +965,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: >- @@ -735,14 +984,14 @@ 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. + This determines how many game ticks happen per second. In general, a higher tick rate means better precision but also worse performance. On lower tickrates, the throughput may not be exact. alwaysMultiplace: title: Multiplace description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. + If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to constantly holding SHIFT. offerHints: title: Hints & Tutorials @@ -772,7 +1021,58 @@ settings: disableCutDeleteWarnings: title: Disable Cut/Delete Warnings description: >- - Disables the warning dialogs brought up when cutting/deleting more than 100 entities. + Disables the warning dialogues 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: Select extractor on resource patch + description: >- + Enabled by default, selects the extractor if you use the pipette when hovering a resource patch. + + simplifiedBelts: + title: Simplified Belts (Ugly) + description: >- + Does not render belt items except when hovering the belt to save performance. I do not recommend to play with this setting if you do not absolutely need the performance. + + enableMousePan: + title: Screen Edge Panning + description: >- + Allows panning the map by moving the cursor to the edges of the screen. The scroll speed depends on the Movement Speed setting. + + zoomToCursor: + title: Zoom towards Cursor + description: >- + If activated the zoom will happen in the direction of your mouse position, otherwise in the middle of the screen. + + mapResourcesScale: + title: Map Resources Size + description: >- + Controls the size of the shapes on the map overview (when zooming out). middleMousePan: title: Pan camera with middle click @@ -789,7 +1089,7 @@ keybindings: hint: >- Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - resetKeybindings: Reset Keybindings + resetKeybindings: Reset categoryLabels: general: Application @@ -822,19 +1122,33 @@ 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 + balancer: *balancer 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 + storage: *storage wire: *wire + constant_signal: *constant_signal + logic_gate: Logic Gate + lever: *lever + filter: *filter + wire_tunnel: *wire_tunnel + display: *display + reader: *reader + virtual_processor: *virtual_processor + transistor: *transistor + analyzer: *analyzer + comparator: *comparator + item_producer: Item Producer (Sandbox) + # --- pipette: Pipette rotateWhilePlacing: Rotate @@ -847,7 +1161,8 @@ keybindings: lockBeltDirection: Enable belt planner switchDirectionLockSide: >- Planner: Switch side - + copyWireValue: >- + Wires: Copy value below cursor massSelectStart: Hold and drag to start massSelectSelectMultiple: Select multiple areas massSelectCopy: Copy area @@ -862,13 +1177,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 @@ -882,3 +1197,60 @@ demo: exportingBase: Exporting whole Base as Image settingNotAvailable: Not available in the demo. + +tips: + - The hub will accept any input, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a mess! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - The storage buffer prioritises the left output. + - Invest time to build repeatable designs - it's worth it! + - Holding SHIFT lets you place multiple buildings in one click. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a mess! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 or 26 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to reuse factories later in the game. Build your factories to be reusable. + - Sometimes, you can find a needed shape in the map without creating it with stackers. + - Full windmills/pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look at the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all three primary colors to make white! + - You have an infinite map. Don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise, starting from the top right. + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the settings page. + - This game has a lot of settings, be sure to check them out! + - Your hub marker has a small compass that shows which direction it is in! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-es.yaml b/translations/base-es.yaml index 88156566..8354c684 100644 --- a/translations/base-es.yaml +++ b/translations/base-es.yaml @@ -1,112 +1,64 @@ -# -# 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 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. + 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. + discordLinkShort: Discord oficial + intro: >- + Shapez.io es un juego tranquilo en el que tienes que construir fábricas + para la producción automatizada de formas geométricas. - # 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) - # - Please keep the markup (Stuff like [b], [list] etc) in the same format - longText: >- - [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] + A medida que el nivel aumenta, las formas se vuelven más y más complejas, y tienes que extenderte en un mapa infinito. - 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. + Y por si fuera poco, también tienes que producir exponencialmente más para satisfacer las demandas - ¡lo único que ayuda es escalar! - 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]! + Mientras que sólo procesas formas al principio, tienes que colorearlas después - ¡para ello tienes que extraer y mezclar los colores! - Después necesitarás mezclar colores para pintar las figuras - Combina recursos de colores rojo, verde y azul para producir diferentes colores y pintar figuras para satisfacer la demanda. - - Este juego cuenta con 18 niveles (¡Que te mantendrán ocupado durante horas!) pero estoy constantemente añadiendo nuevo contenido - ¡Hay mucho planeado! - - Comprando el juego tendrás acceso a la versión completa con contenido adicional, además del contenido en desarrollo. - - [b]Ventajas del juego completo[/b] - - [list] - [*] Modo oscuro - [*] Puntos de referencia ilimitados - [*] Partidas guardadas ilimitadas - [*] Ajustes adicionales - [*] Próximamente: ¡Cables y Energía! Aproximadamente para finales de julio de 2020. - [*] Próximamente: Más niveles - [*] Ayúdame a seguir desarrollando shapez.io ❤️ - [/list] - - [b]Futuras actualizaciones[/b] - - ¡Estoy actualizando el juego muy a menudo e intentando subir actualizaciones al menos una vez a la semana! - - [list] - [*] Diferentes mapas y desafíos (por ejemplo: mapas con obstáculos) - [*] Puzles (Entrega la forma requerida con una zona o conjunto de edificios restringidos) - [*] Modo historia en el que los edificios tengan un coste - [*] Generador de mapas configurable (Configurar recursos, forma, tamaño, densidad, semilla y más) - [*] Más tipos de figuras - [*] Mejoras de rendimiento (¡Aunque el juego ya funciona muy bien!) - [*] ¡Y mucho más! - [/list] - - [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! - - [b]Enlaces[/b] - - [list] - [*] [url=https://discord.com/invite/HN7EVzV]Discord oficial[/url] - [*] [url=https://trello.com/b/ISQncpJP/shapezio]Hoja de ruta[/url] - [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Código fuente (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Ayuda a traducir[/url] - [/list] + Comprando el juego en Steam tienes acceso a la versión completa, ¡pero también puedes jugar una demo en shapez.io primero y decidir después! + title_advantages: Ventajas del juego + advantages: + - 12 nuevos niveles de un total de 26 niveles + - 18 nuevos edificios ¡para una fábrica totalmente automatizada! + - 20 Upgrade Tiers for many hours of fun! + - Wires Update for an entirely new dimension! + - Modo oscuro! + - Partidad guardadas ilimitadas + - Marcadores ilimitados + - Me apoyarás! ❤️ + title_future: Contenido futuro + planned: + - Librería de planos (Exclusivo de Standalone) + - Logros de Steam + - Modo Puzzle + - Minimapa + - Mods + - Modo libre + - ... y mucho más! + title_open_source: Este juego es de código abierto! + title_links: Links + links: + discord: Discord oficial + roadmap: Roadmap + subreddit: Subreddit + source_code: Código fuente (GitHub) + translate: Ayuda a traducír + text_open_source: >- + Cualquiera puede contribuír, Estoy activamete involucrado en la comunidad y + trato de revisar todas las sugerencias además de tomar en cuenta los consejos + siempre que sea posible. + Asegurate de revisar mi página de Trello donde podrás encontrar el Roadmap! global: loading: Cargando error: Error - - # 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" + thousandsDivider: . 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: inf - time: - # Used for formatting past time dates oneSecondAgo: hace un segundo xSecondsAgo: hace segundos oneMinuteAgo: hace un minuto @@ -115,14 +67,10 @@ global: xHoursAgo: hace horas oneDayAgo: hace un día xDaysAgo: hace días - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: min s hoursAndMinutesShort: h min - xMinutes: minutos - keys: tab: TAB control: CTRL @@ -130,13 +78,9 @@ global: escape: ESC shift: SHIFT space: ESPACIO - demoBanners: - # This is the "advertisement" shown in the main menu and other various places title: Versión de prueba - intro: >- - ¡Obtén el juego completo para desbloquear todas las características! - + intro: ¡Obtén el juego completo para desbloquear todas las características! mainMenu: play: Jugar continue: Continuar @@ -148,14 +92,11 @@ mainMenu: discordLink: Servidor de Discord oficial helpTranslate: ¡Ayuda a traducirlo! madeBy: Desarrollado por - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - ¡Lo siento, pero el juego funcionará despacio en tu navegador! Obtén el juego completo o descarga Chrome para la experiencia completa. - + browserWarning: ¡Lo siento, pero el juego funcionará despacio en tu navegador! + Obtén el juego completo o descarga Chrome para la experiencia completa. savegameLevel: Nivel savegameLevelUnknown: Nivel desconocido - + savegameUnnamed: Sin nombre dialogs: buttons: ok: OK @@ -169,112 +110,105 @@ dialogs: viewUpdate: Ver actualización showUpgrades: Ver mejoras showKeybindings: Ver atajos de teclado - importSavegameError: title: Error de importación - text: >- - Fallo al importar tu partida guardada: - + text: "Fallo al importar tu partida guardada:" importSavegameSuccess: title: Partida guardada importada - text: >- - Tu partida guardada ha sido importada con éxito. - + text: Tu partida guardada ha sido importada con éxito. gameLoadFailure: title: Error de carga - text: >- - No se ha podido cargar la partida guardada: - + text: "No se ha podido cargar la partida guardada:" confirmSavegameDelete: title: Confirmar borrado - text: >- - ¿Seguro que quieres borrar la partida? - + text: Estás seguro de querér borrar el siguiente guardado?

+ '' que está en el nivel

Esto no se puede deshacer! savegameDeletionError: title: Fallo al borrar - text: >- - Fallo al borrar la partida guardada: - + text: "Fallo al borrar la partida guardada:" restartRequired: title: Reinicio requerido - text: >- - Tienes que reinciar la partida para aplicar los cambios. - + text: Tienes que reinciar la partida para aplicar los cambios. editKeybinding: title: Cambiar atajos de teclado - desc: Pulsa la tecla o botón del ratón que quieras asignar, o escape para cancelar. - + desc: Pulsa la tecla o botón del ratón que quieras asignar, o escape para + cancelar. resetKeybindingsConfirmation: title: Reiniciar atajos de teclado - desc: Esto devolverá todos los atajos de teclado a los valores por defecto. Por favor, confirma. - + desc: Esto devolverá todos los atajos de teclado a los valores por defecto. Por + favor, confirma. keybindingsResetOk: title: Atajos de teclado reiniciados desc: ¡Los atajos de teclado han sito reiniciados a los valores por defecto! - featureRestriction: title: Versión de prueba - desc: Has intentado acceder a una característica () que no está disponible en la versión de prueba. ¡Considera obtener el juego completo para la experiencia completa! - + desc: Has intentado acceder a una característica () que no está + disponible en la versión de prueba. ¡Considera obtener el juego + completo para la experiencia completa! 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! - + 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: >- - Estos son los cambios desde la última vez que jugaste: - + desc: "Estos son los cambios desde la última vez que jugaste:" upgradesIntroduction: title: Desbloquear mejoras - desc: >- - Todas las figuras se pueden usar para desbloquear mejoras - ¡No destruyas tus fábricas anteriores! - La pestaña de mejoras está en la esquina superior derecha de la pantalla. - + desc: Todas las figuras se pueden usar para desbloquear mejoras - ¡No + destruyas tus fábricas anteriores! La pestaña de mejoras + está en la esquina superior derecha de la pantalla. massDeleteConfirm: title: Confirmar borrado - desc: >- - ¡Estás borrando muchos edificios ( para ser exactos)! ¿Estás seguro de querer hacer esto? - + desc: ¡Estás borrando muchos edificios ( para ser exactos)! ¿Estás seguro + de querer hacer esto? massCutConfirm: title: Confirmar corte - desc: >- - ¡Estás cortando muchos edificios ( para ser exactos)! ¿Estas seguro de que quieres hacer esto? - + desc: ¡Estás cortando muchos edificios ( para ser exactos)! ¿Estas seguro + de que quieres hacer esto? massCutInsufficientConfirm: title: Confirm cut - desc: >- - ¡No puedes permitirte pegar este área! ¿Estás seguro de que quieres cortarlo? - + desc: ¡No puedes permitirte pegar este área! ¿Estás seguro de que quieres + cortarlo? blueprintsNotUnlocked: title: No desbloqueado todavía - desc: >- - ¡Completa el nivel 12 para desbloquear los Planos! - + desc: ¡Completa el nivel 12 para desbloquear los Planos! keybindingsIntroduction: title: Atajos de teclado útiles - desc: >- - El juego tiene muchos atajos de teclado que facilitan la tarea de construir grandes fábricas. - ¡Aquí hay algunos, pero asegúrate de comprobar los atajos de teclado!

- CTRL + Arrastrar: Selecciona un área.
- SHIFT: Mánten pulsado para colocar varias veces un edificio.
- ALT: Invierte la orientación de las cintas transportadoras colocadas.
- + desc: "El juego tiene muchos atajos de teclado que facilitan la tarea de + construir grandes fábricas. ¡Aquí hay algunos, pero asegúrate de + comprobar los atajos de teclado!

CTRL + Arrastrar: Selecciona un área.
+ SHIFT: Mánten pulsado para colocar + varias veces un edificio.
ALT: + Invierte la orientación de las cintas transportadoras + colocadas.
" createMarker: title: Nuevo marcador titleEdit: Editar marcador - desc: Dale un nombre significativo, también puedes agregarle una clave de una forma (La cual puedes generar aquí) - + desc: Dale un nombre significativo, tambien puedes incluir la clave de una forma (La cual puedes generar aquí) markerDemoLimit: - desc: Solo puedes crear dos marcadores en la versión de prueba. ¡Obtén el juego completo para marcadores ilimitados! - + desc: Solo puedes crear dos marcadores en la versión de prueba. ¡Obtén el juego + completo para marcadores ilimitados! exportScreenshotWarning: title: Exportar captura de pantalla - desc: Has solicitado una captura de pantalla de tu base. Por favor, ten en cuenta que puede tardar bastante en las bases grandes. ¡E incluso crashear tu juego! - + desc: Has solicitado una captura de pantalla de tu base. Por favor, ten en + cuenta que puede tardar bastante en las bases grandes. ¡E incluso + crashear tu juego! + editSignal: + title: Establecer señal + descItems: "Elige un item pre-definido:" + descShortKey: ... o escribe la calve de una forma (La cual + puedes generar aquí) + renameSavegame: + title: Renombrar archivo de guardado + desc: Aquí puedes cambiarle el nombre a tu archivo de guardado. + tutorialVideoAvailable: + title: Tutorial disponible + desc: ¡Hay un video tutorial disponible para este nivel! ¿Te gustaría verlo? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Disponible + desc: Hay un video tutorial disponible para este nivel, pero solo está disponible en inglés ¿Te gustaría verlo? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Mover selectBuildings: Seleccionar área @@ -293,10 +227,8 @@ ingame: cutSelection: Cortar copySelection: Copiar clearSelection: Limpiar selección - pipette: Pipette + pipette: Cuentagotas switchLayers: Cambiar capas - - # Names of the colors, used for the color blind mode colors: red: Rojo green: Verde @@ -307,18 +239,9 @@ ingame: white: Blanco black: Negro uncolored: Gris - - # 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 para rotar por las distintas variantes. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Tecla: - + hotkeyLabel: "Tecla: " infoTexts: speed: Velocidad range: Rango @@ -326,36 +249,21 @@ ingame: oneItemPerSecond: 1 elemento / segundo itemsPerSecond: elementos / s itemsPerSecondDouble: (x2) - tiles: casillas - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Nivel completed: Completado unlockText: ¡Has desbloqueado ! buttonNextLevel: Siguiente nivel - - # Notifications on the lower right notifications: newUpgrade: ¡Una nueva mejora está disponible! gameSaved: Se ha guardado la partida. - - # The "Upgrades" window + freeplayLevelComplete: Level has been completed! shop: title: Mejoras buttonUnlock: Mejorar - - # Gets replaced to e.g. "Tier IX" tier: Nivel - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: NIVEL MÁXIMO (Velocidad x) - - # The "Statistics" window statistics: title: Estadísticas dataSources: @@ -364,62 +272,112 @@ ingame: description: Muestra la cantidad de figuras guardadas en tu edificio central. produced: title: Producido - description: Muestra todas las figuras que tu fábrica al completo produce, incluyendo productos intermedios. + description: Muestra todas las figuras que tu fábrica al completo produce, + incluyendo productos intermedios. delivered: title: Entregados description: Muestra las figuras que son entregadas a tu edificio central. noShapesProduced: Todavía no se han producido figuras. - - # Displays the shapes per minute, e.g. '523 / min' - shapesPerMinute: / min - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Tiempo de juego - buildingsPlaced: Edificios beltsPlaced: Cintas transportadoras - - buttons: - continue: Continuar - settings: Opciones - menu: Volver al menú principal - - # Bottom left tutorial hints tutorialHints: title: ¿Necesitas ayuda? showHint: Mostrar pista hideHint: Cerrar - - # When placing a blueprint blueprintPlacer: cost: Coste - - # Map markers waypoints: waypoints: Marcadores hub: Edificio Central - description: Click izquierdo sobre un marcador para ir ahí, click derecho para borrarlo.

Pulsa para crear un marcador de la vista actual o click derecho para crear un marcador en la posición seleccionada. + description: Click izquierdo sobre un marcador para ir ahí, click derecho para + borrarlo.

Pulsa para crear un marcador de la + vista actual o click derecho para crear un marcador + en la posición seleccionada. creationSuccessNotification: El marcador ha sido creado. - - # Shape viewer shapeViewer: title: Capas empty: Vacío copyKey: Copiar - - # Interactive tutorial interactiveTutorial: title: Tutorial hints: - 1_1_extractor: ¡Coloca un extractor encima de un círculo para extraerlo! - 1_2_conveyor: >- - ¡Conecta el extractor con una cinta transportadora a tu edificio central!

Pista: ¡Pulsa y arrastra la cinta transportadora con el ratón! - - 1_3_expand: >- - ¡Esto NO es un "juego de esperar"! Construye más extractores y cintas transportadoras para completar el objetivo más rápido.

Pista: Mantén pulsado SHIFT para colocar varios extractores y usa R para rotarlos. - -# All shop upgrades + 1_1_extractor: ¡Coloca un extractor encima de un + círculo para extraerlo! + 1_2_conveyor: "¡Conecta el extractor con una cinta + transportadora a tu edificio central!

Pista: + ¡Pulsa y arrastra la cinta transportadora con + el ratón!" + 1_3_expand: '¡Esto NO es un "juego de esperar"! Construye más + extractores y cintas transportadoras para completar el objetivo + más rápido.

Pista: Mantén pulsado SHIFT + para colocar varios extractores y usa R para + rotarlos.' + 2_1_place_cutter: "¡Ahora pon un Cortador para dividir los circulos en dos + mitades!

PD: El cortador siempre corta de de arriba a + abajo independientemente de su orientación." + 2_2_place_trash: ¡El cortador se puede tabar y atorar!

Usa un + basurero para deshacerse de la actualmente (!) no + necesitada basura. + 2_3_more_cutters: "¡Buen trabajo! ¡Ahora pon 2 cortadores más para acelerar + este lento proceso!

PD: Usa las teclas 0-9 + para acceder a los edificios más rápido!" + 3_1_rectangles: "¡Ahora consigamos unos rectangulos! construye 4 + extractores y conectalos a el edificio central.

PD: + Manten apretado SHIFT mientrás pones cintas transportadoras para activar + el planeador de cintas!" + 21_1_place_quad_painter: ¡Pon el pintaor cuadruple y consigue unos + circulos, el color blanco y el color + rojo! + 21_2_switch_to_wires: ¡Cambia a la capa de cables apretando la técla + E!

Luego conecta las cuatro + entradas de el pintador con cables! + 21_3_place_button: ¡Genial! ¡Ahora pon un Interruptor y conectalo + con cables! + 21_4_press_button: "Presioa el interruptor para hacer que emita una señal + verdadera lo cual activa el piintador.

PD: ¡No necesitas + conectar todas las entradas! Intenta conectando solo dos." + connectedMiners: + one_miner: 1 Minero + n_miners: Mineros + limited_items: Limitado a + watermark: + title: Versión demo + desc: Presiona aquí para ver que tiene la versión de Steam! + get_on_steam: Consiguelo en Steam + standaloneAdvantages: + title: ¡Consigue la versión completa! + no_thanks: ¡No grácias! + points: + levels: + title: 12 nuevos niveles + desc: ¡Para un total de 26 niveles! + buildings: + title: 18 nuevos edificios + desc: ¡Automatiza completamente tu fabrica! + savegames: + title: Archivos de guardado infinitos + desc: ¡Tantos como desees! + upgrades: + title: 20 niveles de mejoras + desc: ¡Esta demo solo tiene 5! + markers: + title: Marcadores infinitos + desc: ¡Nunca te pierdas en tu propia fabrica! + wires: + title: Cables + desc: ¡Una dimension completamente nueva! + darkmode: + title: Modo oscuro + desc: ¡Deja de lastimar tus ojos! + support: + title: Apoyame + desc: ¡Desarrollo este juego en mi tiempo libre! shopUpgrades: belt: name: Cintas transportadoras, Distribuidores y Túneles @@ -433,241 +391,392 @@ shopUpgrades: painting: name: Mezclado y Pintado description: Velocidad x → x - -# Buildings and their name / description buildings: hub: deliver: Entregar toUnlock: para desbloquear levelShortcut: LVL - + endOfDemo: End of Demo belt: default: - name: &belt Cinta Transportadora - description: Transporta elementos, mantén pulsado y arrastra para colocar varios. - + name: Cinta Transportadora + description: Transporta elementos, mantén pulsado y arrastra para colocar + varios. wire: default: - name: &wire Cable + name: Cable description: Te permite transportar energía - - miner: # Internal name for the Extractor + second: + name: Cable + description: Transfiere señales, que pueden ser items, colores o valores booleanos (1 / 0). + Cables de diferentes colores no se conectan. + miner: default: - name: &miner Extractor + name: Extractor description: Colócalo sobre una figura o un color para extraerlo. - chainable: name: Extractor (Encadenado) - description: Colócalo sobre una figura o un color para extraerlo. Puede ser encadenado. - - underground_belt: # Internal name for the Tunnel + description: Colócalo sobre una figura o un color para extraerlo. Puede ser + encadenado. + underground_belt: default: - name: &underground_belt Túnel - description: Permite contruir un túnel para transportar los elementos por debajo de edificios y otras cintas transportadoras. - + name: Túnel + description: Permite contruir un túnel para transportar los elementos por debajo + de edificios y otras cintas transportadoras. tier2: name: Túnel nivel II - description: Permite contruir un túnel para transportar los elementos por debajo de edificios y otras cintas transportadoras. - - splitter: # Internal name for the Balancer - default: - name: &splitter Balanceador - description: Multifuncional - Distribuye equitativamente todas las entradas a todas las salidas. - - compact: - name: Fusionador (compacto) - description: Junta dos cintas transportadoras en una. - - compact-inverse: - name: Fusionador (compacto) - description: Junta dos cintas transportadoras en una. - + description: Permite contruir un túnel para transportar los elementos por debajo + de edificios y otras cintas transportadoras. cutter: default: - name: &cutter Cortador - description: Corta las figuras de arriba abajo y saca ambas mitades. ¡Si solo usas una parte, asegúrate de destruir la otra parte o se parará! + name: Cortador + description: Corta las figuras de arriba abajo y saca ambas mitades. + ¡Si solo usas una parte, asegúrate de destruir la otra parte o + se parará! quad: name: Cortador (Cuádruple) - description: Corta figuras en cuatro partes. ¡Si solo usas una parte, asegúrate de destruir las otras partes o se parará! - - advanced_processor: - default: - name: &advanced_processor Inversor de color - description: Invierte un color o una figura - + description: Corta figuras en cuatro partes. ¡Si solo usas una parte, + asegúrate de destruir las otras partes o se parará! rotater: default: - name: &rotater Rotador + name: Rotador description: Rota las figuras en sentido horario 90 grados. ccw: name: Rotador (Inverso) description: Rota las figuras en sentido antihorario 90 grados. - + rotate180: + name: Rotador (180) + description: Rota formas en 180 grados. stacker: default: - name: &stacker Apilador - description: Apila ambos elementos. Si no se pueden unir, el elemento de la derecha se coloca encima del elemento de la izquierda. - + name: Apilador + description: Apila ambos elementos. Si no se pueden unir, el elemento de la + derecha se coloca encima del elemento de la izquierda. mixer: default: - name: &mixer Mezclador de colores + name: Mezclador de colores description: Mezcla dos colores usando mezcla aditiva. - painter: default: - name: &painter Pintor - description: &painter_desc Colorea la figura completa de la entrada izquierda con el color de la entrada de arriba. - + name: Pintor + description: Colorea la figura completa de la entrada izquierda con el color de + la entrada de arriba. mirrored: - name: *painter - description: *painter_desc - + name: Pintor + description: Colorea la figura completa de la entrada izquierda con el color de + la entrada de arriba. double: name: Pintor (Doble) - description: Colorea las figuras de las entradas de la izquierda con el color de la entrada de arriba. + description: Colorea las figuras de las entradas de la izquierda con el color de + la entrada de arriba. quad: name: Pintor (Cuádruple) - description: Permite colorear cada cuadrante de una figura con un color distinto. - + description: Te permite colorear cada cuadrante de la forma individualemte. ¡Solo las + ranuras con una señal verdadera en la capa de cables + seran pintadas! trash: default: - name: &trash Basurero - description: Acepta entradas desde todos los lados y los destruye. Para siempre. - - storage: - name: Almacenamiento. - description: Guarda el exceso de elementos, hasta cierta cantidad. Puede ser usado para controlar el desborde de elementos. - - energy_generator: - deliver: Entregar - - # This will be shown before the amount, so for example 'For 123 Energy' - toGenerateEnergy: Para - + name: Basurero + description: Acepta formas desde todos los lados y las destruye. Para siempre. + balancer: default: - name: &energy_generator Generador de energía - description: Genera energía consumiendo figuras. - - wire_crossings: - default: - name: &wire_crossings Divisor de cables - description: Divide un cable en dos - + name: Balanceador + description: Multifuncional - Distribuye igualmente todas las entradas en las salidas. merger: - name: Fusionador de cables - description: Fusiona dos cables en uno - + name: Unión (compacta) + description: Junta dos cintas transportadoras en una. + merger-inverse: + name: Unión (compacta) + description: Junta dos cintas transportadoras en una. + splitter: + name: Separador (compacto) + description: Separa una cinta trasportadora en dos. + splitter-inverse: + name: Separador (compacto) + description: Separa una cinta trasportadora en dos. + storage: + default: + name: Almacén + description: Guarda items en exceso, hasta una dada capacidad. Prioritiza la salida + de la izquierda y puede ser usada como una puerta de desbordamiento. + wire_tunnel: + default: + name: Cruze de cables + description: Permite que dos cables se cruzen sin conectarse. + constant_signal: + default: + name: Señal costante + description: Emite una señal constante, que puede ser una forma, color o valor booleano (1 / 0). + lever: + default: + name: Interruptor + description: Puede ser activado para emitir una señal booleana (1 / 0) en la capa de cables, + la cual puede ser usada por ejemplo para un filtro de items. + logic_gate: + default: + name: Puerta AND + description: Emite el valor booleano "1" si ambas entradas son verdaderas. (Verdadeas significa una forma, + color o valor booleano "1") + not: + name: Puerta NOT + description: Emite el valor booleano "1" si ambas entradas no son verdaderas. (Verdadeas significa una forma, + color o valor booleano "1") + xor: + name: Puerta XOR + description: Emite el valor booleano "1" si una de las entradas es verdadera, pero no si ambas lo son. + (Verdadeas significa una forma, + color o valor booleano "1") + or: + name: Puerta OR + description: Emite el valor booleano "1" Si una de las entradas es verdadera. (Verdadeas significa una forma, + color o valor booleano "1") + transistor: + default: + name: Transistor + description: Envia la señal de abajo si la señal del costado es verdadera (Verdadeas significa una forma, + color o valor booleano "1"). + mirrored: + name: Transistor + description: Envia la señal de abajo si la señal del costado es verdadera (Verdadeas significa una forma, + color o valor booleano "1"). + filter: + default: + name: Filtro + description: Conecta una señal para enviar todas las que coincidan hacia arriba y las demás + hacia la derecha. También puede ser controlada por señales booleanas. + display: + default: + name: Monitor + description: Conecta una señal para mostrarla en el monitor - Puede ser una forma, + color o valor booleano. + reader: + default: + name: Lector de cinta + description: Te permite medir la cantidad media de items que pasan por la cinta. Emite el último + item leído en la capa de cables (una vez desbloquada). + analyzer: + default: + name: Analizador de formas + description: analiza el cuadrante de arriba a la derecha de la capa más baja de la forma + y devuelve su figura y color. + comparator: + default: + name: Comparador + description: Devuelve el valor booleano "1" Si ambas señales son exactamente iguales. Puede comparar + formas, items y valores booleanos. + virtual_processor: + default: + name: Cortador virtual + description: Corta virtualmente la forma en dos. + rotater: + name: Rotador virtual + description: Rota virtualmente la forma, tanto en sentido del horario como sentido anti-horario. + unstacker: + name: Desapilador virtual + description: Extrae virtualmente la capa más alta en la salida a la derecha y + las que quedan en la izquierda. + stacker: + name: Apilador virtual + description: Apila virtualmente la forma de la derecha en la de la izquierda. + painter: + name: Pintor virtual + description: Pinta virtualmente la forma de la entrada de abajo con la forma de + la entrada de la derecha. + item_producer: + default: + name: Productor de items + description: Solo disponible en modo libre, envía la señal recivida de la + capa de cables en la capa regular. storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Cortador de figuras - desc: ¡Acabas de desbloquear el cortador - corta las figuras por la mitad de arriba abajo sin importar su orientación!

Asegúrate de deshacerte de lo que no vayas a usar o se parará - ¡Para eso te he dado un basurero, que destruye todo lo que le pongas! - + desc: ¡Acabas de desbloquear el cortador, el cual corta formas por la mitad + de arriba a abajo independientemente de su + orientacion!

Asegurate de deshacerte de la basura, o + sino se trabará y parará - Por este proposite + Te he dado el basurero, el cual destruye + todo lo que pongas dentro de él! reward_rotater: title: Rotador - desc: ¡El rotador se ha desbloqueado! Rota figuras en sentido horario 90 grados. - + desc: ¡El rotador se ha desbloqueado! Rota figuras en sentido + horario 90 grados. reward_painter: title: Pintor - desc: >- - El pintor se ha desbloqueado - ¡Extrae vetas de color (igual que lo haces con las figuras) y combínalas con una figura en el pintor para colorearlas!

PD: Si tienes alguna forma de daltonismo, ¡hay un modo para daltónicos en los ajustes! - + desc: "El pintor se ha desbloqueado - ¡Extrae vetas de color + (igual que lo haces con las figuras) y combínalas con una figura en + el pintor para colorearlas!

PD: Si tienes alguna forma de + daltonismo, ¡hay un modo para daltónicos en los + ajustes!" reward_mixer: title: Mezclador de color - desc: El mezclador se ha desbloqueado - ¡Combina dos colores usando mezcla aditiva con este edificio! - + desc: El mezclador se ha desbloqueado - ¡Combina dos colores + usando mezcla aditiva con este edificio! reward_stacker: title: Apilador - desc: ¡Ahora puedes combinar figuras con el apilador! Ambas entradas son combinadas, y si pueden ser colocadas una junto a la otra serán fusionadas. ¡Si no, la entrada derecha será apilada encima de la entrada izquierda! - + desc: ¡Ahora puedes combinar figuras con el apilador! Ambas + entradas son combinadas, y si pueden ser colocadas una junto a la + otra serán fusionadas. ¡Si no, la entrada derecha + será apilada encima de la entrada izquierda! reward_splitter: title: Separador/Fusionador - desc: El balanceador multiusos se ha desbloqueado - ¡Se puede usar para construir fábricas más grandes separando y uniendo elementos en varias cintas transportadoras!

- + desc: Has desbloqueado el separador , una variante de el + balanceador - Acepta una entrada y la separa + en dos! reward_tunnel: title: Túnel - desc: El túnel se ha desbloqueado - ¡Ahora puedes transportar elementos por debajo de edificios u otras cintas! - + desc: El túnel se ha desbloqueado - ¡Ahora puedes transportar + elementos por debajo de edificios u otras cintas! reward_rotater_ccw: title: Rotador inverso - desc: Has desbloqueado una variante del rotador - ¡Te permite rotar en sentido antihorario! Para construirlo selecciona el rotador y pulsa 'T' para ciclar por sus variantes - + desc: Has desbloqueado una variante del rotador - ¡Te permite + rotar en sentido antihorario! Para construirlo selecciona el rotador + y pulsa 'T' para ciclar por sus variantes reward_miner_chainable: title: Extractor en cadena - desc: ¡Has desbloqueado el extractor en cadena! Puede enviar los recursos a otros extractores, extrayendo recursos más eficientemente. - + desc: "¡Has desbloqueado el extractor en cadena! ¡Este puede + enviar sus recursos a otros extractores así puedes + extraer recursos más eficientemente!

PD: ¡El extractor + viejo ha sido reemplazado en tu barra de herramientas!" reward_underground_belt_tier_2: title: Túnel nivel II - desc: Has desbloqueado una nueva variante del túnel - ¡Tiene un mayor rango, y ahora puedes mezclar los distintos tipos de túneles! - - 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 nueva variante del túnel - ¡Tiene un + mayor rango, y ahora puedes mezclar los distintos + tipos de túneles! reward_cutter_quad: title: Cortador cuádruple - desc: Has desbloqueado una variante del cortador - ¡Permite cortar figuras en cuatro partes en vez de solo dos! - + desc: Has desbloqueado una variante del cortador - ¡Permite + cortar figuras en cuatro partes en vez de solo dos! reward_painter_double: title: Pintor doble - desc: Has desbloqueado una variante del pintor - ¡Funciona como un pintor normal pero procesa dos figuras a la vez, consumiendo solo un color en vez de dos! - - reward_painter_quad: - title: Pintor cuádruple - desc: Has desbloqueado una variante del pintor - ¡Permite pintar cada parte de una figura individualmente! - + desc: Has desbloqueado una variante del pintor - ¡Funciona como + un pintor normal pero procesa dos figuras a la vez, + consumiendo solo un color en vez de dos! reward_storage: title: Almacenamiento intermedio - desc: Has desbloqueado una variante del basurero - ¡Permite almacenar elementos hasta una cierta capacidad! - + desc: Haz desbloquado el edificio de almacenamiento - ¡Te permite + guardar items hasta una capacidad determinada!

Prioriza la salida + de la izquierda, por lo que tambien puedes suarlo como una puerta de desbordamiento! reward_freeplay: title: Juego libre - desc: ¡Lo has conseguido! ¡Has desbloqueado el Juego Libre! ¡Esto significa que ahora las figuras se generan aleatoriamente! (¡No te preocupes, hay más contenido planeado para el juego completo!) - + desc: ¡Lo hiciste! Haz desbloqueado el modo de juego libre! ¡Esto significa + que las formas ahora son aleatoriamente generadas!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. reward_blueprints: title: Planos - desc: ¡Ahora puedes copiar y pegar partes de tu fábrica! Selecciona un área (mantén pulsado CTRL, después arrastra con el ratón), y pulsa 'C' para copiarlo.

Pegarlo no es gratis, necesitas producir figuras de planos para poder permitírtelo (Esas que acabas de entregar). - - # Special reward, which is shown when there is no reward actually + desc: ¡Ahora puedes copiar y pegar partes de tu fábrica! + Selecciona un área (mantén pulsado CTRL, después arrastra con el + ratón), y pulsa 'C' para copiarlo.

Pegarlo no es + gratis, necesitas producir figuras de + planos para poder permitírtelo (Esas que acabas de + entregar). no_reward: title: Siguiente nivel - desc: >- - Este nivel no da recompensa, ¡pero el siguiente sí!

PD: Es mejor que no destruyas la fábrica que tienes - ¡Necesitarás todas esas figuras más adelante para desbloquear mejoras! - + desc: "Este nivel no da recompensa, ¡pero el siguiente sí!

PD: Es mejor + que no destruyas la fábrica que tienes - ¡Necesitarás + todas esas figuras más adelante para + desbloquear mejoras!" no_reward_freeplay: title: Siguiente nivel - desc: >- - ¡Felicidades! ¡Por cierto, hay más contenido planeado para el juego completo! - + desc: ¡Felicidades! ¡Por cierto, hay más contenido planeado para el juego + completo! + reward_balancer: + title: Balanceador + desc: El balanceador multifuncional ha sido desbloqueado - ¡Este puede + ser usado para construir fabricas más grandes al separar y mezclar + items hacia múltiples cintas! + reward_merger: + title: Unión compacta + desc: Has desbloqueado la variante unión de el + balanceador - ¡Acepta dos entradas y las une en + una sola cinta! + reward_belt_reader: + title: Lector de cinta + desc: ¡Has desbloqueado el lector de cinta! Este te permite + medir la cantidad de items que pasan por esta.
rotador de 180 grados! - Te permite + rotar una forma en 180 grados (¡Sorpresa! :D) + reward_display: + title: Monitor + desc: "Has desbloqueado el Monitor - ¡Conecta una señal dentro de + la capa de cables para visualizarla!

PD: ¿Te has dado cuenta que el lector + de cinta y el almacenador emiten su último item leído? ¡Trata de conectarlo + al monitor!" + reward_constant_signal: + title: Señal constante + desc: ¡Has desbloqueado la señal constante en la capa de + cables! Esto es muy útil para conectar a el filtro de items + por ejemplo.

La señal constante puede emitir + formas, colores o + valores booleanos (1 / 0). + reward_logic_gates: + title: Puertas lógicas + desc: ¡Has desbloqueado las puertas lógicas! No es necesario que te emociones + por esto ¡Pero en realidad es super geniall!

Con estas puertas + ahora puedes computar operaciones AND, OR, XOR y NOT.

Como bonus + también te he dado el transistor! + reward_virtual_processing: + title: Procesamiento virtual + desc: ¡Acabo de darte un monton de nuevos edificios los cuales te permiten + simular el procesamiento de las formas!

¡Ahora puedes + simular un cortador, rotador, apilador y más dentro de la capa de cables! + Con esto ahora tienes tres opciones para continuar el juego:

- + Construir una maquina automatizada para crear cualquier + forma que te pida el HUB (¡Te recomiendo que lo intentes!).

- Construir + algo genial con los cables.

- Continuar jugando de + la manera regular.

¡Cualquiera que eligas, recuerda divertirte! + reward_wires_painter_and_levers: + title: Cables y pintor cuádruple + desc: "Has desbloqueado la Capa de cables: ¡Es una capa + separada a la capa regular e introduce un montón de mecanicas + nuevas!

Para empezar te he dado el Pintor + Cuádruple - ¡Conecta las ranuras que quieras pintar usando + la capa de cables!

Para cambiar a la capa de cables, presiona la tecla + E.

PD: ¡Activa las pistas en + las opciones para activar el tutorial de cables!" + reward_filter: + title: Filtro de items + desc: Has desbloqueado el Filtro de Items! Este enviará los items tanto + arriaba como a la derecha dependiendo en si coinciden con la + señal de la capa de cables o no.

Tambien puedes enviar una señal + booleana (1 / 0) para activarlo o desactivarlo completamente. + reward_demo_end: + title: Fin de la demo + desc: ¡Has llegado al final de la demo! settings: title: Opciones categories: - game: Juego - app: Aplicación - + general: General + userInterface: Interfaz de Usuario + advanced: Avanzado + performance: Rendimiento versionBadges: dev: Desarrollo staging: Escenificación prod: Producción buildDate: Generado - labels: uiScale: title: Escala de la interfaz - description: >- - Cambia el tamaño de la interfaz de usuario. La interfaz se seguirá escalando dependiendo de la resolución de tu dispositivo, pero esta opción controla la cantidad de escalado. + description: Cambia el tamaño de la interfaz de usuario. La interfaz se seguirá + escalando dependiendo de la resolución de tu dispositivo, pero + esta opción controla la cantidad de escalado. scales: super_small: Muy pequeño small: Pequeño regular: Mediano large: Grande huge: Enorme - autosaveInterval: title: Intervalo de autoguardado - description: >- - Controla con qué frecuencia se guarda el juego automáticamente. También se puede desactivar por completo. - + description: Controla con qué frecuencia se guarda el juego automáticamente. + También se puede desactivar por completo. intervals: one_minute: 1 minuto two_minutes: 2 minutos @@ -675,22 +784,19 @@ settings: ten_minutes: 10 minutos twenty_minutes: 20 minutos disabled: Desactivado - scrollWheelSensitivity: title: Sensibilidad del zoom - description: >- - Cambia cómo de sensible es el zoom (Tanto la rueda del ratón como el panel táctil) + description: Cambia cómo de sensible es el zoom (Tanto la rueda del ratón como + el panel táctil) sensitivity: super_slow: Muy lento slow: Lento regular: Normal fast: Rápido super_fast: Muy rápido - movementSpeed: title: Velocidad de movimiento - description: >- - Cambia cómo de rápido se mueve la vista usando el teclado. + description: Cambia cómo de rápido se mueve la vista usando el teclado. speeds: super_slow: Super lento slow: Lento @@ -698,87 +804,123 @@ settings: fast: Rápido super_fast: Súper rápido extremely_fast: Extremadamente rápido - language: title: Idioma - description: >- - Cambia el idioma. ¡Todas las traducciones son contribuciones de los usuarios y pueden estar incompletas! - + description: Cambia el idioma. ¡Todas las traducciones son contribuciones de los + usuarios y pueden estar incompletas! enableColorBlindHelper: title: Modo para daltónicos - description: >- - Activa varias herramientas que facilitan jugar si tienes alguna forma de daltonismo. - + description: Activa varias herramientas que facilitan jugar si tienes alguna + forma de daltonismo. fullscreen: title: Pantalla Completa - description: >- - Se recomienda jugar en pantalla completa para conseguir la mejor experiencia. Solo disponible en el juego completo. - + description: Se recomienda jugar en pantalla completa para conseguir la mejor + experiencia. Solo disponible en el juego completo. soundsMuted: title: Silenciar sonidos - description: >- - Si está habilitado, silencia todos los efectos de sonido. - + description: Si está habilitado, silencia todos los efectos de sonido. musicMuted: title: Silenciar música - description: >- - Si está habilitado, silencia toda la música. - + description: Si está habilitado, silencia toda la música. theme: title: Tema del juego - description: >- - Elige el tema del juego (claro/oscuro). + description: Elige el tema del juego (claro/oscuro). themes: dark: Oscuro light: Claro - refreshRate: title: Objetivo de simulación - description: >- - Si tienes un monitor de 144hz, cambia la tasa de refresco. Así el juego se ejecutará correctamente a una mayor tasa de refresco. Esto puede disminuir los FPS si tu ordenador no es lo suficientemente rápido. - + description: Si tienes un monitor de 144hz, cambia la tasa de refresco. Así el + juego se ejecutará correctamente a una mayor tasa de refresco. + Esto puede disminuir los FPS si tu ordenador no es lo + suficientemente rápido. alwaysMultiplace: title: Colocación múltiple - description: >- - Si está activado, todos los edificios se quedarán seleccionados después de colocarlos hasta que lo canceles. Equivale a pulsar SHIFT permanentemente. - + description: Si está activado, todos los edificios se quedarán seleccionados + después de colocarlos hasta que lo canceles. Equivale a pulsar + SHIFT permanentemente. offerHints: title: Pistas y tutoriales - description: >- - Actívalo para recibir pistas y tutoriales mientras juegas. También oculta algunos elementos de la interfaz hasta cierto nivel para hacer más fácil la introducción al juego. - + description: Actívalo para recibir pistas y tutoriales mientras juegas. También + oculta algunos elementos de la interfaz hasta cierto nivel para + hacer más fácil la introducción al juego. enableTunnelSmartplace: title: Túneles inteligentes - description: >- - Si está activado, al colocar túneles se eliminará automáticamente las cintas transportadoras innecesarias. También te permite arrastrar con el ratón y los túneles restantes serán eliminados. - + description: Si está activado, al colocar túneles se eliminará automáticamente + las cintas transportadoras innecesarias. También te permite + arrastrar con el ratón y los túneles restantes serán eliminados. vignette: title: Viñeta - description: >- - Activa el efecto viñeta que oscurece las esquinas de la pantalla y hace el texto más fácil de leer. - + description: Activa el efecto viñeta que oscurece las esquinas de la pantalla y + hace el texto más fácil de leer. rotationByBuilding: title: Rotación por tipo de edificio - description: >- - Cada tipo de edificio recuerda la última rotación que le diste individualmente. Esto puede ser más cómodo si cambias a menudo entre colocar diferentes tipos de edificio. - + description: Cada tipo de edificio recuerda la última rotación que le diste + individualmente. Esto puede ser más cómodo si cambias a menudo + entre colocar diferentes tipos de edificio. compactBuildingInfo: title: Información compacta de edificios - description: >- - Acorta la caja de información mostrando solo sus ratios. Si no, se mostrará una descripción y una imagen. - + description: Acorta la caja de información mostrando solo sus ratios. Si no, se + mostrará una descripción y una imagen. disableCutDeleteWarnings: title: Deshabilitar las advertencias de cortar/eliminar - description: >- - Deshabilita los diálogos de advertencia que se muestran cuando se cortan/eliminan más de 100 elementos. - + description: Deshabilita los diálogos de advertencia que se muestran cuando se + cortan/eliminan más de 100 elementos. + soundVolume: + title: Volumen de efectos + description: Establece el volumen para los efectos de sonido + musicVolume: + title: Volumen de música + description: Establece el volumen para la música + lowQualityMapResources: + title: Recursos del mapa de baja calidad + description: Simplifica el renderizado de los recusos en el mapa al ser vistos desde cerca, + mejorando el rendimiento. ¡Incluso se ve más limpio, asi que asegurate de probarlo! + disableTileGrid: + title: Deshabilitar grilla + description: Deshabilitar la grilla puede ayudar con el rendimiento. ¡También hace + que el juego se vea más limpio! + clearCursorOnDeleteWhilePlacing: + title: Limpiar el cursos al apretar click derecho + description: Activado por defecto, Limpia el cursor al hacer click derecho + mientras tengas un un edificio seleccionado. Si se deshabilita, + puedes eliminar edificios al hacer click derecho mientras pones + un edificio. + lowQualityTextures: + title: Texturas de baja calidad (Feo) + description: Usa texturas de baja calidad para mejorar el rendimiento. ¡Esto hará que el + juego se vea muy feo! + displayChunkBorders: + title: Mostrar bordes de chunk + description: Este juego está dividido en chunks de 16x16 cuadrados, si esta opción es + habilitada los bordes de cada chunk serán mostrados. + pickMinerOnPatch: + title: Elegír el minero en la veta de recursos + description: Activado pir defecto, selecciona el minero si usas el cuentagotas sobre + una veta de recursos. + simplifiedBelts: + title: Cintas trasportadoras simplificadas (Feo) + description: No rederiza los items en las cintas trasportadoras exceptuando al pasar el cursor sobre la cinta para mejorar + el rendimiento. No recomiendo jugar con esta opcion activada + a menos que necesites fuertemente mejorar el rendimiento. + enableMousePan: + title: Habilitar movimiento con mouse + description: Te permite mover el mapa moviendo el cursor hacia los bordes de la + pantalla. La velocidad depende de la opción de velocidad de movimiento. + zoomToCursor: + title: Hacer zoom donde está el cursor + description: Si se activa, se hará zoom en al dirección donde esté tu cursor, + a diferencia de hacer zoom en el centro de la pantalla. + mapResourcesScale: + title: Tamaño de recursos en el mapa + description: Controla el tamaño de los recursos en la vista de aerea del mapa (Al hacer zoom + minimo). + rangeSliderPercentage: % keybindings: title: Atajos de teclado - hint: >- - Pista: ¡Asegúrate de usar CTRL, SHIFT y ALT! Habilitan distintas opciones de colocación. - + hint: "Pista: ¡Asegúrate de usar CTRL, SHIFT y ALT! Habilitan distintas opciones + de colocación." resetKeybindings: Reestablecer atajos de teclado - categoryLabels: general: Aplicación ingame: Juego @@ -787,7 +929,6 @@ keybindings: massSelect: Selección masiva buildings: Atajos de edificios placementModifiers: Modificadores de colocación - mappings: confirm: Confirmar back: Atrás @@ -797,58 +938,63 @@ keybindings: mapMoveLeft: Mover a la izquierda mapMoveFaster: Mover más rápido centerMap: Centrar mapa - mapZoomIn: Acercarse mapZoomOut: Alejarse createMarker: Crear marcador - menuOpenShop: Mejoras menuOpenStats: Estadísticas menuClose: Cerrar menú - toggleHud: Activar HUD toggleFPSInfo: Activar FPS e información de depurado switchLayers: Cambiar capas exportScreenshot: Exportar la base completa como imagen - 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 + belt: Cinta Transportadora + underground_belt: Túnel + miner: Extractor + cutter: Cortador + rotater: Rotador + stacker: Apilador + mixer: Mezclador de colores + painter: Pintor + trash: Basurero + wire: Cable + pipette: Cuentagotas rotateWhilePlacing: Rotar - rotateInverseModifier: >- - Modificador: Rotar inversamente + rotateInverseModifier: "Modificador: Rotar inversamente" cycleBuildingVariants: Ciclar variantes confirmMassDelete: Borrar área pasteLastBlueprint: Pegar último plano cycleBuildings: Ciclar edificios lockBeltDirection: Activar planificador de cintas transportadoras - switchDirectionLockSide: >- - Planner: Cambiar sentido - + switchDirectionLockSide: "Planner: Cambiar sentido" massSelectStart: Mantén pulsado y arrastra para empezar massSelectSelectMultiple: Seleccionar múltiples áreas massSelectCopy: Copiar área massSelectCut: Cortar área - placementDisableAutoOrientation: Desactivar orientación automática placeMultiple: Permanecer en modo de construcción placeInverse: Invierte automáticamente la orientación de las cintas transportadoras - + balancer: Balanceador + storage: Almacenamiento + constant_signal: Señal constante + logic_gate: Puerta lógica + lever: Interruptor (regular) + filter: Filtro + wire_tunnel: Cruze de cables + display: Monitor + reader: Lector de cinta + virtual_processor: Cortador virtual + transistor: Transistor + analyzer: Analizador de formas + comparator: Comparador + item_producer: Productor de items (Sandbox) + copyWireValue: "Cables: Copiar valor bajo el cursos" about: title: Sobre el juego body: >- - Este juego es de código abierto y ha sido desarrollado por Tobias Springer (Ese soy yo).

+ Este juego es de código abierto y ha sido desarrollado por Tobias Springer + (Ese soy yo).

Si quieres contribuir, revisa shapez.io en github.

@@ -857,10 +1003,8 @@ about: La banda sonora ha sido creada por Peppsen - Es genial.

Por último, muchísimas gracias a mi amigo Niklas - Sin nuestras sesiones de Factorio, este juego nunca existiría. - changelog: title: Historial de cambios - demo: features: restoringGames: Recuperando partidas guardadas @@ -868,5 +1012,65 @@ demo: oneGameLimit: Limitado a una partida guardada customizeKeybindings: Personalizando atajos de teclado exportingBase: Exportando la base completa como imagen - settingNotAvailable: No disponible en la versión de prueba. +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-fi.yaml b/translations/base-fi.yaml index 2a2c83af..6da1e0bf 100644 --- a/translations/base-fi.yaml +++ b/translations/base-fi.yaml @@ -1,141 +1,86 @@ -# -# 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 on peli tehtaiden rakentamisesta, joiden avulla automatisoidaan yhä monimutkaisempien muotojen luonti and yhdisteleminen loputtomassa maailmassa. + shortText: shapez.io on peli tehtaiden rakentamisesta, joiden avulla + automatisoidaan yhä monimutkaisempien muotojen luonti and yhdisteleminen + loputtomassa maailmassa. + discordLinkShort: Virallinen Discord + intro: >- + Shapez.io on rento peli, jossa sinun täytyy rakentaa tehtaita geometristen muotojen + automatisoituun tuotantoon. - # 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] + Kun taso kasvaa, muodot tulevat entistä vaikeammaksi sekä sinun täytyy laajentua loputtomassa kartassa. - 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. + Ja jos tämä ei ollut tarpeeksi, niin sinun täytyy tuottaa eksponentiaalisesti enemmän täyttääksesi tarpeet - ainut asia mikä auttaa on skaalautuminen! - 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]! + Vaikka alussa vain prosessoit muotoja, myöhemmin niitä pitää maalata - tätä varten täytyy sinun kaivaa ja sekoittaa värejä - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! + Pelin ostaminen Steamista antaa sinulle pääsyn pelin kokoversioon, mutta voit myös pelata kokeiluversiota esin sivuillamme shapez.io ja päättää myöhemmin! + title_advantages: Kokoversion hyödyt + advantages: + - 12 uutta tasoa nostaen tasojen määrän 26 tasoon! + - 18 uutta rakennusta täysin automatisoidulle tehtaalle! + - 20 päivitystasoa monelle hauskalle pelitunnille! + - Johdot -päivitys tuoden täyden uuden ulottuvuuden! + - Tumma teema! + - Rajattomat tallennukset + - Rajattomat merkit + - Tue minua! ❤️ + title_future: Suunniteltu sisältö + planned: + - Pohjapiirustus kirjasto (Standalone Exclusive) + - Steam Achievements + - Palapelitila + - Minikartta + - Modit + - Hiekkalaatikko -tila + - ... ja paljon muuta! + title_open_source: Tämä peli on avointa lähdekoodia! + title_links: Linkit + links: + discord: Virallinen Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Lähdekoodi (GitHub) + translate: Auta kääntämään + text_open_source: >- + Kuka tahansa voi osallistua. Olen aktiivisesti mukana yhteisössä ja + yritän tarkistaa kaikki ehdotukset ja ottaa palautteen huomioon missä + mahdollista. + Muista tarkistaa Trello -lautani, jossa löytyy koko roadmap! global: loading: Ladataan error: Virhe - - # 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. + decimalSeparator: . suffix: thousands: k millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: ∞ - time: - # Used for formatting past time dates oneSecondAgo: yksi sekunti sitten - xSecondsAgo: sekunttia sitten + xSecondsAgo: sekuntia sitten oneMinuteAgo: yksi minuutti sitten xMinutesAgo: minuuttia sitten oneHourAgo: yksi tunti sitten xHoursAgo: tuntia sitten oneDayAgo: yksi päivä sitten xDaysAgo: päivää sitten - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s hoursAndMinutesShort: h m - xMinutes: minuuttia - keys: tab: SARKAIN control: CTRL alt: ALT escape: ESC - shift: VAIHTO + shift: SHIFT space: VÄLILYÖNTI - demoBanners: - # This is the "advertisement" shown in the main menu and other various places title: Demoversio - intro: >- - Hanki itsenäinen peli avataksesi kaikki omunaisuudet! - + intro: Hanki pelin kokoversio avataksesi kaikki ominaisuudet! mainMenu: play: Pelaa continue: Jatka @@ -144,19 +89,14 @@ mainMenu: subreddit: Reddit importSavegame: Tuo peli openSourceHint: Tämä on avoimen lähdekoodin peli! - discordLink: Virallinen Discord Palvelin + discordLink: Virallinen Discord -palvelin helpTranslate: Auta kääntämään! madeBy: Pelin on tehnyt - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - Anteeksi, mutta pelin tiedetään toimivan huonosti selaimellasi! Hanki itsenäinen versio tai lataa Chrome täyttä tukea varten. - + browserWarning: Anteeksi, mutta pelin tiedetään toimivan huonosti selaimellasi! + Hanki pelin kokoversio tai lataa Google Chrome täyttä tukea varten. savegameLevel: Taso - savegameLevelUnknown: Tuntematon Taso - - - + savegameLevelUnknown: Tuntematon taso + savegameUnnamed: Unnamed dialogs: buttons: ok: OK @@ -165,115 +105,109 @@ dialogs: later: Myöhemmin restart: Käynnistä uudelleen reset: Nollaa - getStandalone: Hanki itsenäinen peli + getStandalone: Hanki kokoversio deleteGame: Tiedän mitä olen tekemässä viewUpdate: Näytä päivitys - showUpgrades: Näytä Päivitykset - showKeybindings: Show Keybindings - + showUpgrades: Näytä päivitykset + showKeybindings: Näytä pikanäppäimet importSavegameError: - title: Tuonti Virhe - text: >- - Tallennuksen tuonti epäonnistui: - + title: Tuontivirhe + text: "Tallennuksen tuonti epäonnistui:" importSavegameSuccess: title: Tallennus tuotiin - text: >- - Tallennuksesi tuotiin onnistuneesti. - + text: Tallennuksesi tuotiin onnistuneesti. gameLoadFailure: title: Peli on rikki - text: >- - Tallennuksen lataus epäonnistui: - + text: "Tallennuksen lataus epäonnistui:" confirmSavegameDelete: title: Varmista poisto - text: >- - Oletko varma että haluat poistaa tallennuksen? - + text: Oletko varma, että haluat poistaa valitun pelin?

+ '' tasossa

Tätä toimintoa ei + voida peruuttaa! savegameDeletionError: title: Poisto epäonnistui - text: >- - Tallennuksen poisto epäonnistui: - + text: "Tallennuksen poisto epäonnistui:" restartRequired: title: Uudelleenkäynnistys vaaditaan - text: >- - Käynnistä peli uudelleen ottaaksesi asetukset käyttöön. - + text: Käynnistä peli uudelleen ottaaksesi asetukset käyttöön. editKeybinding: title: Vaihda pikanäppäin - desc: Paina näppäintä tai hiiren nappia jonka haluat asettaa tai paina escape peruuttaaksesi. - + desc: Paina näppäintä tai hiiren nappia, jonka haluat asettaa tai paina + escape peruuttaaksesi. resetKeybindingsConfirmation: title: Nollaa pikanäppäimet desc: Tämä nollaa kaikki pikanäppäimet oletusarvoihin. Vahvista. - keybindingsResetOk: title: Pikanäppäimet nollattiin desc: Pikanäppäimet nollattiin oletusarvoihin! - featureRestriction: title: Demoversio - desc: Yritit käyttää ominaisuutta () joka ei ole saatavilla demoversiossa. Harkitse itsenäisen version hankkimista avataksesi kaikki ominaisuudet! - + desc: Yritit käyttää ominaisuutta (), joka ei ole saatavilla + demoversiossa. Harkitse kokoversio avataksesi + kaikki ominaisuudet! oneSavegameLimit: title: Rajoitetut tallennukset - desc: Sinulla voi olla vain yksi tallennus kerrallaan demoversiossa. Poista vanha tallennus tai hanki itsenäinen versio! - + desc: Sinulla voi olla vain yksi tallennus kerrallaan demoversiossa. Poista + vanha tallennus tai hanki kokoversio pelistä! updateSummary: title: Uusi päivitys! - desc: >- - Tässä on tulleet muutokset sen jälkeen kun viimeksi pelasit: - + desc: "Tässä uudet muutokset sen jälkeen kun viimeksi pelasit:" upgradesIntroduction: - title: Avaa Päivitykset - desc: >- - Kaikkia muodoja joita tuotat voi käyttää päivitysten avaamiseen - Älä tuhoa vanhoja tehtaitasi! - Löydät päivitysikkunan näytön oikeasta yläkulmasta. - + title: Avaa päivitykset + desc: Kaikkia muotoja joita tuotat voidaan käyttää päivitysten avaamiseen - + Älä tuhoa vanhoja tehtaitasi! Löydät + päivitysikkunan näytön oikeasta yläkulmasta. massDeleteConfirm: title: Vahvista poisto - desc: >- - Olet poistamassa paljon rakennuksia (tasan )! Oletko varma että haluat jatkaa? - + desc: Olet poistamassa paljon rakennuksia ( tarkalleen)! Oletko varma, että + haluat jatkaa? massCutConfirm: - title: Vahtista leikkaus - desc: >- - Olet leikkaamassa paljon rakennuksia (tasan )! Oletko varma että haluat jatkaa? - + title: Vahvista leikkaus + desc: Olet leikkaamassa paljon rakennuksia ( tarkalleen)! Oletko varma, että + haluat jatkaa? blueprintsNotUnlocked: title: Ei vielä avattu - desc: >- - Suorita taso 12 avataksesi Piirustukset! - + desc: Suorita taso 12 avataksesi piirustukset! keybindingsIntroduction: title: Hyödyllisiä pikanäppäimiä - desc: >- - Tässä pelissä on paljon pikanäppäimiä, jotka tekevät isojen tehtaiden rakentamisesta helpompaa. - Tässä on muutama, mutta katso kaikki pikanäppäimet!

- CTRL + Raahaus: Valitse alue.
- VAIHTO: Pidä pohjassa sijoittaaksesi useita samoja rakennuksia.
- ALT: Käännä sijoitettavien hihnojen suunta.
- + desc: "Tässä pelissä on paljon pikanäppäimiä, jotka tekevät isojen tehtaiden + rakentamisesta helpompaa. Tässä on muutama, mutta katso + kaikki pikanäppäimet!

CTRL + Raahaus: Valitse alue.
VAIHTO: Pidä pohjassa sijoittaaksesi + useita samoja rakennuksia.
ALT: + Käännä sijoitettavien hihnojen suunta.
" createMarker: - title: Uusi Merkki - desc: Anna merkille kuvaava nimi, voit myös sisällyttää muodon lyhyen avaimen siihen. (Lyhyen avaimen voit luoda täällä) - titleEdit: Edit Marker - + title: Uusi merkki + desc: Anna merkille merkitsevä nimi. Voit myös liittää lyhyen koodin + muodosta. (Jonka voit luoda täällä.) + titleEdit: Muokkaa merkkiä markerDemoLimit: - desc: Voit tehdä vain kaksi mukautettua merkkiä demoversiossa. Hanki itsenäinen versio saadaksesi loputtoman määrän merkkejä! - + desc: Voit tehdä vain kaksi mukautettua merkkiä demoversiossa. Hanki kokoversio + saadaksesi loputtoman määrän merkkejä! exportScreenshotWarning: title: Vie kuvakaappaus - desc: Pyysit tukikohtasi viemistä kuvakaappauksena. Huomaa, että tämä voi olla melko hidasta isolla tukikohdalla ja voi jopa kaataa pelisi! + desc: Pyysit tukikohtasi viemistä kuvakaappauksena. Huomaa, että tämä voi olla + melko hidasta isolla tukikohdalla ja voi jopa kaataa pelisi! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? - + title: Vahvista leikkaus + desc: Sinulla ei ole varaa leikata tätä aluetta! Oletko varma että haluat + leikata sen? + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: Nimeä tallennus uudelleen + desc: Voit nimetä tallennuksesi uudelleen täällä. + tutorialVideoAvailable: + title: Ohjevideo saatavilla + desc: Tästä tasosta on saatavilla ohjevideo! Haluaisitko katsoa sen? + tutorialVideoAvailableForeignLanguage: + title: Ohjevideo saatavilla + desc: Tästä tasosta on saatavilla ohjevideo! Haluaisitko katsoa sen? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Liiku selectBuildings: Valitse alue @@ -291,11 +225,9 @@ ingame: plannerSwitchSide: Käännä suunnittelijan puoli cutSelection: Leikkaa copySelection: Kopioi - clearSelection: Tyhjennä Valinta + clearSelection: Tyhjennä valinta pipette: Pipetti - switchLayers: Vaihda Tasoa - - # Names of the colors, used for the color blind mode + switchLayers: Vaihda tasoa colors: red: Punainen green: Vihreä @@ -304,20 +236,11 @@ ingame: purple: Violetti cyan: Syaani white: Valkoinen - uncolored: Ei Väriä - black: Black - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + uncolored: Väritön + black: Musta 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: Paina kiertääksesi muunnoksia. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Pikanäppäin: - + cycleBuildingVariants: Paina selataksesi vaihtoehtoja. + hotkeyLabel: "Pikanäppäin: " infoTexts: speed: Nopeus range: Matka @@ -325,36 +248,21 @@ ingame: oneItemPerSecond: 1 kappale / sekunti itemsPerSecond: kappaleita / s itemsPerSecondDouble: (x2) - tiles: laattaa - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Taso completed: Suoritettu unlockText: Avattu ! buttonNextLevel: Seuraava taso - - # Notifications on the lower right notifications: newUpgrade: Uusi päivitys on saatavilla! gameSaved: Peli on tallennettu. - - # The "Upgrades" window + freeplayLevelComplete: Taso on saavutettu! shop: title: Päivitykset buttonUnlock: Päivitä - - # Gets replaced to e.g. "Tier IX" tier: Taso - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: SUURIN TASO (Nopeus x) - - # The "Statistics" window statistics: title: Tilastot dataSources: @@ -363,309 +271,503 @@ ingame: description: Näyttää keskusrakennuksessa varastoitujen muotojen määrän. produced: title: Tuotettu - description: Näyttää kaikki muodot mitä tehtaasi tuottaa ja lisäksi myös välituotteet. + description: Näyttää kaikki muodot mitä tehtaasi tuottaa ja lisäksi myös + välituotteet. delivered: title: Toimitettu - description: Näyttää muodot jotka on toimitettu keskusrakennukseen. + description: Näyttää muodot, jotka on toimitettu keskusrakennukseen. noShapesProduced: Toistaiseksi ei muotoja tuotettu. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Peliaika - buildingsPlaced: Rakennukset beltsPlaced: Liukuhihnat - - buttons: - continue: Jatka - settings: Asetukset - menu: Palaa valikkoon - - # Bottom left tutorial hints tutorialHints: title: Tarvitsetko apua? showHint: Näytä vihje hideHint: Sulje - - # When placing a blueprint blueprintPlacer: cost: Hinta - - # Map markers waypoints: waypoints: Merkit hub: Keskusrakennus - description: Paina merkkia hiiren vasemmalla mennäksesi siihen, paina oikeaa nappia poistaaksesi sen.

Paina luodaksesi merkin nykyisestä näkymästä tai varen nappi luodaksesi merkin valittuun paikkaan. + description: Paina merkkiä hiiren vasemmalla mennäksesi siihen, paina oikeaa + nappia poistaaksesi sen.

Paina luodaksesi merkin + nykyisestä näkymästä tai vasen nappi luodaksesi + merkin valittuun paikkaan. creationSuccessNotification: Merkki luotiin onnistuneesti. - - # Shape viewer shapeViewer: title: Tasot empty: Tyhjä copyKey: Kopioi avain - - # Interactive tutorial interactiveTutorial: title: Tutoriaali hints: - 1_1_extractor: Laita Kaivaja ympyrämuodon päälle kaivaaksesi sen! - 1_2_conveyor: >- - Yhdistä kaivaja liukuhihnalla keskusrakennukseen!

Vihje: Paina ja raahaa liukuhihnaa hiirellä! - - 1_3_expand: >- - Tämä EI OLE tyhjäkäyntipeli! Rakenna lisää kaivajia ja hihnoja saadaksesi tavoitteen nopeammin valmiiksi.

Vihje: Pidä pohjassa VAIHTO laittaaksesi useampia kaivajia ja käytä R kääntääksesi niitä. - -# All shop upgrades + 1_1_extractor: Laita Kaivaja ympyrämuodon + päälle kaivaaksesi sen! + 1_2_conveyor: "Yhdistä kaivaja liukuhihnalla + keskusrakennukseen!

Vihje: Paina ja + raahaa liukuhihnaa hiirellä!" + 1_3_expand: "Tämä EI OLE tyhjäkäyntipeli! Rakenna lisää + kaivajia ja hihnoja saadaksesi tavoitteen nopeammin + valmiiksi.

Vihje: Pidä pohjassa VAIHTO + laittaaksesi useampia kaivajia ja käytä R + kääntääksesi niitä." + 2_1_place_cutter: "Nyt aseta Leikkuri leikataksesi ympyrä + puoliksi!

PS: Leikkuri aina leikkaa ylhäältä alaspäin + riippumatta sen asennosta." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." + connectedMiners: + one_miner: 1 kaivaja + n_miners: kaivajaa + limited_items: Rajoitettu + watermark: + title: Kokeiluversio + desc: Napsauta tästä nähdäksesi Steam version edut! + get_on_steam: Hanki Steamista + standaloneAdvantages: + title: Hanki kokoversio! + no_thanks: Ei kiitos! + points: + levels: + title: 12 Uutta tasoa + desc: Yhteensä 26 tasoa! + buildings: + title: 18 Uutta rakennusta + desc: Automatisoi tehtaasi täysin! + savegames: + title: ∞ Tallennukset + desc: Niin paljon kuin sielusi kaipaa! + upgrades: + title: 20 päivitystasoa + desc: Kokeiluversiossa on vain viisi! + markers: + title: ∞ Merkit + desc: Älä koskaan eksy tehtaassasi! + wires: + title: Johdot + desc: Täysin uusi ulottuvuus! + darkmode: + title: Tumma teema + desc: Jotta silmiisi ei sattuisi! + support: + title: Tue minua + desc: Kehitän peliä vapaa-ajallani! shopUpgrades: belt: - name: Hihnat, Jakelija & Tunneli + name: Hihnat, jakelija & tunneli description: Nopeus x → x miner: name: Kaivuu description: Nopeus x → x processors: - name: Leikkaus, Kääntö & Pinoaminen + name: Leikkaus, kääntö & pinoaminen description: Nopeus x → x painting: - name: Sekoitus & Värjäys + name: Sekoitus & värjäys description: Nopeus x → x - -# Buildings and their name / description buildings: hub: deliver: Toimita toUnlock: avataksesi levelShortcut: LVL - + endOfDemo: Kokeiluversion loppu! belt: default: - name: &belt Liukuhihna - description: Kuljettaa esineitä, pidä pohjassa ja raahaa laittaaksesi useampia. - + name: Liukuhihna + description: Kuljettaa esineitä. Pidä pohjassa ja raahaa laittaaksesi useampia. wire: default: - name: &wire Johto - description: Sallii sähkön kuljetuksen - - miner: # Internal name for the Extractor + name: Johto + description: Sallii sähkönkuljetuksen + second: + name: Johto + description: Siirtää signaaleja, jotka voivat olla muotoja, värejä, taikka binääriarvoja (1 / 0). + Eriväriset johdot eivät yhdisty toisiinsa. + miner: default: - name: &miner Kaivaja + name: Kaivaja description: Laita muodon tai värin päälle kaivaaksesi sen. - chainable: name: Kaivaja (Sarja) - description: Laita muodon tai värin päälle kaivaaksesi sen. Voidaan kytkeä sarjaan. - - underground_belt: # Internal name for the Tunnel + description: Laita muodon tai värin päälle kaivaaksesi sen. Voidaan kytkeä + sarjaan. + underground_belt: default: - name: &underground_belt Tunneli + name: Tunneli description: Sallii resurssien kuljetuksen rakennuksien ja hihnojen alta. - tier2: - name: Tunneli Taso II - description: Sallii resurssien kuljetuksen rakennuksien ja hihnojen alta. - - splitter: # Internal name for the Balancer - default: - name: &splitter Tasaaja - description: Monikäyttöinen - Jakaa kaikki sisääntulot tasaisesti kaikkiin ulostuloihin. - - compact: - name: Yhdistäjä (Pienikokoinen) - description: Yhdistää kaksi liukuhihnaa yhdeksi. - - compact-inverse: - name: Yhdistäjä (Pienikokoinen) - description: Yhdistää kaksi liukuhihnaa yhdeksi. - + name: Tunneli taso II + description: Sallii resurssien kuljetuksen rakennuksien ja hihnojen alta + pidemmältä kantamalta. cutter: default: - name: &cutter Leikkuri - description: Leikkaa muotoja ylhäältä alaspäin ja tuottaa muodon molemmat puoliskot. Jos käytät vain yhden puoliskon, tuhoa toinen puolisko tai se jumittaa leikkurin! + name: Leikkuri + description: Leikkaa muotoja ylhäältä alaspäin ja tuottaa muodon molemmat + puoliskot. Jos käytät vain yhden puoliskon, tuhoa toinen + puolisko tai se jumittaa leikkurin! quad: name: Leikkuri (Neliö) - description: Leikkaa muotoja ylhäältä alaspäin ja tuottaa muodon molemmat puoliskot. Jos käytät vain yhden puoliskon, tuhoa toinen puolisko tai se jumittaa leikkurin! - - advanced_processor: - default: - name: &advanced_processor Edistynyt Käsittelijä - description: Edistynyt muotojen käsittely - + description: Leikkaa muotoja ylhäältä alaspäin ja tuottaa muodon molemmat + puoliskot. Jos käytät vain yhden puoliskon, tuhoa toinen + puolisko tai se jumittaa leikkurin! rotater: default: - name: &rotater Kääntäjä + name: Kääntäjä description: Kääntää muotoja 90 astetta myötäpäivään. ccw: - name: Rotate (Vastapäivään) + name: Kääntäjä (vastapäivään) description: Kääntää muotoja 90 astetta vastapäivään. - + rotate180: + name: Kääntäjä (180) + description: Kääntää muotoja 180 astetta. stacker: default: - name: &stacker Pinoaja - description: Pinoaa molemmat tavarat. Jos niitä ei pysty yhdistämään, oikeanpuoleinen tavara laitetaan vasemmanpuoleisen päälle. - + name: Pinoaja + description: Pinoaa molemmat tavarat. Jos niitä ei pysty yhdistämään, + oikeanpuoleinen tavara laitetaan vasemmanpuoleisen päälle. mixer: default: - name: &mixer Värinsekoittaja + name: Värinsekoittaja description: Sekoittaa kaksi väriä lisäaineiden avulla. - painter: default: - name: &painter Värjääjä - description: &painter_desc Värjää vasemmasta sisääntulosta tulevan muodon ylemmästä sisääntulosta tulevalla värillä. - + name: Maalari + description: Maalaa vasemmasta sisääntulosta tulevan muodon ylemmästä + sisääntulosta tulevalla värillä. mirrored: - name: *painter - description: *painter_desc - + name: Maalari + description: Maalaa vasemmasta sisääntulosta tulevan muodon alemmasta + sisääntulosta tulevalla värillä. double: - name: Värjääjä (Kaksinkertainen) - description: Värjää vasemmasta sisääntulosta tulevan muodon ylemmästä sisääntulosta tulevalla värillä. + name: Maalari (kaksinkertainen) + description: Värjää vasemmasta sisääntulosta tulevat muodot ylemmästä + sisääntulosta tulevalla värillä. quad: - name: Painter (Neljännes) - description: Sallii muodon neljäsosien värjäämisen eri väreillä. - + name: Maalari (neljännes) + description: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! trash: default: - name: &trash Roskakori + name: Roskakori description: Sallii sisääntulot kaikilta sivuilta ja tuhoaa ne. Lopullisesti. - - storage: - name: Varasto - description: Varastoi ylimääräisia resursseja tiettyyn kapasiteettiin asti. Voidaan käyttää ylivuotoporttina. - - energy_generator: - deliver: Toimita - - # This will be shown before the amount, so for example 'For 123 Energy' - toGenerateEnergy: Kohden - + balancer: default: - name: &energy_generator Sähkögeneraattori - description: Tuottaa sähköä kuluttamalla muotoja. Jokainen sähkögeneraattori vaatii eri muotoja. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Tasaaja + description: Monikäyttöinen - Jaa sisääntulot tasaisesti kaikkiin ulostuloihin. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Yhdistäjä (compact) + description: Yhdistää kaksi hihnaa yhteen. + merger-inverse: + name: Yhdistäjä (compact) + description: Yhdistää kaksi hihnaa yhteen. + splitter: + name: Erottaja (compact) + description: Erottaa hihnan kahteen hihnaan. + splitter-inverse: + name: Erottaja (compact) + description: Erottaa hihnan kahteen hihnaan. + storage: + default: + name: Varasto + description: Varasotoi ylijäämätavarat tiettyyn kapasiteettiin asti. Priorisoi vasemman ulostulon + ja voidaan käyttää ylivuotoporttina. + wire_tunnel: + default: + name: Johdon ylitys + description: Antaa johdon ylittää toisen liittämättä niitä. + constant_signal: + default: + name: Jatkuva signaali + description: Lähettää vakiosignaalin, joka voi olla muoto, väri, taikka binääriarvo (1 / 0). + lever: + default: + name: Kytkin + description: Voidaan kytkeä lähettämään binääriarvoa (1 / 0) johtotasolla, + jota voidaan sitten käyttää esimerkiksi tavarasuodattimen ohjaukseen. + logic_gate: + default: + name: AND portti + description: Lähettää totuusarvon "1", jos molemmat sisääntulot ovat totta. (Totuus tarkoittaa, + että muoto, väri tai totuusarvo "1") + not: + name: NOT portti + description: Lähettää totuusarvon "1", jos sisääntulot eivät ole totta. + (Totuus tarkoittaa, että muoto, väri tai totuusarvo "1") + xor: + name: XOR portti + description: Lähettää totuusarvon "1", jos yksi sisääntuloista on totta, mutta kaikki eivät. + (Totuus tarkoittaa, että muoto, väri tai totuusarvo "1") + or: + name: OR portti + description: Lähettää totuusarvon "1", jos yksi sisääntuloista on totta. + (Totuus tarkoittaa, että muoto, väri tai totuusarvo "1") + transistor: + default: + name: Transistori + description: Lähettää pohjasignaalin eteenpäin, jos sivusisääntulo on totta. + (Totuus tarkoittaa, että muoto, väri tai totuusarvo "1") + mirrored: + name: Transistori + description: Lähettää pohjasignaalin eteenpäin, jos sivusisääntulo on totta. + (Totuus tarkoittaa, että muoto, väri tai totuusarvo "1") + filter: + default: + name: Suodatin + description: Yhdistä signaali reitittääksesi kaikki vastaavat tavarat ylös, + ja jäljelle jäämät vasemmalle. Voidaan ohjata myös binääriarvoilla. + display: + default: + name: Näyttö + description: Yhdistö signaali näyttääksesi sen näytöllä. Voi olla muoto, + väri tai binääriarvo. + reader: + default: + name: Hihnanlukija + description: Mittaa hihnan keskiarvosuorituskyky. Antaa viimeksi luetun + tavaran signaalin johtotasolla (kun saavutettu). + analyzer: + default: + name: Tutkija + description: Analysoi ylä oikean neljänneksen alimmasta tavaran tasosta ja + palauttaa sen muodon ja värin. + comparator: + default: + name: Vertain + description: Palauttaa binääriarvon "1", jos molemmat signaalit ovat täysin samat. + Voi verrata värejä, tavaroita, ja binääriarvoja. + virtual_processor: + default: + name: Virtuaalileikkuri + description: Virtuaalisesti leikkaa tavara kahteen puoliskoon. + rotater: + name: Virtuaalikääntäjä Rotater + description: Virtuaalisesti käännä tavara, sekä myötäpäivään että vastapäivään. + unstacker: + name: Virtuaalierottaja + description: Virtuaalisesti erota ylin taso oikeaan ulostuloon ja jäljelle jäävät + vasempaan ulostuloon. + stacker: + name: Virtuaaliyhdistäjä + description: Virtuaalisesti yhdistä oikea tavara vasempaan. + painter: + name: Virtuaalimaalaaja + description: Virtuaalisesti maalaa tavara alhaalta sisääntulosta oikean sisääntulon värillä. + item_producer: + default: + name: Item Producer + description: Saatavilla vain hiekkalaatikkotilassa. Palauttaa + johtotasolla annetun signaalin normaaliin tasoon. storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Muotojen Leikkaus - desc: Avasit Leikkurin - se leikkaa muotoja puoliksi ylhäältä alaspäin riippumatta sen suunnasta!

Varmista, että pääset eroon jätteistä, tai muuten se jumittuu - Tätä varten saat Roskiksen, joka tuhoaa kaiken mitä laitat sinne! - + desc: You just unlocked the cutter, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! reward_rotater: title: Kääntö - desc: Avasit Kääntäjän! Se kääntää muotoja myötäpäivään 90 astetta. - + desc: Avasit Kääntäjän! Se kääntää muotoja myötäpäivään 90 + astetta. reward_painter: title: Värjäys - desc: >- - Avasit Värjääjän - Kaiva joitain värialueita (Samanlailla kuin muotoja) ja yhdistä se muotoon värjääjän avulla!

PS: Jos olet värisokea, asetuksissa on tila värisokeille! - + desc: "Avasit Värjääjän - Kaiva joitain värialueita + (Samanlailla kuin muotoja) ja yhdistä se muotoon värjääjän + avulla!

PS: Jos olet värisokea, asetuksissa on tila + värisokeille!" reward_mixer: title: Värin Sekoitus - desc: Avasit Värinsekoittajan - Yhdistä kaksi väriä lisäaineiden avulla tällä rakennuksella! - + desc: Avasit Värinsekoittajan - Yhdistä kaksi väriä + lisäaineiden avulla tällä rakennuksella! reward_stacker: title: Yhdistäjä - desc: Nyt voit yhdistää muotoja Yhdistäjällä! Molemman sisääntulot yhdistetään, jos ne laitetaan vierekkäin, niistä tulee sulatettu. Jos ne eivät ole vierekkäin, oikeanpuoleinen sisääntulo kasataan vasemman päälle! - + desc: Nyt voit yhdistää muotoja Yhdistäjällä! Molemman + sisääntulot yhdistetään, jos ne laitetaan vierekkäin, niistä tulee + sulatettu. Jos ne eivät ole vierekkäin, + oikeanpuoleinen sisääntulo kasataan vasemman + päälle! reward_splitter: title: Tasaaja - desc: Avasit monikäyttöisen Tasaajan - Sitä voidaan käyttää isompien tehtaiden rakennukseen jakamaan ja yhdistämään tavaroita monille hihnoille!

- + desc: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! reward_tunnel: title: Tunneli - desc: Avasit Tunnelin - Nyt voit kuljettaa tavaroita liukuhihnoilla rakennusten ja liukuhihnojen alta! - + desc: Avasit Tunnelin - Nyt voit kuljettaa tavaroita + liukuhihnoilla rakennusten ja liukuhihnojen alta! reward_rotater_ccw: title: Vastapäivään Kääntö - desc: Avasit uuden muodon Kääntäjästä - Se sallii kääntämisen vastapäivään! Sen voi rakentaa valitsemalla kääntäjän ja painamalla 'T' vaihtaaksesi sen muotoja! - + desc: Avasit uuden muodon Kääntäjästä - Se sallii kääntämisen + vastapäivään! Sen voi rakentaa valitsemalla kääntäjän ja + painamalla 'T' vaihtaaksesi sen muotoja! reward_miner_chainable: title: Sarja Kaivaja - desc: Avasit Sarja Kaivajan! Se voi välittää sen resurssit muille kaivajille, jotta voit kaivaa resursseja tehokkaammin! - + desc: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" reward_underground_belt_tier_2: title: Tunneli Taso II - desc: Avasit uuden muodon Tunnelista - Siinä on pidempi matka, ja voit myös yhdistellä ja sovitella tunneleita! - - reward_splitter_compact: - title: Pienikokoinen Yhdistäjä - desc: >- - Avasit pienikokoisen muodon Yhdistäjästä - Se ottaa kaksi sisääntuloa ja yhdistää ne yhdeksi! - + desc: Avasit uuden muodon Tunnelista - Siinä on pidempi + matka, ja voit myös yhdistellä ja sovitella tunneleita! reward_cutter_quad: title: Neljäsosa Leikkaus - desc: Avasit muodon Leikkurista - Se sallii muotojen leikkaamisen neljään osaan kahden sijaan! - + desc: Avasit muodon Leikkurista - Se sallii muotojen + leikkaamisen neljään osaan kahden sijaan! reward_painter_double: title: Kaksinkertainen Värjäys - desc: Avasit muodon Värjääjästä - Se toimii samanlailla kuin normaali värjääjä, mutta käsittelee kaksi muotoa kerrallaan käyttäen vain yhden värin kahden sijaan! - - reward_painter_quad: - title: Neljäsosa Värjäys - desc: Avasit muodon Värjääjästä - Se sallii muodon eri osien värjäämisen erikseen! - + desc: Avasit muodon Värjääjästä - Se toimii samanlailla kuin + normaali värjääjä, mutta käsittelee kaksi muotoa + kerrallaan käyttäen vain yhden värin kahden sijaan! reward_storage: title: Varasto Puskuri - desc: Avasit muodon Roskiksesta - Se sallii resurssien säilyttämisen tiettyyn kapasiteettiin asti! - + desc: You have unlocked the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! reward_freeplay: title: Vapaapeli - desc: Sinä teit sen! Avasit Vapaapelitilan! Tämä tarkoittaa sitä, että muodot tehdään nyt satunnaisesti! (Ei hätää, lisää sisältöä on suunnitteilla itsenäiseen peliin!) - + desc: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. reward_blueprints: title: Piirustukset - desc: Nyt voit Kopioida ja Liittää paloja tehtaastasi! Valitse alue (pidä pohjassa CTRL ja raahaa hiirellä), ja paina 'C' kopioidaksesi.

Sen liittäminen ei ole ilmaista, sinun täytyy tuottaa piirustus muotoja jotta sinulla on varaa siihen! (Ne mitkä juuri toimitit). - - # Special reward, which is shown when there is no reward actually + desc: Nyt voit Kopioida ja Liittää paloja tehtaastasi! Valitse + alue (pidä pohjassa CTRL ja raahaa hiirellä), ja paina 'C' + kopioidaksesi.

Sen liittäminen ei ole + ilmaista, sinun täytyy tuottaa piirustus + muotoja jotta sinulla on varaa siihen! (Ne mitkä juuri + toimitit). no_reward: title: Seuraava taso - 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! - + 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: Seuraava taso - desc: >- - Onnittelut! Muuten, lisää sisältöä on suunniteltu itsenäiseen versioon! - + desc: Onnittelut! Muuten, lisää sisältöä on suunniteltu itsenäiseen versioon! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: Kokeiluversion loppu! + desc: Olet läpäissyt kokeiluversion! settings: title: Asetukset categories: - game: Peli - app: Sovellus - + general: Yleinen + userInterface: Käyttöliittymä + advanced: Lisäasetukset + performance: Suorityskyky versionBadges: dev: Kehitys - staging: Näyttämö + staging: Testaus prod: Tuotanto - buildDate: Rakennettu - + buildDate: Koottu labels: uiScale: - title: Käyttöliittymän Koko - description: >- - Muuttaa käyttöliittymän kokoa. Käyttöliittymä skaalataan silti laitteen resoluution perusteella based on your device resolution, mutta tämä asetus määrittää skaalauksen määrän. + title: Käyttöliittymän koko + description: Muuttaa käyttöliittymän kokoa. Käyttöliittymä skaalataan silti + laitteen resoluution perusteella, mutta tämä asetus määrittää skaalauksen määrän. scales: super_small: Erittäin pieni small: Pieni regular: Normaali large: Iso huge: Valtava - autosaveInterval: - title: Automaattitallennuksen Aikaväli - description: >- - Määrittää kuinka usein peli tallentaa automaattisesti. Voit myös poistaa automaattisen tallennuksen kokonaan käytöstä täällä. - + title: Automaattitallennuksen aikaväli + description: Määrittää kuinka usein peli tallentaa automaattisesti. Voit myös + poistaa automaattisen tallennuksen kokonaan käytöstä täällä. intervals: one_minute: 1 Minuutin välein two_minutes: 2 Minuutin välein @@ -673,119 +775,150 @@ settings: ten_minutes: 10 Minuutin välein twenty_minutes: 20 Minuutin välein disabled: Pois käytöstä - scrollWheelSensitivity: - title: Zoomausherkkyys - description: >- - Vaihtaa kuinka herkkä zoomi on (Joko hiiren rulla tai ohjauslevy). + title: Suurennusherkkyys + description: Vaihtaa kuinka herkkä suurennus on (Joko hiiren rulla tai ohjauslevy). sensitivity: super_slow: Erittäin hidas slow: Hidas regular: Normaali fast: Nopea super_fast: Erittäin nopea - movementSpeed: - title: Liikkumis nopeus - description: >- - Muuttaa kuinka nopeasti näkymä liikkuu kun käytetään näppäimistöä. + title: Liikkumisnopeus + description: Muuttaa kuinka nopeasti näkymä liikkuu kun käytetään näppäimistöä. speeds: super_slow: Erittäin hidas slow: Hidas regular: Normaali fast: Nopea super_fast: Erittäin nopea - extremely_fast: Hyper nopea - + extremely_fast: Supernopea language: title: Kieli - description: >- - Vaihda kieltä. Kaikki käännökset ovat käyttäjien tekemiä ja saattavat olla puutteellisia! - + description: Vaihda kieltä. Kaikki käännökset ovat käyttäjien tekemiä ja + saattavat olla puutteellisia! enableColorBlindHelper: title: Värisokeatila - description: >- - Ottaa käyttöön useita työkaluja, jotka sallivat pelin pelaamisen jos olet värisokea. - + description: Ottaa käyttöön useita työkaluja, jotka sallivat pelin pelaamisen + jos olet värisokea. fullscreen: title: Kokonäyttö - description: >- - On suositeltava pelata tätä peliä kokonäytön tilassa saadaksesi parhaan kokemuksen. Saatavilla vain itsenäisessä versiossa. - + description: On suositeltava pelata tätä peliä kokonäytön tilassa saadaksesi + parhaan kokemuksen. Saatavilla vain itsenäisessä versiossa. soundsMuted: - title: Mykistä Äänet - description: >- - Jos käytössä, mykistää kaikki ääniefektit. - + title: Mykistä äänet + description: Jos käytössä, mykistää kaikki ääniefektit. musicMuted: - title: Mykistä Musiikki - description: >- - Jos käytössä, mykistää musiikin. - + title: Mykistä musiikki + description: Jos käytössä, mykistää musiikin. theme: - title: Pelin Teema - description: >- - Valitse pelin teema (vaalea / tumma). + title: Pelin teema + description: Valitse pelin teema (vaalea / tumma). themes: dark: Tumma - light: Kirkas - + light: Vaalea refreshRate: - title: Simulaatiotavoite - description: >- - Jos sinulla on 144hz näyttö, muuta virkistystaajuus täällä jotta pelin simulaatio toimii oikein isommilla virkistystaajuuksilla. Tämä voi laskea FPS nopeutta jos tietokoneesi on liian hidas. - + title: Virkistystaajuus + description: Jos sinulla on 144hz näyttö, muuta virkistystaajuus täällä jotta + pelin simulaatio toimii oikein isommilla virkistystaajuuksilla. + Tämä voi laskea FPS nopeutta, jos tietokoneesi on liian hidas. alwaysMultiplace: title: Monisijoitus - description: >- - Jos käytössä, kaikki rakennukset pysyvät valittuina sijoittamisen jälkeen kunnes peruutat sen. Tämä vastaa SHIFT:in pitämistö pohjassa ikuisesti. - + description: Jos käytössä, kaikki rakennukset pysyvät valittuina sijoittamisen + jälkeen kunnes peruutat sen. Tämä vastaa SHIFT:in pitämistä + pohjassa ikuisesti. offerHints: - title: Vihjeet & Oppaat - description: >- - Tarjotaanko pelaamisen aikana vihjeitä ja oppaita. Myös piilottaa tietyt käyttöliittymäelementit tietyn tason mukaan, jotta alkuunpääseminen olisi helpompaa. - + title: Vihjeet & oppaat + description: Tarjoaa pelaamisen aikana vihjeitä ja oppaita. Myös piilottaa + tietyt käyttöliittymäelementit tietyn tason mukaan, jotta + alkuunpääseminen olisi helpompaa. enableTunnelSmartplace: - title: Älykkäät Tunnelit - description: >- - Kun käytössä, tunnelin sijoittaminen automaattisesti poistaa tarpeettomat liukuhihnat. Tämä myös ottaa käyttöön tunnelien raahaamisen ja ylimääräiset tunnelit poistetaan. - + title: Älykkäät tunnelit + description: Kun käytössä, tunnelin sijoittaminen automaattisesti poistaa + tarpeettomat liukuhihnat. Tämä myös ottaa käyttöön tunnelien + raahaamisen ja ylimääräiset tunnelit poistetaan. vignette: - title: Vignetti - description: >- - Ottaa käyttöön vignetin, joka tummentaa näytön kulmia ja tekee tekstin lukemisesta helpompaa. - + title: Vinjetointi + description: Ottaa käyttöön vinjetoinnin, joka tummentaa näytön kulmia ja tekee + tekstin lukemisesta helpompaa. rotationByBuilding: title: Kiertäminen rakennustyypin mukaan - description: >- - Jokainen rakennustyyppi muistaa kierron, jonka viimeksi asetit yksilöllisesti. Tämä voi olla mukavampi vaihtoehto jos usein sijoitat eri rakennustyyppejä. - + description: Jokainen rakennustyyppi muistaa kierron, jonka viimeksi asetit + yksilöllisesti. Tämä voi olla mukavampi vaihtoehto jos usein + sijoitat eri rakennustyyppejä. compactBuildingInfo: - title: Kompaktit Rakennusten Tiedot - description: >- - Lyhentää rakennusten tietolaatikoita näyttämällä vain niiden suhteet. Muuten rakennuksen kuvaus ja kuva näytetään. - + title: Kompaktit rakennusten tiedot + description: Lyhentää rakennusten tietolaatikoita näyttämällä vain niiden + suhteet. Muuten rakennuksen kuvaus ja kuva näytetään. disableCutDeleteWarnings: - title: Poista Leikkaus/Poisto Varoitukset - description: >- - Poista varoitusikkunat dialogs brought up when cutting/deleting more than 100 entities. - + title: Poista leikkaus/poisto -varoitukset + description: Poista varoitusikkunat jotka ilmestyy kun leikkaat/poistat enemmän + kuin 100 entiteettiä + soundVolume: + title: Efektien äänenvoimakkuus + description: Aseta äänenvoimakkuus efekteille + musicVolume: + title: Musiikin äänenvoimakkuus + description: Aseta äänenvoimakkuus musiikille + 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: Poista ruudukko + 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: Alhaisen tason tekstuurit (ruma) + description: Käyttää alhaisen tason tekstuureja tehojen säästämiseksi. Tämä + muutta pelin rumaksi! + displayChunkBorders: + title: Näytä kimpaleiden reunus Display Chunk Borders + description: Pel on jaettu 16x16 kimpaleisiin. Jos tämä asetus on käytössä, + reunat jokaiselle kimpaleelle näytetään. + pickMinerOnPatch: + title: Pick miner on resource patch + description: Enabled by default, selects the miner if you use the pipette when + hovering a resource patch. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: Pikanäppäimet - hint: >- - Tip: Muista käyttää CTRL, VAIHTO and ALT! Ne ottavat käyttöön erilaisia sijoitteluvaihtoehtoja. - - resetKeybindings: Nollaa Pikanäppäimet - + hint: "Tip: Muista käyttää CTRL, SHIFT ja ALT! Ne ottavat käyttöön erilaisia + sijoitteluvaihtoehtoja." + resetKeybindings: Nollaa pikanäppäimet categoryLabels: general: Sovellus ingame: Peli navigation: Navigointi placement: Sijoitus - massSelect: Massa Valinta + massSelect: Massavalinta buildings: Rakennus Pikanäppäimet placementModifiers: Sijoittelu Muokkaajat - mappings: confirm: Vahvista back: Takaisin @@ -795,70 +928,73 @@ keybindings: mapMoveLeft: Liiku Vasemmalle mapMoveFaster: Liiku Nopeammin centerMap: Keskitä Kartta - mapZoomIn: Lähennä mapZoomOut: Loitonna createMarker: Luo merkki - menuOpenShop: Päivitykset menuOpenStats: Tilastot - toggleHud: Vaihda valikon näkyvyys toggleFPSInfo: Vaihda FPS and Virheenkorjaus tiedot switchLayers: Vaihda tasoa exportScreenshot: Vie koko tukikohta kuvana - 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 - + belt: Liukuhihna + underground_belt: Tunneli + miner: Kaivaja + cutter: Leikkuri + rotater: Kääntäjä + stacker: Pinoaja + mixer: Värinsekoittaja + painter: Värjääjä + trash: Roskakori + wire: Johto pipette: Pipetti rotateWhilePlacing: Käännä - rotateInverseModifier: >- - Modifier: Käännä sen sijaan vastapäivään + rotateInverseModifier: "Modifier: Käännä sen sijaan vastapäivään" cycleBuildingVariants: Valitse muotoja confirmMassDelete: Poista alue pasteLastBlueprint: Liitä viimeisin piirustus cycleBuildings: Valitse Rakennuksia lockBeltDirection: Ota liukuhihnasuunnittelija käyttöön - switchDirectionLockSide: >- - Planner: Muuta sivua - + switchDirectionLockSide: "Planner: Muuta sivua" massSelectStart: Pidä pohjassa ja raahaa aloittaaksesi massSelectSelectMultiple: Valitse useita alueita massSelectCopy: Kopioi alue massSelectCut: Leikkaa alue - placementDisableAutoOrientation: Poista automaattinen suunta käytöstä placeMultiple: Pysy sijoittamistilassa - placeInverse: Käännä automaattinen hihnan suunta - menuClose: Close Menu - + placeInverse: Käännä automaattinen hihnan suunta päinvastoin + menuClose: Sulje valikko + balancer: Balancer + storage: Storage + constant_signal: Constant Signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" about: title: Tietoja tästä pelistä body: >- - Tämä peli on avoimen lähdekoodin ja kehitettä on Tobias Springer (tämä on minä).

+ Tämä peli on avointa lähdekoodia ja kehittäjä on Tobias Springer + (tämä on minä).

- Jos haluat osallistua, tarkista shapez.io githubissa.

+ 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 mahdollista ilman suurta Discord -yhteisöä pelini ympärillä - Sinun kannattaisi liittyä Discord palvelimelleni!

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

Lopuksi, isot kiitokset minun parhaalle kaverilleni Niklas - Ilman meidän factorio istuntoja tätä peliä ei olisi koskaan ollut olemassa. - changelog: title: Muutosloki - demo: features: restoringGames: Tallennusten palautus @@ -866,5 +1002,65 @@ demo: oneGameLimit: Rajoitettu yhteen tallennukseen customizeKeybindings: Pikanäppäinten mukautus exportingBase: Viedään koko tukikohta kuvana - settingNotAvailable: Ei saatavilla demoversiossa. +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetria on keskeistä! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - Sekoita kolmea väriä saadaksesi valkoista. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Tehokkuus on keskeistä! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Paina F4 nähdäksesi FPS laskurin ja virkistystaajuuden. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-fr.yaml b/translations/base-fr.yaml index 1f359f10..bb2ada7c 100644 --- a/translations/base-fr.yaml +++ b/translations/base-fr.yaml @@ -1,350 +1,269 @@ -# -# 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 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. + 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. + discordLinkShort: Discord officiel + intro: >- + Vous aimez les jeux d’automatisation ? Ce jeu est pour vous ! - # 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 est un jeu calme où vous devrez construire des usines pour produire automatiquement des formes géométriques. À mesure que le niveau augmente, les formes deviennent de plus en plus complexes, et vous devrez vous étendre sur la carte infinie. - shapez.io est un jeu où il faut construire des usines pour automatiser la création et la transformation de formes de plus en plus complexes sur une carte infinie. - En livrant les bonnes formes tu vas progresser dans le jeu et débloquer des améliorations pour accélerer ton usine. + Et en plus, vous devrez aussi produire de plus en plus pour satisfaire la demande. La seule solution est de construire en plus grand ! Au début vous ne ferez que découper les formes, mais plus tard vous devrez les peindre — et pour ça vous devrez extraire et mélanger des couleurs ! - Comme la demande de formes augmente, il va falloir agrandir ton usine pour produire plus - N'oublie pas les resources, il va falloir s'étendre tout autour de la [b]carte infinie[/b]! - - Puis il va falloir mélanger les couleurs et peindre tes formes avec - Combine du rouge, du bleu et du vert pour produire différente couleurs et peindre des formes pour satisfaire la demande. - - Ce jeu propose 18 niveaux progressifs (qui devraient vous occuper pendant des heures!) et j'ajoute constamment plus de contenu - Il y en a beaucoup qui arrive! - - Acheter le jeu te donnes accès à la version hors-ligne qui a plus de contenu et tu recevras l'accès aux nouvelles fonctionnalités. - - [b]Avantages de la version hors-ligne[/b] - - [list] - [*] Mode sombre - [*] Balises infinies - [*] Sauvegardes infinies - [*] Plus d'options - [*] Arrive bientôt: Câbles et éléctricité! Sort en Juillet 2020. - [*] Arrive bientôt: Plus de niveaux - [*] Me permet de plus développer le jeu ❤️ - [/list] - - [b]Mises à jours futures[/b] - - Je fais souvent des mises à jour et essaye d'en sortir une par semaine! - - [list] - [*] Plusieurs cartes et challenges (e.g. carte avec des obstacles) - [*] Puzzles (Livrer les formes avec des batiments limités/une carte limitée) - [*] Un mode histoire où les bâtiments ont un coût - [*] Générateur de carte configurable (Configure les ressources/formes leur taille, densité et plus) - [*] Plus de formes - [*] Meilleures performances (Le jeu est déja très optimisé!) - [*] Et bien plus! - [/list] - - [b]Ce jeu est open source![/b] - - Tout le monde peut contribuer, je suis très impliqué dans la communeauté et essaye de regarder toutes les suggestions et prendre les retours si possible. - Vas voir mon trello pour plus d'informations! - - [b]Liens[/b] - - [list] - [*] [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]Code source (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Aide à traduire[/url] - [/list] - - discordLink: Discord officiel - Parles avec moi! + En achetant le jeu sur Steam, vous aurez accès à la version complète, mais vous pouvez aussi jouer à une démo sur shapez.io et vous décider ensuite ! + title_advantages: Avantages de la version complète + advantages: + - 12 nouveaux niveaux avec 26 niveaux en tout + - 18 nouveaux bâtiments pour automatiser entièrement votre usine ! + - 20 niveaux d’amélioration pour s’amuser pendant des heures ! + - Les câbles ouvrent une toute nouvelle dimension ! + - Mode sombre ! + - Sauvegardes illimitées + - Balises illimitées + - Me soutenir ! ❤️ + title_future: Prévu + planned: + - Bibliothèque de patrons + - Succès sur Steam + - Mode réflexion + - Mini-carte + - Mods + - Mode bac à sable + - …et bien plus ! + title_open_source: Ce jeu est open source ! + text_open_source: >- + Tout le monde peut contribuer. Je suis très impliqué dans la communauté + et j’essaie de lire toutes les suggestions et de prendre en compte vos + retours quand c’est possible. + N’oubliez pas de consulter mon tableau Trello pour voir tout le plan de développement ! + title_links: Liens + links: + discord: Discord officiel + roadmap: Plan de développement + subreddit: Reddit + source_code: Code source (GitHub) + translate: Aidez à traduire global: loading: Chargement error: Erreur - - # 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" + thousandsDivider: 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 suffix: thousands: k millions: M billions: G trillions: T - - # Shown for infinitely big numbers - infinite: inf - + infinite: ∞ time: - # Used for formatting past time dates oneSecondAgo: il y a une seconde - xSecondsAgo: il y a secondes + xSecondsAgo: il y a  secondes oneMinuteAgo: il y a une minute - xMinutesAgo: il y a minutes + xMinutesAgo: il y a  minutes oneHourAgo: il y a une heure - xHoursAgo: il y a heures + xHoursAgo: il y a  heures oneDayAgo: il y a un jour xDaysAgo: il y a jours - - # Short formats for times, e.g. '5h 23m' - secondsShort: s - minutesAndSecondsShort: m s - hoursAndMinutesShort: h m - - xMinutes: minutes - + secondsShort:  s + minutesAndSecondsShort:  m  s + hoursAndMinutesShort:  h  m + xMinutes:  minutes keys: tab: TAB control: CTRL alt: ALT escape: ESC - shift: SHIFT + shift: MAJ space: ESPACE - demoBanners: - # This is the "advertisement" shown in the main menu and other various places - title: Version démo - intro: >- - Achetez la version complète pour débloquer toutes les fonctionnalités ! - + title: Version de démo + intro: Achetez la version complète pour débloquer toutes les fonctionnalités ! mainMenu: play: Jouer - changelog: Historique - importSavegame: Importer - openSourceHint: Ce jeu est open source ! - discordLink: Serveur Discord officiel - helpTranslate: Contribuez à la traduction ! - - # 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. - - savegameLevel: Niveau - savegameLevelUnknown: Niveau inconnu - continue: Continuer newGame: Nouvelle partie - madeBy: Créé par + changelog: Historique subreddit: Reddit - + importSavegame: Importer + openSourceHint: Ce jeu est open source ! + discordLink: Serveur Discord officiel + helpTranslate: Contribuez à la traduction ! + madeBy: Créé par + browserWarning: Désolé, ce jeu sera lent 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 + savegameUnnamed: Sans titre dialogs: buttons: ok: OK - delete: Effacer + delete: Supprimer cancel: Annuler later: Plus tard restart: Relancer reset: Réinitialiser - getStandalone: Se procurer la version complète + getStandalone: Obtenir 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 - importSavegameError: - title: Erreur d'importation - text: >- - Impossible d'importer votre sauvegarde: - + title: Erreur d’importation + text: "Impossible d’importer votre sauvegarde :" importSavegameSuccess: title: Sauvegarde importée - text: >- - Votre sauvegarde a été importée avec succès. - + text: Votre sauvegarde a été importée avec succès. gameLoadFailure: - title: Le jeu est cassé - text: >- - Impossible de charger votre sauvegarde: - + title: La sauvegarde est corrompue + text: "Impossible de charger votre sauvegarde :" confirmSavegameDelete: title: Confirmez la suppression - text: >- - Êtes-vous certains de vouloir supprimer votre partie ? - + text: Êtes-vous sûr de vouloir supprimer cette partie ?

” + au niveau

Ce sera définitif ! savegameDeletionError: title: Impossible de supprimer - text: >- - Impossible de supprimer votre sauvegarde: - + text: "Impossible de supprimer votre sauvegarde :" restartRequired: title: Redémarrage requis - text: >- - Vous devez relancer le jeu pour appliquer les modifications. - + text: Vous devez relancer le jeu pour appliquer les modifications. 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 desc: Ceci réinitialisera les touches par défaut. Veuillez confirmer. - keybindingsResetOk: title: Réinitialisation des contrôles - desc: Les contrôles ont été réinitialisés dans leur état par défaut respectifs ! - + desc: Les contrôles ont été remis à défaut ! featureRestriction: - title: Version démo - desc: Vous avez essayé d'accéder à la fonction () qui n'est pas disponible dans la démo. Considérez l'achat de la version complète pour une expérience optimale ! - + title: Version de démo + desc: Vous avez essayé d’accéder à la fonction “” qui n’est pas + disponible dans la démo. Pensez à acheter la version complète pour + une expérience optimale ! oneSavegameLimit: title: Sauvegardes limitées - 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 ! - + 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 bien de vous procurer la + version complète ! updateSummary: - title: Nouvel mise-à-jour ! - desc: >- - Voici les modifications depuis votre dernière session: - + title: Nouvelle mise à jour ! + desc: "Voici les changements depuis votre dernière session de jeu :" upgradesIntroduction: title: Débloquer les améliorations - desc: >- - Toutes les formes que vous produisez peuvent être utilisées pour débloquer des améliorations - Ne détruisez pas vos anciennes usines ! - L'onglet des améliorations se trouve dans le coin supérieur droit de l'écran. - + desc: Toutes les formes que vous produisez peuvent être utilisées pour débloquer + des améliorations — Ne détruisez pas vos anciennes + usines ! L’onglet des améliorations se trouve dans le coin + supérieur droit de l’écran. massDeleteConfirm: - title: Confirmation de suppression - desc: >- - Vous allez supprimer pas mal de bâtiments ( pour être exact) ! Êtes vous certains de vouloir faire cela ? - + title: Confirmer la suppression + desc: Vous allez supprimer beaucoup de bâtiments ( pour être précis) ! + Êtes-vous sûr 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 ? - + desc: Vous allez couper beaucoup de bâtiments ( pour être précis) ! + Êtes-vous sûr de vouloir faire ça ? + massCutInsufficientConfirm: + title: Confirmer la coupure + desc: Vous n’avez pas les moyens de copier cette zone ! Êtes-vous sûr de vouloir + la couper ? blueprintsNotUnlocked: title: Pas encore débloqué - desc: >- - Les patrons n'ont pas encore étés débloqués ! Terminez encore quelques niveaux pour y avoir accès. - + desc: Terminez le niveau 12 pour avoir accès aux patrons ! keybindingsIntroduction: title: Raccourcis utiles - desc: >- - Le jeu a plein de 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.
- ALT: Inverse l'orientation des convoyeurs placés.
- + desc: '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 / supprimer.
MAJ : + Laissez appuyé pour placer plusieurs fois le même bâtiment.
+ ALT : Inverse l’orientation des + convoyeurs placés.
' 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: Modifier cette balise + desc: Donnez-lui un nom. Vous pouvez aussi inclure le raccourci + d’une forme (que vous pouvez générer ici). + editSignal: + title: Définir le signal + descItems: "Choisissez un objet prédéfini :" + descShortKey: …ou entrez le raccourci d’une forme (que vous + pouvez générer ici) 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 ! - + desc: Vous ne pouvez créer que deux balises dans la démo. Achetez la version + complète pour en placer autant que vous voulez ! 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 ! - - massCutInsufficientConfirm: - title: Confirmer la coupe - desc: Vous n'avez pas les moyens de copier cette zone ! Êtes-vous certain de vouloir la couper ? - + title: Exporter une capture d’écran + desc: Vous avez demandé à exporter une capture d’écran de votre base. Soyez + conscient que cela peut s’avérer passablement lent pour une grande + base, voire faire planter votre jeu ! + renameSavegame: + title: Renommer la sauvegarde + desc: Vous pouvez renommer la sauvegarde ici. + tutorialVideoAvailable: + title: Tutoriel disponible + desc: Il y a un tutoriel vidéo pour ce niveau. Voulez-vous le regarder ? + tutorialVideoAvailableForeignLanguage: + title: Tutoriel disponible + desc: Il y a un tutoriel vidéo pour ce niveau, mais il n’est disponible qu’en + anglais. Voulez-vous le regarder ? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Déplacer - selectBuildings: Sélection d'une zone - stopPlacement: Arrêter le placement + selectBuildings: Sélection d’une zone + stopPlacement: Arrêter de placer rotateBuilding: Tourner le bâtiment placeMultiple: Placement multiple - reverseOrientation: Changer l'orientation - disableAutoOrientation: Désactiver l'orientation automatique - toggleHud: Basculer l'affichage tête haute (ATH) + reverseOrientation: Changer l’orientation + disableAutoOrientation: Désactiver l’orientation automatique + toggleHud: Basculer l’affichage tête haute (ATH) placeBuilding: Placer un bâtiment createMarker: Créer une balise delete: Supprimer pasteLastBlueprint: Copier le dernier patron - lockBeltDirection: Utiliser le plannificateur de convoyeurs - plannerSwitchSide: Échanger la direction du plannificateur + lockBeltDirection: Utiliser le planificateur de convoyeurs + plannerSwitchSide: Inverser la direction du planificateur cutSelection: Couper copySelection: Copier clearSelection: Effacer la sélection pipette: Pipette - switchLayers: Échanger les calques - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + switchLayers: Changer de calque + colors: + red: Rouge + green: Vert + blue: Bleu + yellow: Jaune + purple: Magenta + cyan: Cyan + white: Blanc + black: Noir + uncolored: Sans couleur 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: Appuyez sur pour alterner entre les variantes. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Raccourci: - + hotkeyLabel: "Raccourci : " infoTexts: speed: Vitesse range: Portée storage: Espace de stockage - oneItemPerSecond: 1 forme / s - itemsPerSecond: formes / s - itemsPerSecondDouble: (x2) - + oneItemPerSecond: 1 forme ⁄ s + itemsPerSecond:  formes ⁄ s + itemsPerSecondDouble: (×2) tiles: cases - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: Niveau + levelTitle: Niveau  completed: Terminé - unlockText: débloqué ! + unlockText: débloqué ! buttonNextLevel: Niveau suivant - - # Notifications on the lower right notifications: - newUpgrade: Une nouvelle amélioration est disponible ! + newUpgrade: Une nouvelle amélioration est disponible ! gameSaved: Votre partie a été sauvegardée. - - # The "Upgrades" window + freeplayLevelComplete: Niveau  complet ! shop: title: Améliorations buttonUnlock: Améliorer - - # Gets replaced to e.g. "Tier IX" - tier: Niveau - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: NIVEAU MAXIMAL (Vitesse x) - - # The "Statistics" window + tier: Niveau  + maximumLevel: NIVEAU MAX (Vitesse ×) statistics: title: Statistiques dataSources: @@ -353,429 +272,692 @@ 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 toutes les formes que votre usine produit, y compris les + formes intermédiaires. delivered: - title: Délivré - description: Affiche les formes qui ont été livrées dans votre centre. - noShapesProduced: Aucune forme n'a été produite jusqu'à présent. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + title: Livré + description: Affiche les formes qui ont été livrées dans votre bâtiment central. + noShapesProduced: Aucune forme produite pour le moment. + shapesDisplayUnits: + second:  ⁄ s + minute:  ⁄ m + hour:  ⁄ h settingsMenu: playtime: Temps de jeu - buildingsPlaced: Bâtiments beltsPlaced: Convoyeurs - - buttons: - continue: Continuer - settings: Options - menu: Retourner au menu - - # Bottom left tutorial hints tutorialHints: - title: Besoin d'aide ? + title: Besoin d’aide ? showHint: Indice hideHint: Fermer - - # When placing a blueprint blueprintPlacer: cost: Coût - - # Map markers waypoints: waypoints: Balise hub: Centre - description: Cliquez une balise pour vous y rendre, clic-droit pour l'effacer.

Appuyez sur pour créer une balise sur la vue actuelle, ou clic-droit pour en créer une sur l'endroit pointé. + description: Cliquez sur une balise pour vous y rendre, clic-droit pour la + supprimer.

Appuyez sur pour créer une balise + sur la vue actuelle, ou clic-droit pour en créer + une sur l’endroit pointé. creationSuccessNotification: La balise a été créée. - - # Interactive tutorial + shapeViewer: + title: Couches + empty: Vide + copyKey: Copier le raccourci interactiveTutorial: title: Tutoriel hints: - 1_1_extractor: Placez un extracteur sur une forme en cercle pour l'extraire ! - 1_2_conveyor: >- - 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. - - colors: - red: Rouge - green: Vert - blue: Bleu - yellow: Jaune - purple: Violet - cyan: Cyan - white: Blanc - uncolored: Non coloré - black: Noir - shapeViewer: - title: Calques - empty: Vide - copyKey: Touche de copie - -# All shop upgrades + 1_1_extractor: Placez un extracteur sur une forme en + cercle pour l’extraire ! + 1_2_conveyor: "Connectez l’extracteur avec un convoyeur vers + votre centre !

Astuce : Cliquez et faites + glisser le convoyeur avec la 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 but.

Astuce : Gardez + MAJ enfoncé pour placer plusieurs extracteurs, + et utilisez R pour les faire pivoter." + 2_1_place_cutter: "Maintenant, placez un découpeur pour + couper les cercles en deux.

PS : Le découpeur coupe toujours + de haut en bas quelle que soit son orientation." + 2_2_place_trash: Le découpeur peut se bloquer !

+ Utilisez la poubelle pour vous débarrasser des déchets + dont vous n’avez pas (encore) besoin. + 2_3_more_cutters: "Bravo ! Maintenant ajoutez deux découpeurs de + plus pour accélérer le processus !

+ PS : Utilisez les raccourcis clavier 0–9 pour accéder + plus rapidement aux bâtiments." + 3_1_rectangles: "Maintenant, extrayez des rectangles.Construisez + quatre extracteurs et connectez-les au centre.

+ PS : Gardez MAJ enfoncé en plaçant un convoyeur pour + activer le planificateur." + 21_1_place_quad_painter: Placez un quadruple peintre et + connectez des cercles et des couleurs + blanche et rouge ! + 21_2_switch_to_wires: Basculez sur le calque de câblage en appuyant sur + E.

Puis connectez les quatre + entrées du peintre avec des câbles ! + 21_3_place_button: Génial ! Maintenant, placez un + interrupteur et connectez-le avec des câbles ! + 21_4_press_button: "Appuyez sur le bouton pour qu’il émette un + signal vrai et active le peintre.

PS : Vous + n’êtes pas obligé de connecter toutes les entrées ! Essayez d’en brancher + seulement deux." + connectedMiners: + one_miner: 1 extracteur + n_miners:  extracteurs + limited_items: Limité à  + watermark: + title: Version de démo + desc: Cliquez ici pour voir les avantages de la version Steam ! + get_on_steam: Acheter sur Steam + standaloneAdvantages: + title: Obtenir la version complète + no_thanks: Non merci ! + points: + levels: + title: 12 nouveaux niveaux + desc: Pour un total de 26 niveaux ! + buildings: + title: 18 nouveaux bâtiments + desc: Automatisez entièrement votre usine ! + savegames: + title: Sauvegardes ∞ + desc: Autant que votre cœur le désire ! + upgrades: + title: 20 niveaux d’amélioration + desc: Cette version de démonstration n’en a que 5 ! + markers: + title: Balises ∞ + desc: Ne vous perdez plus jamais dans votre usine ! + wires: + title: Câbles + desc: Une toute nouvelle dimension ! + darkmode: + title: Mode sombre + desc: Plus jamais mal aux yeux ! + support: + title: Me soutenir + desc: Je le développe pendant mon temps libre ! shopUpgrades: belt: - name: Convoyeurs, Distributeurs et Tunnels - description: Vitesse x → x - + name: Convoyeurs, distributeurs et tunnels + description: Vitesse × → × miner: name: Extraction - description: Vitesse x → x - + description: Vitesse × → × processors: - name: Découpage, Rotation et Empilage - description: Vitesse x → x - + name: Découpage, rotation et empilage + description: Vitesse × → × painting: - name: Mélange et Peinture - description: Vitesse x → x - -# Buildings and their name / description + name: Mélange et peinture + description: Vitesse × → × buildings: - belt: - default: - name: &belt Convoyeur - description: Transporte les objects, maintenez et faites glisser pour en placer plusieurs. - - miner: # Internal name for the Extractor - default: - name: &miner Extracteur - description: Placez-le au dessus d'une forme ou couleur pour l'extraire. - - chainable: - name: Extracteur en série - description: Placez-le au dessus d'une forme ou couleur pour l'extraire. Peut être mis en série. - - underground_belt: # Internal name for the Tunnel - default: - name: &underground_belt Tunnel - description: Permet de faire passer des ressources en dessous de bâtiment et de convoyeurs. - - tier2: - name: Tunnel Niveau II - description: Permet de faire passer des ressources en dessous de bâtiment et de convoyeurs. - - splitter: # Internal name for the Balancer - default: - name: &splitter Répartiteur - description: Multifonctionnel - Distribue de manière équitable toutes les entrées vers toutes les sorties. - - compact: - name: Fusionneur (compact) - description: Fusionne deux convoyeurs en un. - - compact-inverse: - name: Fusionneur (compact) - description: Fusionne deux convoyeurs en un. - - cutter: - default: - name: &cutter Découpeur - description: Coupe une forme de haut en bas et sort les deux parties. Si vous n'utilisez qu'une seule partie, assurez-vous de détruite l'autre ou sinon, gare au blocage ! - quad: - name: Découpeur (Quatre) - description: Coupe une forme en quatre parties. Si vous n'utilisez pas toutes les parties, assurez-vous de détruite les autres ou sinon, gare au blocage ! - - rotater: - default: - name: &rotater Pivoteur - description: Fait pivoter une forme de 90 degrés vers la droite. - ccw: - name: Pivoteur inversé - description: Fait pivoter une forme de 90 degrés vers la gauche. - - stacker: - default: - name: &stacker Combineur - description: Combine deux formes. Si elles ne peuvent pas êtres combinées, la forme de droite est placée sur la forme de gauche. - - mixer: - default: - name: &mixer Mélangeur de couleur - description: Mélange deux couleurs en utilisant la synthèse additive des couleurs. - - painter: - default: - name: &painter Peintre - description: &painter_desc Colorie entièrement la forme de gauche avec la couleur de droite. - double: - name: Peintre (Double) - description: Colorie les deux formes de gauche avec la couleur de droite. - quad: - name: Peintre (Quadruple) - description: Permet de colorier chaque quadrant d'une forme avec une couleur différente. - mirrored: - name: *painter - description: *painter_desc - - trash: - default: - name: &trash Poubelle - description: Accepte des formes de n'importe quel côté et les détruit... pour toujours. - - storage: - name: Stockage - description: Stocke les formes en trop jusqu'à une certaine capacité. Peut être utilisé comme tampon. hub: - deliver: Délivrez + deliver: Livrez toUnlock: pour débloquer levelShortcut: NV + endOfDemo: Fin de la démo + belt: + default: + name: Convoyeur + description: Transporte les objets. Maintenez et faites glisser pour en placer + plusieurs. + miner: + default: + name: Extracteur + description: Placez-le au-dessus d’une forme ou couleur pour l’extraire. + chainable: + name: Extracteur en série + description: Placez-le au-dessus d’une forme ou couleur pour l’extraire. Peut + être mis en série. + underground_belt: + default: + name: Tunnel + description: Permet de faire passer des ressources sous les bâtiments et les + convoyeurs. + tier2: + name: Tunnel niveau II + description: Permet de faire passer des ressources sous les bâtiments et les + convoyeurs. + balancer: + default: + name: Répartiteur + description: Multifonctions — Distribue équitablement toutes les entrées vers + toutes les sorties. + merger: + name: Fusionneur (compact) + description: Fusionne deux convoyeurs en un seul. + merger-inverse: + name: Fusionneur (compact) + description: Fusionne deux convoyeurs en un seul. + splitter: + name: Séparateur (compact) + description: Sépare un convoyeur en deux. + splitter-inverse: + name: Séparateur (compact) + description: Sépare un convoyeur en deux. + cutter: + default: + name: Découpeur + description: Coupe une forme de haut en bas et sort les deux parties. Si + vous n’utilisez qu’une seule partie, assurez-vous de détruire + l’autre ou sinon, gare au blocage ! + quad: + name: Découpeur (quadruple) + description: Coupe une forme en quatre parties. Si vous n’utilisez pas + toutes les parties, assurez-vous de détruire les autres ou + sinon, gare au blocage ! + rotater: + default: + name: Pivoteur + description: Fait pivoter une forme de 90 degrés vers la droite. + ccw: + name: Pivoteur inversé + description: Fait pivoter une forme de 90 degrés vers la gauche. + rotate180: + name: Retourneur + description: Tourne une forme de 180 degrés. + stacker: + default: + name: Combineur + description: Combine deux formes. Si elles ne peuvent pas être combinées, la + forme de droite est placée sur la forme de gauche. + mixer: + default: + name: Mélangeur de couleur + description: Mélange deux couleurs en utilisant la synthèse additive des + couleurs. + painter: + default: + name: Peintre + description: Colorie entièrement la forme venant de gauche avec la couleur + entrant en haut. + mirrored: + name: Peintre + description: Colorie entièrement la forme venant de gauche avec la couleur + entrant en bas. + double: + name: Peintre (double) + description: Colorie les deux formes venant de gauche avec la couleur entrant en + haut. + quad: + name: Peintre (quadruple) + description: Colorie chaque quadrant d’une forme avec une couleur différente. + Seules les entrées recevant un signal vrai sur + le calque de câblage seront peintes ! + trash: + default: + name: Poubelle + description: Accepte des formes de n’importe quel côté et les détruit… pour + toujours. + storage: + default: + name: Stockage + description: Stocke les formes en trop jusqu’à une certaine capacité. Peut être + utilisé pour absorber un surplus. wire: default: - name: Ligne énergétique - description: Vous permet de transporter de l'énergie. - advanced_processor: + name: Câble + description: Transfère des signaux, qui peuvent être des formes, des couleurs ou + des booléens (1 / 0). Les câbles de couleurs différentes ne se + connectent pas. + second: + name: Câble + description: Transfère des signaux, qui peuvent être des formes, des couleurs ou + des booléens (1 / 0). Les câbles de couleurs différentes ne se + connectent pas. + wire_tunnel: default: - name: Inverseur de couleur - description: Accepte une couleur ou une forme et l'inverse - energy_generator: - deliver: Délivrer - toGenerateEnergy: Pour + name: Tunnel à câble + description: Permet de croiser deux câbles sans les connecter entre eux. + constant_signal: default: - name: Générateur d'énergie - description: Génère de l'énergie en consommant des formes. - wire_crossings: + name: Constante + description: Émet un signal constant, qui peut être une forme, une couleur ou un + booléen (1 / 0). + lever: default: - name: Duplicateur de ligne - description: Sépare une ligne énergétique en deux. - merger: - name: Fusionneur de ligne - description: Fusionne deux lignes énergétiques en une seule. - + name: Interrupteur + description: Peut être basculé pour émettre un signal booléen (1 / 0) sur le + calque de câblage, qui peut être utilisé pour contrôler par + exemple un filtre à formes. + logic_gate: + default: + name: Porte ET + description: Émet un “1” booléen si les deux entrées sont vraies (une forme, + couleur ou “1”). + not: + name: Porte INVERSEUR + description: Émet un “1” booléen si l’entrée n’est pas vraie (une forme, couleur + ou “1”). + xor: + name: Porte OU-EXCLUSIF + description: Émet un “1” booléen si une des entrées est vraie (une forme, + couleur ou “1”), mais pas les deux. + or: + name: Porte OU + description: Émet un “1” booléen si une des entrées est vraie (une forme, + couleur ou “1”). + transistor: + default: + name: Transistor + description: Transmet l’entrée du bas si l’entrée du côté est vraie (une forme, + couleur ou “1”). + mirrored: + name: Transistor + description: Transmet l’entrée du bas si l’entrée du côté est vraie (une forme, + couleur ou “1”). + filter: + default: + name: Filtre + description: Connectez un signal pour envoyer toutes les formes et couleurs + correspondantes en haut, et tout le reste à droite. Fonctionne + aussi avec un signal booléen. + display: + default: + name: Afficheur + description: Connectez un signal pour l’afficher. Ça peut être une forme, une + couleur, ou un booléen. + reader: + default: + name: Lecteur de débit + description: Mesure le débit d’un convoyeur. Émet sur le calque de câblage (une + fois déverrouillé) la dernière forme ou couleur mesurée. + analyzer: + default: + name: Analyseur de formes + description: Analyse le quadrant supérieur droit de la couche la plus basse + d’une forme, et renvoie sa forme et sa couleur. + comparator: + default: + name: Comparateur + description: Émet un “1” booléen si les deux entrées sont exactement les mêmes. + Peut comparer des formes, des couleurs, et des booléens. + virtual_processor: + default: + name: Découpeur virtuel + description: Découpe virtuellement une forme. + rotater: + name: Pivoteur virtuel + description: Fait pivoter virtuellement la forme de 90 degrés vers la droite. + unstacker: + name: Décombineur virtuel + description: Renvoie la couche supérieure à droite, et les couches restantes à + gauche. + stacker: + name: Combineur virtuel + description: Combine virtuellement la forme de droite sur celle de gauche. + painter: + name: Peintre virtuel + description: Peint virtuellement la forme du bas avec la couleur de droite. + item_producer: + default: + name: Générateur d’objet + description: Seulement disponible en mode bac à sable. Renvoie le signal du + calque de câblage sur le calque normal. storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: - title: Découper des formes - desc: Vous venez de débloquer le découpeur - il coupe des formes en deux de haut en bas quel que soit son orientation !

Assurez-vous de vous débarasser des déchets, sinon gare au blocage - À cet effet, je mets à votre disposition la poubelle, qui détruit tout ce que vous y mettez ! - + title: Découpage de formes + desc: Vous avez débloqué le découpeur. Il coupe des formes en + deux de haut en bas quelle que soit son + orientation !

Assurez-vous de vous débarrasser des déchets, + sinon gare au blocage. À cet effet, je mets à votre + disposition la poubelle, qui détruit tout ce que vous y mettez ! reward_rotater: title: Rotation - desc: Le pivoteur a été débloqué ! Il pivote les formes de 90 degrés vers la droite. - + desc: Le pivoteur a été débloqué ! Il pivote les formes de 90 + degrés vers la droite. reward_painter: title: Peintre - desc: >- - Le peintre a été débloqué - Extrayez des pigments de couleur (comme vous le faites avec les formes) et combinez les avec une forme dans un peintre pour les colorier !

PS: Si vous êtes daltonien, il y a un mode daltonien paramétrable dans les préférences ! - + desc: "Le peintre a été débloqué. Extrayez des pigments de + couleur (comme vous le faites avec les formes) et combinez-les avec + une forme dans un peintre pour les colorier !

PS : Si vous + êtes daltonien, il y a un mode daltonien + paramétrable dans les préférences !" reward_mixer: title: Mélangeur de couleurs - desc: Le mélangeur a été débloqué - Combinez deux couleurs en utilisant la synthèse additive des couleurs avec ce bâtiment ! - + desc: Le mélangeur a été débloqué. Combinez deux couleurs en + utilisant la synthèse additive des couleurs avec ce + bâtiment ! 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. - - reward_splitter: - title: Distributeur/Rassembleur - desc: Le répartiteur multifonctionnel a été débloqué - Il peut être utilisé pour construire de plus grandes usines en distribuant équitablement et rassemblant les formes entre plusieurs convoyeurs !

- + desc: Vous pouvez maintenant combiner deux formes avec le + combineur ! Les deux entrées sont combinées et si + elles peuvent être 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. + reward_balancer: + title: Répartiteur + desc: Le répartiteur multifonctionnel a été débloqué. Il peut + être utilisé pour construire de plus grandes usines en + distribuant équitablement et rassemblant les formes + entre plusieurs convoyeurs !

reward_tunnel: title: Tunnel - desc: Le tunnel a été débloqué - À présent il devient possible de faire passer des formes sous les convoyeurs et les bâtiments ! - + desc: Le tunnel a été débloqué. Vous pouvez maintenant faire + passer des formes sous les convoyeurs et les bâtiments ! reward_rotater_ccw: title: Pivoteur inversé - desc: Vous avez débloqué une variante du pivoteur - Elle permet de faire pivoter vers la gauche ! Pour le construire, sélectionnez le pivoteur et appuyez sur 'T' pour alterner entre les variantes ! - + desc: Vous avez débloqué une variante du pivoteur. Elle permet + de faire pivoter vers la gauche ! Pour le construire, sélectionnez + le pivoteur et appuyez sur “T” pour alterner entre les + variantes ! reward_miner_chainable: title: Extracteur en série - desc: Vous avez débloqué l'extracteur en série ! Il permet de transférer ses resources à d'autres extracteurs pour augmenter le débit sortant ! - + desc: "Vous avez débloqué l’extracteur en série ! Il permet de + transférer ses ressources à d’autres extracteurs + pour augmenter le débit sortant !

Note : Il remplace + l’ancien extracteur dans votre barre d’outils." reward_underground_belt_tier_2: title: Tunnel niveau II - desc: Vous avez débloqué une nouvelle variante du tunnel - Elle a une portée plus grande, et vous pouvez à présent superposer les deux variantes de tunnels ! - - reward_splitter_compact: + desc: Vous avez débloqué une nouvelle variante du tunnel — Elle + a une portée plus grande, et vous pouvez superposer + les deux variantes de tunnels ! + reward_merger: + title: Fusionneur compact + desc: Vous avez débloqué le fusionneur, une variante du + répartiteur. Il accepte deux entrées et les fusionne en un + seul convoyeur ! + reward_splitter: title: Répartiteur compact - desc: >- - Vous avez débloqué une variante compacte du répartiteur - Elle accepte deux entrées et les rassemble en une sortie ! - + desc: Vous avez débloqué une variante compacte du répartiteur — + Il accepte une seule entrée et la divise en deux sorties ! + reward_belt_reader: + title: Lecteur de débit + desc: Vous avez débloqué le lecteur de débit ! Il vous permet + de mesurer le débit d’un convoyeur.

Et attendez de + déverrouiller les câbles, il sera alors très utile ! reward_cutter_quad: title: Quadruple découpeur - desc: Vous avez débloqué une variante du découpeur - Elle permet de découper les formes en quatre parties à la place de simplement deux ! - + desc: Vous avez débloqué une variante du découpeur — Elle + permet de découper les formes en quatre parties + plutôt que seulement deux ! reward_painter_double: title: Double peintre - desc: Vous avez débloqué une variante du peintre - Elle fonctionne comme le peintre de base, mais elle permet de traiter deux formes à la fois en ne consommant qu'une couleur au lieu de deux ! - - reward_painter_quad: - title: Quadruple peintre - desc: Vous avez débloqué une variante du peintre - Elle permet de colorier chaque partie d'une forme individuellement ! - + desc: Vous avez débloqué une variante du peintre — Elle + fonctionne comme le peintre de base, mais elle permet de traiter + deux formes à la fois en ne consommant qu’une + couleur au lieu de deux ! reward_storage: title: Tampon de stockage - desc: Vous avez débloqué une variante de la poubelle - Elle permet de stocker des formes jusqu'à une certaine limite ! - - reward_freeplay: - title: Mode libre - desc: Vous y êtes arrivé ! Vous avez débloqué le mode libre ! Cela veut dire que dorénavant, les formes sont générées aléatoirement ! (Ne vous en faites pas, plus de contenu est prévu pour la version complète !) - + desc: Vous avez débloqué le bâtiment de stockage. Il permet de + stocker des objets jusqu’à une certaine limite !

Il priorise + la sortie gauche, vous pouvez donc aussi l’utiliser comme + drain de débordement ! reward_blueprints: 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 + desc: Vous pouvez maintenant copier et coller des parties de + votre usine ! 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). + reward_rotater_180: + title: Retourneur + desc: Vous avez débloqué le retourneur ! Il permet de faire + pivoter une forme de 180 degrés (Surprise ! :D) + reward_wires_painter_and_levers: + title: Câbles & quadruple peintre + desc: "Vous avez débloqué le calque de câblage : C’est un + calque au-dessus du calque normal, qui introduit beaucoup de + nouvelles mécaniques de jeu !

Pour commencer, je vous + débloque le quadruple peintre. Connectez les + entrées à peindre sur le calque de câblage.

Pour voir le + calque de câblage, appuyez sur E.

PS : Activez + les indices dans les paramètres pour voir un tutoriel + sur le câblage." + reward_filter: + title: Filtre à objets + desc: Vous avez débloqué le filtre à objets ! Il dirige les + objets en haut ou à droite selon qu’ils correspondent ou non au + signal provenant du calque de câblage.

Vous pouvez aussi + connecter un signal booléen (1 / 0) pour l’activer ou le désactiver + complètement. + reward_display: + title: Afficheur + desc: "Vous avez débloqué l’afficheur ! Connectez-y un signal + sur le calque de câblage pour afficher une couleur, une forme ou un + booléen !

PS : Avez-vous remarqué que le lecteur de débit et + le stockage émettent le dernier objet vu ? Essayez de le montrer sur + un écran !" + reward_constant_signal: + title: Constante + desc: Vous avez débloqué l’émetteur de constante sur le calque + de câblage ! Vous pouvez par exemple la connecter à des + filtres à objets.

La constante peut émettre + une forme, une couleur ou un + booléen (1 / 0). + reward_logic_gates: + title: Portes logiques + desc: "Vous avez débloqué les portes logiques ! Vous n’êtes pas + obligé de trouver ça génial, mais en fait c’est super cool !

+ Avec ces portes, vous pouvez maintenant faire les opérations + booléennes ET, OU, OU-EXCLUSIF et INVERSEUR !

Et la cerise + sur le gâteau : je vous donne aussi le + transistor !" + reward_virtual_processing: + title: Traitement virtuel + desc: Je viens de vous donner tout un tas de nouveaux bâtiments qui vous + permettent de simuler le traitement des + formes !

Vous pouvez maintenant simuler un + découpeur, un pivoteur, un combineur et plus encore sur le calque de + câblage !

Avec ça, vous avez trois possibilités pour + continuer le jeu :

- Construire une machine + automatisée pour fabriquer n’importe quelle forme demandée + par le centre (je conseille d’essayer !).

- Construire + quelque chose de cool avec des câbles.

- Continuer à jouer + normalement.

Dans tous les cas, l’important c’est de + s’amuser ! no_reward: title: Niveau suivant - desc: >- - Ce niveau n'a pas de récompense mais le prochain, oui !

PS: Vous ne devriez pas détruire votre usine actuelle - Vous aurez besoin de toutes ces formes plus tard pour débloquer des améliorations - + desc: "Ce niveau n’a pas de récompense mais le prochain, si !

PS : Ne + détruisez pas votre usine actuelle. Vous aurez besoin de + toutes ces formes plus tard pour débloquer + des améliorations." no_reward_freeplay: title: Niveau suivant - desc: >- - Bravo ! À propos, plus de contenu est prévu pour la version complète ! - + desc: Bravo ! + reward_freeplay: + title: Mode libre + desc: Vous y êtes arrivé ! Vous avez débloqué le mode libre ! + Cela veut dire que dorénavant, les formes sont générées + aléatoirement !

Comme le centre va demander + un gros débit à partir de maintenant, je recommande + vivement de construire une machine qui fabrique automatiquement la + forme demandée.

Le centre émet la forme demandée sur le + calque de câblage, donc vous n’avez qu’à l’analyser et l’utiliser + pour configurer automatiquement votre usine. + reward_demo_end: + title: Fin de la démo + desc: Vous avez atteint la fin de la version de démo ! settings: title: Options categories: - game: Jeu - app: Application - + general: Général + userInterface: Interface utilisateur + advanced: Avancé + performance: Performance versionBadges: dev: Développement staging: Test prod: Production - buildDate: Créé le - + buildDate: Créé + rangeSliderPercentage:  % labels: uiScale: - title: Taille de l'interface - description: >- - Change la taille de l'interface utilisateur. Cette interface se redimensionnera suivant la résolution de votre appareil, mais cette option contrôle le facteur de résolution. + title: Taille de l’interface + description: Change la taille de l’interface utilisateur. Cette interface se + redimensionnera suivant la résolution de votre écran, mais cette + option contrôle le facteur de résolution. scales: super_small: Très petite small: Petite regular: Normale - large: Large - huge: Très large - + large: Grande + huge: Très grande + autosaveInterval: + title: Fréquence des sauvegardes automatiques + description: Contrôle avec quelle fréquence le jeu sera sauvegardé + automatiquement. Vous pouvez aussi entièrement désactiver cette + fonctionnalité ici. + intervals: + one_minute: 1 minute + two_minutes: 2 minutes + five_minutes: 5 minutes + ten_minutes: 10 minutes + twenty_minutes: 20 minutes + disabled: Désactivé scrollWheelSensitivity: title: Sensibilité du zoom - description: >- - Change la sensibilité du zoom (aussi bien de la roulette de la souris que du pavé tactile). + description: Change la sensibilité du zoom (roulette de la souris et pavé + tactile). sensitivity: - super_slow: Super lent + super_slow: Très lent slow: Lent regular: Normal fast: Rapide - super_fast: Super rapide - - fullscreen: - title: Plein écran - description: >- - Il est recommandé de jouer au jeu en plein écran pour obtenir la meilleure expérience possible. Seulement disponible dans la version complète. - - soundsMuted: - title: Sons désactivés - description: >- - Si coché, tous les sons seront désactivés. - - musicMuted: - title: Musique désactivée - description: >- - Si coché, toute la musique sera désactivée. - - theme: - title: Thème - description: >- - Choisissez votre thème (clair / sombre). - - themes: - dark: Sombre - light: Clair - - refreshRate: - title: Fréquence de simulation - description: >- - Si vous avez un moniteur à fréquence élevée, changez le taux de rafraichissement pour que le jeu fonctionne correctement à cette haute fréquence. Ceci pourrait cependant diminuer vos IPS (itérations par seconde) si votre ordinateur est trop lent. - - alwaysMultiplace: - title: Placement multiple - description: >- - Si activé, tous les bâtiments resterons sélectionnés tant que vous n'aurez pas annulé. Ceci revient à garder la touche SHIFT appuyée en permanence. - - offerHints: - title: Indices - description: >- - Affiche ou non le bouton 'Afficher un indice' dans le coin inférieur gauche. - - language: - title: Langage - description: >- - Change le langage. Toutes les traductions sont des contributions des utilisateurs et pourraient être partiellement incomplètes ! - + super_fast: Très rapide movementSpeed: title: Vitesse de déplacement - description: Change la vitesse à laquelle l'écran se déplace lors de l'utilisation du clavier. + description: Change la vitesse de déplacement de l’écran avec les touches du + clavier. speeds: - super_slow: Super lent + super_slow: Très lent slow: Lent regular: Normal fast: Rapide super_fast: Très rapide extremely_fast: Extrêmement rapide + language: + title: Langue + description: Change la langue. Les traductions sont une contribution des + utilisateurs et peuvent être incomplètes ! + enableColorBlindHelper: + title: Mode daltonien + description: Active divers outils qui permettent de jouer à ce jeu si vous êtes + daltonien. + fullscreen: + title: Plein écran + description: Il est recommandé de jouer au jeu en plein écran pour obtenir la + meilleure expérience possible. Seulement disponible dans la + version complète. + soundsMuted: + title: Sons désactivés + description: Si coché, tous les sons seront désactivés. + musicMuted: + title: Musique désactivée + description: Si coché, toute la musique sera désactivée. + soundVolume: + title: Volume du son + description: Régler le volume des effets sonores + musicVolume: + title: Volume de la musique + description: Régler le volume de la musique + theme: + title: Thème + description: Choisissez votre thème (clair / sombre). + themes: + dark: Sombre + light: Clair + refreshRate: + title: Fréquence de rafraîchissement + description: Détermine la fréquence de simulation du jeu par seconde. En + général, un taux de rafraîchissement plus élevé se traduit par + une meilleure précision mais une performance plus mauvaise. Si + la fréquence de rafraîchissement est basse, les débits peuvent + ne pas être exacts. + alwaysMultiplace: + title: Placement multiple + description: Si activé, tous les bâtiments resteront sélectionnés tant que vous + n’aurez pas annulé. Ceci revient à garder la touche MAJ appuyée + en permanence. + offerHints: + title: Indices + description: Affiche ou non le bouton “Afficher un indice” dans le coin + inférieur gauche. 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. + 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: >- - Permet l'affichage de l'effet de vignette qui assombrit les coins de l'écran afin de rendre le texte plus facile à lire. - - autosaveInterval: - title: Fréquence des sauvegardes automatiques - description: >- - Contrôle avec quelle fréquence le jeu sera sauvegardé automatiquement. Vous pouvez aussi entièrement désactiver cette fonctionnalité ici. - intervals: - one_minute: 1 Minute - two_minutes: 2 Minutes - five_minutes: 5 Minutes - 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: >- - Désactive la boîte de dialogue qui s'affiche lorsque vous vous apprêtez à couper/effacer plus de 100 entités. - - enableColorBlindHelper: - title: Mode Daltonien - description: Active divers outils qui permettent de jouer à ce jeu si vous êtes daltonien. + description: Active l’effet de vignette qui assombrit les coins de l’écran pour + rendre le texte plus facile à lire. 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. - + 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 agréable si vous alternez fréquemment + entre le placement de différents types de bâtiments. + 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. Si désactivé, montre une description + et une image. + disableCutDeleteWarnings: + title: Désactive les avertissements pour Couper / Supprimer + description: Désactive la boîte de dialogue qui s’affiche lorsque vous vous + apprêtez à couper / supprimer plus de 100 entités. + lowQualityMapResources: + title: Ressources de la carte de plus basse qualité + description: Simplifie le rendu des ressources sur la carte lorsqu’elle est + zoomée pour améliorer les performances. Ça donne un rendu encore + plus propre, alors essayez-le ! + disableTileGrid: + title: Désactiver la grille de placement + description: Désactiver la grille de placement peut améliorer les performances. + Ça rend aussi l’apparence plus unie ! + clearCursorOnDeleteWhilePlacing: + title: Déselectionner avec le clic droit + description: Activé par défaut. Désélectionne le bâtiment choisi pour la + construction lorsque vous faites un clic droit sur un bâtiment + existant. Si désactivé, vous pouvez détruire des bâtiments avec + un clic droit puis continuer de placer le bâtiment sélectionné. + lowQualityTextures: + title: Textures de basse résolution (moche) + description: Utilise des textures de basse qualité pour améliorer les + performances. Rend le jeu très moche ! + displayChunkBorders: + title: Montrer les secteurs + description: Le jeu est divisé en secteurs de 16×16 cases. Si ce réglage est + activé, les limites de chaque secteur sont affichées. + pickMinerOnPatch: + title: Choisir l’extracteur sur un gisement de ressources + description: Activé par défaut, sélectionne l’extracteur si vous utilisez la + pipette en survolant un gisement de ressources. + simplifiedBelts: + title: Convoyeurs simplifiés (moche) + description: Désactive le rendu des formes et couleurs sur les convoyeurs sauf + lors du survol du convoyeur pour améliorer les performances. Je + ne recommande pas de jouer avec ce réglage si vous n’avez pas + absolument besoin de performance. + enableMousePan: + title: Activer le déplacement à la souris + description: Permet de déplacer la carte en déplaçant le curseur sur les bords + de l’écran. La vitesse dépend du réglage de la vitesse de + déplacement. + zoomToCursor: + title: Zoomer vers le curseur + description: Si activé, zoome vers la position de la souris ; sinon, vers le centre de l’écran. + mapResourcesScale: + title: Taille des ressources sur la carte + description: Contrôle la taille des formes sur la vue d’ensemble de la carte visible en dézoomant. keybindings: title: Contrôles - hint: >- - Astuce: Soyez sûr d'utiliser CTRL, SHIFT et ALT ! Ces touches activent différentes options de placement. - + hint: "Astuce : N’oubliez pas d’utiliser CTRL, MAJ et ALT ! Ces touches activent + différentes options de placement." resetKeybindings: Réinitialiser les contrôles - categoryLabels: general: Application ingame: Jeu navigation: Navigation placement: Placement - massSelect: Suppression de zone + massSelect: Sélection de zone buildings: Raccourcis bâtiment placementModifiers: Modificateurs de placement - mappings: confirm: Confirmer back: Retour @@ -783,88 +965,159 @@ keybindings: mapMoveRight: Aller à droite mapMoveDown: Aller en bas mapMoveLeft: Aller à gauche + mapMoveFaster: Se déplacer plus vite centerMap: Centrer la carte - mapZoomIn: Zoom avant mapZoomOut: Zoom arrière createMarker: Créer une balise - menuOpenShop: Améliorations menuOpenStats: Statistiques - - toggleHud: Basculer l'affichage tête haute (ATH) - toggleFPSInfo: Basculer l'affichage des IPS (itérations par seconde) et des informations de débogage - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + menuClose: Fermer le menu + toggleHud: Basculer l’affichage tête haute (ATH) + toggleFPSInfo: Basculer l’affichage des IPS (itérations par seconde) et des + informations de débogage + switchLayers: Basculer le calque + exportScreenshot: Exporter une image de toute la base + belt: Convoyeur + balancer: Répartiteur + underground_belt: Tunnel + miner: Extracteur + cutter: Découpeur + rotater: Pivoteur + stacker: Combineur + mixer: Mélangeur de couleur + painter: Peintre + trash: Poubelle + storage: Stockage + wire: Câble + constant_signal: Constante + logic_gate: Porte logique + lever: Interrupteur + filter: Filtre + wire_tunnel: Tunnel à câble + display: Afficheur + reader: Lecteur de débit + virtual_processor: Découpeur virtuel + transistor: Transistor + analyzer: Analyseur de formes + comparator: Comparateur + item_producer: Générateur d’objets (bac à sable) + pipette: Pipette rotateWhilePlacing: Pivoter - rotateInverseModifier: >- - Variante: Pivote à gauche + rotateInverseModifier: "Variante : Pivote à gauche" cycleBuildingVariants: Alterner entre les variantes confirmMassDelete: Confirmer la suppression de la sélection + pasteLastBlueprint: Copier le dernier patron cycleBuildings: Alterner entre les bâtiments - - massSelectStart: Cliquez et maintenez pour commencer + lockBeltDirection: Utiliser le planificateur de convoyeurs + switchDirectionLockSide: "Planificateur : changer de côté" + copyWireValue: "Câble : Copier la valeur sous le curseur" + massSelectStart: Cliquez et glissez pour commencer massSelectSelectMultiple: Sélectionner plusieurs zones massSelectCopy: Copier la sélection - - placementDisableAutoOrientation: Désactiver l'orientation automatique - placeMultiple: Rester en mode placement - placeInverse: Inverser le mode d'orientation automatique - pasteLastBlueprint: Copier le dernier patron massSelectCut: Couper la sélection - exportScreenshot: Exporter toute la base en tant qu'image. - mapMoveFaster: Se déplacer plus vite - lockBeltDirection: Utiliser le plannificateur de convoyeurs - switchDirectionLockSide: "Plannificateur: changer de côté" - pipette: Pipette - menuClose: Fermer le Menu - switchLayers: Échanger les calques - advanced_processor: Inverseur de couleur - energy_generator: Générateur d'énergie - wire: Ligne énergétique - + placementDisableAutoOrientation: Désactiver l’orientation automatique + placeMultiple: Rester en mode placement + placeInverse: Inverser l’orientation des convoyeurs about: title: À propos de ce jeu body: >- - Ce jeu est open source et développé par Tobias Springer (c'est moi).

+ Ce jeu est open source et développé par Tobias Springer + (c’est moi).

- Si vous souhaitez contribuer, allez voir shapez.io sur github.

+ 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 - mes jeux - Vous devriez vraiment envisager de joindre le serveur discord !

+ Ce jeu n’aurait pas pu être réalisé sans la précieuse communauté Discord autour de mes jeux — Vous devriez vraiment rejoindre le serveur Discord !

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

- - Pour terminer, un immense merci à mon meilleur amis Niklas - Sans nos sessions sur factorio, ce jeu n'aurait jamais existé. + La bande son a été créée par Peppsen — Il est génial !

+ Pour terminer, un immense merci à mon meilleur ami Niklas — Sans nos sessions sur Factorio, ce jeu n’aurait jamais existé. changelog: title: Historique - demo: features: restoringGames: Charger des sauvegardes importingGames: Importer des sauvegardes oneGameLimit: Limité à une sauvegarde customizeKeybindings: Personnalisation des contrôles - exportingBase: Exporter toute la base en tant qu'image - + exportingBase: Exporter une image de toute la base settingNotAvailable: Indisponible dans la démo. -# -# 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 +tips: + - Le centre n’importe quelle forme, pas seulement la forme actuelle ! + - Assurez-vous que vos usines soient modulaires, cela paiera ! + - Ne construisez pas trop près du centre, ou ce sera un énorme chaos ! + - Si l’empilement ne fonctionne pas, essayez d’échanger les entrées. + - Vous pouvez changer le sens du planificateur de convoyeur en appuyant sur + R. + - Maintenir CTRL permet de déposer les convoyeurs sans + auto-orientation. + - Les ratios restent les mêmes, tant que toutes les améliorations sont au + même niveau. + - L’exécution en série est plus efficace qu’en parallèle. + - Vous débloquerez plus de variantes de bâtiments plus tard dans le jeu ! + - Vous pouvez utiliser T pour basculer entre différentes variantes. + - La symétrie est la clé ! + - Vous pouvez entrelacer différents niveaux de tunnels. + - Essayez de construire des usines compactes, cela paiera ! + - Le peintre a une variante en miroir que vous pouvez sélectionner avec + T + - Avoir les bons ratios de construction maximisera l’efficacité. + - Au niveau maximum, 5 extracteurs rempliront un seul convoyeur. + - N’oubliez pas les tunnels ! + - Vous n’avez pas besoin de répartir les objets uniformément pour une + efficacité totale. + - Maintenir MAJ activera le planificateur de convoyeur, vous + permettant de placer facilement de longues lignes de convoyeur. + - Les découpeurs coupent toujours verticalement, quelle que soit leur + orientation. + - Pour obtenir du blanc, mélangez les trois couleurs. + - Le stockage priorise la première sortie. + - Investissez du temps pour créer des patrons reproductibles, ça vaut le + coup ! + - Maintenir CTRL permet de placer plusieurs bâtiments. + - Vous pouvez maintenir ALT pour inverser la direction des convoyeurs + placés. + - L’efficacité est la clé ! + - Les gisements plus éloignés du centre produisent des formes plus complexes. + - Les machines ont une vitesse limitée, divisez-les pour une efficacité + maximale. + - Utilisez des répartiteurs pour maximiser votre efficacité. + - L’organisation est importante. Essayez de ne pas trop croiser les + convoyeurs. + - Planifiez à l’avance, ou ce sera un énorme chaos ! + - Ne supprimez pas vos anciennes usines ! Vous en aurez besoin pour + débloquer des améliorations. + - Essayez de réussir le niveau 18 par vous-même avant de demander de l’aide ! + - Ne compliquez pas les choses, essayez de rester simple et vous irez loin. + - Vous devrez peut-être réutiliser les usines plus tard dans le jeu. + Planifiez vos usines pour qu’elles soient réutilisables. + - Parfois, vous pouvez trouver une forme nécessaire sur la carte sans la + créer avec des combineurs. + - Les formes en hélice complètes ne peuvent jamais apparaître naturellement. + - Colorez vos formes avant de les découper pour une efficacité maximale. + - Avec les modules, l’espace n’est qu’une perception ; une préoccupation + pour les hommes mortels. + - Créez une usine de patrons à part. Ils sont importants pour les modules. + - Regardez de plus près le mélangeur de couleur et vous aurez la réponse à + vos questions. + - Utilisez CTRL + clic pour sélectionner une zone. + - Construire trop près du centre peut gêner les projets futurs. + - L’icône d’épingle à côté de chaque forme dans la liste d’améliorations + épingle la forme à l’écran. + - Mélangez toutes les couleurs primaires ensemble pour faire du blanc ! + - Vous avez une carte infinie, n’encombrez pas votre usine, développez-vous ! + - Essayez aussi Factorio ! C’est mon jeu préféré. + - Le découpeur quadruple coupe dans le sens des aiguilles d’une montre à + partir du coin supérieur droit ! + - Vous pouvez télécharger vos sauvegardes dans le menu principal ! + - Ce jeu a beaucoup de raccourcis clavier utiles ! Pensez à regarder la page + des paramètres. + - Ce jeu a beaucoup de paramètres, pensez à les regarder ! + - Le marqueur de votre centre a une petite boussole pour indiquer sa + direction ! + - Pour nettoyer les convoyeurs, coupez la zone puis collez-la au même + endroit. + - Appuyez sur F4 pour voir vos IPS et votre fréquence de rafraîchissement. + - Appuyez deux fois sur F4 pour voir les coordonnées. + - Cliquez sur une forme épinglée à gauche pour l’enlever. diff --git a/translations/base-hr.yaml b/translations/base-hr.yaml index d5858cb1..70f2bcb3 100644 --- a/translations/base-hr.yaml +++ b/translations/base-hr.yaml @@ -1,143 +1,63 @@ -# -# 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. -# - -# -# This is a message in Croatian to all potential contributers. -# -# Za buduće prevoditelje, htio sam na jednom mjestu imati prijevode glavnih -# komponenti igre, a ovaj prostor se činio dovoljno dobro mjesto za to. -# -# Siguran sam da znate kako je naš jezik malo manje fleksibilan što se tiče -# tehničkih pojmova. Teško je naći elegantan prijevod koji se ujedno čini i -# dovoljno dobar/precizan. Zato je svaka nova ideja dobro došla. Možete mi se -# slobodno javiti na Discordu da prokomentiramo eventualne prijevode ili -# novotvorenice za ovu igru. -# -# Prijevodi glavnih elemenata igre: -# GENERALNI POJMOVI -# + Shape = Oblik -# + Upgrade = Nadogradnja -# + Waypoint = Putokaz -# + Blueprint = Nacrt -# GRAĐEVINSKI ELEMENTI -# + Extractor = Rudar (od alternativnog izraza Miner) -# + Extractor (chain) = Rudar (lančani) -# + Conveyor Belt = Pokretna Traka -# + Belt = Traka (shodno prošlom prijevodu) -# + Tunnel = Tunel -# + Merger = Sjedinitelj -# + 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. + shortText: shapez.io je igra o izradi tvornica za automatizaciju stvaranja i + spajanja sve složenijih oblika unutar beskonačno velike mape. + discordLinkShort: Official Discord + intro: >- + Shapez.io is a relaxed game in which you have to build factories for the + automated production of geometric shapes. - # 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 - # TODO - longText: >- - [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] + As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map. - 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. + And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! - 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]! + While you only process shapes at the beginning, you have to color them later - for this you have to extract and mix colors! - 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. + Buying the game on Steam gives you access to the full version, but you can also play a demo on shapez.io first and decide later! + title_advantages: Standalone Advantages + advantages: + - 12 New Level for a total of 26 levels + - 18 New Buildings for a fully automated factory! + - 20 Upgrade Tiers for many hours of fun! + - Wires Update for an entirely new dimension! + - Dark Mode! + - Unlimited Savegames + - Unlimited Markers + - Support me! ❤️ + title_future: Planned Content + planned: + - Blueprint Library (Standalone Exclusive) + - Steam Achievements + - Puzzle Mode + - Minimap + - Mods + - Sandbox mode + - ... and a lot more! + title_open_source: This game is open source! + title_links: Links + links: + discord: Official Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Help translate + text_open_source: >- + Anybody can contribute, I'm actively involved in the community and + attempt to review all suggestions and take feedback into consideration + where possible. - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! - 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. + decimalSeparator: . suffix: thousands: k millions: M billions: B trillions: T - - # Shown for infinitely big numbers - infinite: inf # TODO šta s ovim? - + infinite: inf time: - # Used for formatting past time dates - # - # Short formats used for Croatian due to different word cases causing - # diffrerent suffixes due to declension oneSecondAgo: prije jedne sekunde xSecondsAgo: prije s oneMinuteAgo: prije jedne minute @@ -146,14 +66,10 @@ global: xHoursAgo: prije h oneDayAgo: prije jedan dan xDaysAgo: prije dana - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: min s hoursAndMinutesShort: h min - xMinutes: min - keys: tab: TAB control: CTRL @@ -161,13 +77,9 @@ global: escape: ESC shift: SHIFT space: SPACE - demoBanners: - # This is the "advertisement" shown in the main menu and other various places title: Demo Verzija - intro: >- - Nabavi samostalnu igru kako bi otključao sve značajke! - + intro: Nabavi samostalnu igru kako bi otključao sve značajke! mainMenu: play: Igraj continue: Nastavi @@ -179,17 +91,11 @@ mainMenu: discordLink: Službeni Discord Server helpTranslate: Pomogni s prevođenjem! madeBy: Izradio - - # 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. - + 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: Nivo savegameLevelUnknown: Nepoznati Nivo - - # TODO - - + savegameUnnamed: Unnamed dialogs: buttons: ok: OK @@ -203,132 +109,124 @@ dialogs: viewUpdate: Pogledaj ažuriranje showUpgrades: Pokaži Nadogradnje showKeybindings: Pokaži tipke - importSavegameError: title: Greška prilikom uvoza - text: >- - Neuspješan uvoz spremljene igre: - + text: "Neuspješan uvoz spremljene igre:" importSavegameSuccess: title: Uvoz spremljene igre - text: >- - Tvoja spremljena igra je uspješno uvezena. - + text: Tvoja spremljena igra je uspješno uvezena. gameLoadFailure: title: Igra je pukla - text: >- - Neuspješno učitavanje spremljene igre: - + text: "Neuspješno učitavanje spremljene igre:" confirmSavegameDelete: title: Potvrdi brisanje - text: >- - Jesi li siguran da želiš izbrisati spremljenu igru? - + text: Are you sure you want to delete the following game?

+ '' at level

This can not be + undone! savegameDeletionError: title: Greška prilikom brisanja - text: >- - Neuspješno brisanje spremljene igre: - + text: "Neuspješno brisanje spremljene igre:" restartRequired: title: Potrebno ponovno pokretanje - text: >- - Kako bi primijenio postavke, moraš ponovno pokrenuti igru. - + text: Kako bi primijenio postavke, moraš ponovno pokrenuti igru. editKeybinding: title: Promijeni tipku - desc: Pritisni tipku ili gumb na mišu kojeg želiš dodijeliti, ili Escape za otkazivanje. - + desc: Pritisni tipku ili gumb na mišu kojeg želiš dodijeliti, ili Escape za + otkazivanje. resetKeybindingsConfirmation: title: Resetiraj tipke - desc: Ovo će resetirati sve tipke na njihove zadane vrijednosti. Potrebna potvrda. - + desc: Ovo će resetirati sve tipke na njihove zadane vrijednosti. Potrebna + potvrda. keybindingsResetOk: title: Tipke resetirane desc: Tipke su resetirane na svoje zadane vrijednosti! - featureRestriction: title: Demo Verzija - desc: Pokušao si pristupiti značajki () koja nije dostupna u demu. Za puno iskustvo, nabavi samostalnu igru! - + desc: Pokušao si pristupiti značajki () koja nije dostupna u demu. Za + puno iskustvo, nabavi samostalnu igru! oneSavegameLimit: title: Ograničen broj spremljenih igara - desc: Možeš imati samo jednu spremljenu igru u demo verziji. Ukloni postojeću ili nabavi samostalnu igru. - + desc: Možeš imati samo jednu spremljenu igru u demo verziji. Ukloni postojeću + ili nabavi samostalnu igru. updateSummary: title: Novi update! - desc: >- - Evo sve promjene od zadnjeg igranja: - - # TODO + desc: "Evo sve promjene od zadnjeg igranja:" upgradesIntroduction: title: Otključaj Nadogradnje - desc: >- - Svi oblici koji se prozivedu mogu se iskoristiti za otključavanje nadogradnji - Ne preporuča se uništavanje starih tvornica! - Kartica za nadogradnje se može pronaći u gornjem desnom kutu ekrana. - + desc: Svi oblici koji se prozivedu mogu se iskoristiti za otključavanje + nadogradnji - Ne preporuča se uništavanje starih + tvornica! Kartica za nadogradnje se može pronaći u gornjem + desnom kutu ekrana. massDeleteConfirm: title: Potvrdi brisanje - desc: >- - građevina će biti obrisano. Jesi li siguran/na da to želiš? - + desc: građevina će biti obrisano. Jesi li siguran/na da to želiš? massCutConfirm: title: Potvrdi rezanje - desc: >- - građevina će biti izrezano! Jesi li siguran/na da to želiš? - + desc: građevina će biti izrezano! Jesi li siguran/na da to želiš? blueprintsNotUnlocked: title: Nije otključano - desc: >- - Dovrši 12 nivo kako bi otključao Nacrte. - + desc: Dovrši 12 nivo kako bi otključao Nacrte. keybindingsIntroduction: title: Korisne tipke - desc: >- - Igra ima mnogo korisnih tipki, koje olakšavaju izgradnju velikih tvornica. - Evo ih nekoliko, ali svakako se preporuča pogledati sve tipke!

- CTRL + Miš: Odaberi područje.
- SHIFT: Držati za postavljanje više istih zgrada odjednom.
- ALT: Obrni smjer postavljenih pokretnih traka.
- + desc: "Igra ima mnogo korisnih tipki, koje olakšavaju izgradnju velikih + tvornica. Evo ih nekoliko, ali svakako se preporuča + pogledati sve tipke!

CTRL + Miš: Odaberi područje.
SHIFT: Držati za postavljanje više istih + zgrada odjednom.
ALT: Obrni + smjer postavljenih pokretnih traka.
" createMarker: title: Novi Putokaz - desc: Daj mu smisleno ime. Može se uključiti i kratki kod oblika. (Koju možeš generirati ovdje) + 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: U demo verziji se mogu stvoriti samo dva putokaza istovremeno. Nabavi samostalnu igru za beskonačno mnogo putokaza! - + desc: U demo verziji se mogu stvoriti samo dva putokaza istovremeno. Nabavi + samostalnu igru za beskonačno mnogo putokaza! exportScreenshotWarning: title: Izvezi sliku zaslona - desc: Zatražen je izvoz cijele baze u obliku slike zaslone. Ovo može biti jako sporo za velike tvornice, a može i srušiti igru! + desc: Zatražen je izvoz cijele baze u obliku slike zaslone. Ovo može biti jako + sporo za velike tvornice, a može i srušiti igru! massCutInsufficientConfirm: title: Confirm cut desc: You can not afford to paste this area! Are you sure you want to cut it? - + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: Rename Savegame + desc: You can rename your savegame here. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: - moveMap: Kretanje #Move - selectBuildings: Odaberi područje #Select area - stopPlacement: Prekini postavljenje #Stop placement - rotateBuilding: Okreći građevinu #Rotate building - placeMultiple: Postavi više odjednom #Place multiple - reverseOrientation: Obrni orijentaciju #Reverse orientation - disableAutoOrientation: Onemogući automatsku orijentaciju #Disable auto orientation - toggleHud: Uključi/Isključi HUD #Toggle HUD - placeBuilding: Smjesti građevinu #Place building + moveMap: Kretanje + selectBuildings: Odaberi područje + stopPlacement: Prekini postavljenje + rotateBuilding: Okreći građevinu + placeMultiple: Postavi više odjednom + reverseOrientation: Obrni orijentaciju + disableAutoOrientation: Onemogući automatsku orijentaciju + toggleHud: Uključi/Isključi HUD + placeBuilding: Smjesti građevinu createMarker: Stvori Putokaz delete: Uništi - pasteLastBlueprint: Zalijepi zadnji nacrt # Paste last blueprint - lockBeltDirection: Onemogući planiranje traka # Enable belt planner - plannerSwitchSide: Okreni stranu planera # Flip planner side + pasteLastBlueprint: Zalijepi zadnji nacrt + lockBeltDirection: Onemogući planiranje traka + plannerSwitchSide: Okreni stranu planera cutSelection: Izreži copySelection: Kopiraj clearSelection: Očisti odabir pipette: Pipeta switchLayers: Promijeni sloj - # Names of the colors, used for the color blind mode colors: red: Crvena green: Zelena @@ -339,18 +237,9 @@ ingame: white: Bijela 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 varijante. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Tipka: - + hotkeyLabel: "Tipka: " infoTexts: speed: Brzina range: Domet @@ -358,36 +247,21 @@ ingame: oneItemPerSecond: 1 predmet / 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: Dovršeno unlockText: Otključano je ! buttonNextLevel: Idući nivo - - # Notifications on the lower right notifications: newUpgrade: Nova nadogradnja je dostupna! gameSaved: Igra je spremljena. - - # The "Upgrades" window + freeplayLevelComplete: Level has been completed! shop: title: Nadogradnje buttonUnlock: Nadogradi - - # Gets replaced to e.g. "Tier IX" tier: Razina - - # 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: @@ -396,62 +270,110 @@ ingame: description: Količine pohranjenih oblika u središnjoj građevini. produced: title: Proizvedeno - description: Svi oblici koje proizvodi cijela tvornica, uključujući i međuproizvode. + description: Svi oblici koje proizvodi cijela tvornica, uključujući i + međuproizvode. delivered: title: Dostavljeno description: Oblici koji se dostavljaju u središnju građevinu. noShapesProduced: Za sada nema proizvedenih oblika. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / min - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Vrijeme igranja - buildingsPlaced: Građevine beltsPlaced: Trake - - buttons: - continue: Nastavi - settings: Postavke - menu: Vrati se u glavni izbornik - - # Bottom left tutorial hints tutorialHints: title: Trebaš pomoć? showHint: Savjet za gradnju hideHint: Zatvori - - # When placing a blueprint blueprintPlacer: cost: Cijena - - # Map markers waypoints: waypoints: Putokazi hub: Središte - description: Klikni lijevim klikom na marker kako bi skočio na njegovu lokaciju, a izbriši ga desnim klikom.

Za stvaranje markera pritisni , ili desnim klikom stvori marker na odabranoj lokaciji. + description: Klikni lijevim klikom na marker kako bi skočio na njegovu lokaciju, + a izbriši ga desnim klikom.

Za stvaranje markera pritisni + , ili desnim klikom stvori marker na + odabranoj lokaciji. creationSuccessNotification: Putokaz stvoren. - - # Shape viewer shapeViewer: title: Slojevi empty: Prazno - copyKey: Kopiraj # TODO ispraviti ovo/correct this - - # Interactive tutorial + copyKey: Kopiraj interactiveTutorial: title: Tutorijal hints: - 1_1_extractor: Stavi Rudara na oblik kruga kako bi se izvukao iz tla! - 1_2_conveyor: >- - Spoji rudara na središnju građevinu (HUB) koristeći pokretnu traku.

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

Savjet: Drži SHIFT za postavljanje više rudara istovremeno, a pritisni R za rotaciju. - -# All shop upgrades + 1_1_extractor: Stavi Rudara na oblik kruga + kako bi se izvukao iz tla! + 1_2_conveyor: "Spoji rudara na središnju građevinu (HUB) koristeći + pokretnu traku.

Savjet: Pritisni + i povlači traku mišem!" + 1_3_expand: "Ovo NIJE igra čekanja! Više rudara i pokretnih + traka će ubrzati napredak do cilja.

Savjet: Drži + SHIFT za postavljanje više rudara istovremeno, + a pritisni R za rotaciju." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limited to + watermark: + title: Demo version + desc: Click here to see the Steam version advantages! + get_on_steam: Get on steam + standaloneAdvantages: + title: Get the full version! + no_thanks: No, thanks! + points: + levels: + title: 12 New Levels + desc: For a total of 26 levels! + buildings: + title: 18 New Buildings + desc: Fully automate your factory! + savegames: + title: ∞ Savegames + desc: As many as your heart desires! + upgrades: + title: 20 Upgrade Tiers + desc: This demo version has only 5! + markers: + title: ∞ Markers + desc: Never get lost in your factory! + wires: + title: Wires + desc: An entirely new dimension! + darkmode: + title: Dark Mode + desc: Stop hurting your eyes! + support: + title: Support me + desc: I develop it in my spare time! shopUpgrades: belt: name: Trake, Distributer i Tuneli @@ -465,240 +387,381 @@ shopUpgrades: painting: name: Miješanje i Bojanje description: Brzina x → x - -# Buildings and their name / description buildings: hub: deliver: Dostavi toUnlock: kako bi otključao levelShortcut: LVL - + endOfDemo: End of Demo belt: default: - name: &belt Pokretna Traka + name: Pokretna Traka description: Transports items, hold and drag to place multiple. - wire: default: - name: &wire Žica + name: Žica description: Dopušta prijenos energije - - miner: # Internal name for the Extractor + second: + name: Wire + description: Transfers signals, which can be items, colors or booleans (1 / 0). + Different colored wires do not connect. + miner: default: - name: &miner Rudar + name: Rudar description: Place over a shape or color to extract it. - chainable: name: Rudar (Lančani) description: Place over a shape or color to extract it. Can be chained. - - underground_belt: # Internal name for the Tunnel + underground_belt: default: - name: &underground_belt Tunel + name: Tunel description: Allows to tunnel resources under buildings and belts. - tier2: name: Tunel razine II description: Allows to tunnel resources under buildings and belts. - - splitter: # Internal name for the Balancer - default: - name: &splitter Balanser - description: Multifunkcionalan - Jednoliko raspodijeljuje sve ulaze na sve izlaze. - - compact: - name: Sjedinitelj (kompaktni) - description: Sjedinjuje dvije pokretne trake u jednu. - - compact-inverse: - name: Sjedinitelj (kompaktni) - description: Sjedinjuje dvije pokretne trake u jednu. - cutter: default: - name: &cutter Rezač - description: Reže oblike od vrha prema dnu i na izlaze daje obe polovice. Ako se koristi samo jedan dio, drugi se mora uništiti da bi se spriječio zastoj! + name: Rezač + description: Reže oblike od vrha prema dnu i na izlaze daje obe polovice. + Ako se koristi samo jedan dio, drugi se mora uništiti da + bi se spriječio zastoj! quad: name: Rezač (Četverostruki) - description: Reže oblike u četiri dijela. Ako se koristi samo jedan dio, ostali se moraju uništiti da bi se spriječio zastoj! - - advanced_processor: - default: - name: &advanced_processor Napredni Procesor - description: Napredna obrada Oblika - + description: Reže oblike u četiri dijela. Ako se koristi samo jedan dio, + ostali se moraju uništiti da bi se spriječio zastoj! rotater: default: - name: &rotater Obrtač (↻) + name: Obrtač (↻) description: Okreće oblike za 90 stupnjeva u smjeru kazaljke na satu. ccw: name: Obrtač (↺) - description: Okreće oblike za 90 stupnjeva u smjeru suprotnom od kazaljke na satu. - + description: Okreće oblike za 90 stupnjeva u smjeru suprotnom od kazaljke na + satu. + rotate180: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: - name: &stacker Slagač - description: Slaže jedan oblik na drugi. Ako se ne mogu spojiti, desni oblik se postavlja na vrh lijevog. - + name: Slagač + description: Slaže jedan oblik na drugi. Ako se ne mogu spojiti, desni oblik se + postavlja na vrh lijevog. mixer: default: - name: &mixer Miješalica boja + name: Miješalica boja description: Spaja dvije boje koristeći aditivno miješanje. - painter: default: - name: &painter Bojač - description: &painter_desc Boja cijeli oblik na lijevom ulazu bojom s gornjeg ulaza. - + name: Bojač + description: Boja cijeli oblik na lijevom ulazu bojom s gornjeg ulaza. mirrored: - name: *painter - description: *painter_desc - + name: Bojač + description: Boja cijeli oblik na lijevom ulazu bojom s gornjeg ulaza. double: name: Bojač (Dupli) description: Boja oblike na lijevom ulazu bojom s gornjeg ulaza. quad: name: Bojač (Četverostruki) - description: Dopušta bojanje svake četvrtine oblika različitom bojom. - + description: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! trash: default: - name: &trash Smeće + name: Smeće description: Prima stvari sa svih strana i uništava ih. Zauvijek. - - storage: - name: Skladište - description: Skladišti višak stvari do određenog kapaciteta. Može se koristiti kao zaštita od preljeva. - - energy_generator: - deliver: Dostavi - - # This will be shown before the amount, so for example 'For 123 Energy' - toGenerateEnergy: Za - + balancer: default: - name: &energy_generator Generator - description: Proizvodi energiju iz oblika. Svaki generator zahtijeva različiti oblik. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Merger (compact) + description: Merges two conveyor belts into one. + merger-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + storage: + default: + name: Storage + description: Stores excess items, up to a given capacity. Prioritizes the left + output and can be used as an overflow gate. + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: Switch + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means + shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. + (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means + shape, color or boolean "1") + transistor: + default: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + mirrored: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: Belt Reader + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: Virtual Cutter + description: Virtually cuts the shape into two halves. + rotater: + name: Virtual Rotater + description: Virtually rotates the shape, both clockwise and counter-clockwise. + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the + remaining ones to the left. + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the shape on + the right input. + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the + wires layer on the regular layer. storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Rezanje Oblika - desc: Rezač je otključan! Ovaj stroj reže oblike od vrha prema dnu bez obzira na orijentaciju građevine!

Višak se mora odbaciti kako bi se izbjegao zastoj. - Za tu svrhu postoji smeće, koje uništava sve što u njega uđe. - + desc: You just unlocked the cutter, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! reward_rotater: title: Obrtanje - desc: Obrtač je otključan! Ovaj stroj okreće oblike za 90 stupnjeva u smjeru kazaljke na satu. - + desc: Obrtač je otključan! Ovaj stroj okreće oblike za 90 + stupnjeva u smjeru kazaljke na satu. reward_painter: title: Painting - desc: >- - Bojač je otključan - Boja se (kao i oblici) može rudariti i spojiti s oblikom u bojaču!

PS: Postoji opcija za daltonizam u postavkama! - + desc: "Bojač je otključan - Boja se (kao i oblici) može + rudariti i spojiti s oblikom u bojaču!

PS: Postoji + opcija za daltonizam u postavkama!" reward_mixer: title: Miješalica boja - desc: Miješalica boja je otključana - U ovoj se građevini dvije boje mogu spojiti koristeći aditivno miješanje! - + desc: Miješalica boja je otključana - U ovoj se građevini dvije + boje mogu spojiti koristeći aditivno miješanje! reward_stacker: title: Slagač - desc: Sada se dva oblika mogu spojiti slagačem! Oblici s oba ulaza se spajaju - ako se mogu staviti jedan kraj drugoga, biti će spojeni. Ako ne, desni ulaz se slaže na vrh lijevog! - + desc: Sada se dva oblika mogu spojiti slagačem! Oblici s oba + ulaza se spajaju - ako se mogu staviti jedan kraj drugoga, biti će + spojeni. Ako ne, desni ulaz se slaže na + vrh lijevog! reward_splitter: title: Razdjeljivanje i sjedinjavanje - desc: Multifunkcionalni balancer je otključan! Može ga se iskoristiti za razdjeljivanje i sjedinjavanje oblika na više pokretnih traka!

- + desc: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! reward_tunnel: title: Tunel - desc: Tunel je otključan - Omogućava slanje stvari ispod traka i ostalih građevina! - + desc: Tunel je otključan - Omogućava slanje stvari ispod traka + i ostalih građevina! reward_rotater_ccw: title: Rotacija u smjeru suprotnom od kazaljke na satu - desc: Varijanta obrtača je otključana - Omogućuje okretanje u smjeru suprotnom od kazaljke! Odaberi obrtač i pritisni 'T' za mijenjanje njegove varijante! - + desc: Varijanta obrtača je otključana - Omogućuje okretanje u + smjeru suprotnom od kazaljke! Odaberi obrtač i pritisni 'T' + za mijenjanje njegove varijante! reward_miner_chainable: title: Lančani rudar - desc: Otključan je lančani rudar! Može proslijediti svoje resurse drugim rudarima za efikasnije rudarenje! - + desc: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" reward_underground_belt_tier_2: title: Tunel Razine II - desc: Otključana je nova varijanta tunela - Ima veći domet, a uz se sada mogu kombinirati vrste tunela. - - reward_splitter_compact: - title: Kompaktni Balanser - desc: >- - You have unlocked a compact variant of the balanser - It accepts two inputs and merges them into one! - + desc: Otključana je nova varijanta tunela - Ima veći + domet, a uz se sada mogu kombinirati vrste tunela. 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! - + desc: You have unlocked a variant of the cutter - It allows you + to cut shapes in four parts instead of just two! 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! - - 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 works as + the regular painter but processes two shapes at + once consuming just one color instead of two! 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 the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! 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!) - + desc: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. 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). - - # Special reward, which is shown when there is no reward actually + 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). 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! - + 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: >- - Congratulations! By the way, more content is planned for the standalone! - + desc: Congratulations! By the way, more content is planned for the standalone! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: End of Demo + desc: You have reached the end of the demo version! settings: title: Postavke categories: - game: Igra - app: Aplikacija - + general: General + userInterface: User Interface + advanced: Advanced + performance: Performance versionBadges: dev: Development staging: Staging prod: Production buildDate: Built - labels: uiScale: title: Veličina sučelja - 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. + 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. scales: super_small: Jako maleno small: Maleno regular: Normalno large: Veliko huge: Ogromno - autosaveInterval: title: Interval Automatskog Spremanja - description: >- - Upravlja koliko se često pokreće automatsko spremanje igre. Također se ta funkcionalnost može u potpunosti isključiti. - + description: Upravlja koliko se često pokreće automatsko spremanje igre. Također + se ta funkcionalnost može u potpunosti isključiti. intervals: one_minute: 1 minuta two_minutes: 2 minute @@ -706,22 +769,18 @@ settings: ten_minutes: 10 minuta twenty_minutes: 20 minuta disabled: Onemogući - scrollWheelSensitivity: title: Osjetljivost zumiranja - description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + description: Changes how sensitive the zoom is (Either mouse wheel or trackpad). sensitivity: super_slow: Jako sporo slow: Sporo regular: Normalno fast: Brzo super_fast: Jako brzo - movementSpeed: title: Brzina kretanja - description: >- - Mijenja brzinu kretanja kamere pri korištenju tipkovnice. + description: Mijenja brzinu kretanja kamere pri korištenju tipkovnice. speeds: super_slow: Jako Sporo slow: Sporo @@ -729,87 +788,120 @@ settings: fast: Brzo super_fast: Jako Brzo extremely_fast: Iznimno Brzo - language: title: Jezik - description: >- - Promijeni jezik igre. Sve prijevode su napravili korisnici volonteri i mogu biti nedovršeni. - + description: Promijeni jezik igre. Sve prijevode su napravili korisnici + volonteri i mogu biti nedovršeni. enableColorBlindHelper: title: Opcija za daltonizam - description: >- - Omogućuje razne alate koji pomožu pri igranju igre s nekim oblikom sljepoće na boju. - + description: Omogućuje razne alate koji pomožu pri igranju igre s nekim oblikom + sljepoće na boju. fullscreen: title: Puni zaslon - description: >- - Preporuča se, radi najboljeg iskustva, igrati igru na punom zaslonu. Dostupno samo u samostalnoj igri. - + description: Preporuča se, radi najboljeg iskustva, igrati igru na punom + zaslonu. Dostupno samo u samostalnoj igri. soundsMuted: title: Utišaj Zvukove - description: >- - Ako je odabrano, svi zvukovi su utišani. - + description: Ako je odabrano, svi zvukovi su utišani. musicMuted: title: Utišaj Glazbu - description: >- - Ako je odabrano, glazba je utišana. - + description: Ako je odabrano, glazba je utišana. theme: title: Tema Igre - description: >- - Odaberi temu igre (svijetlo/tamno). + description: Odaberi temu igre (svijetlo/tamno). themes: dark: Tamno light: Svijetlo - refreshRate: title: Simulacija za 144 Hz - description: >- - Opcija za monitore visoke frekvencije osvježavanje. Ovo može smanjiti FPS ako je računalo presporo. - + description: Opcija za monitore visoke frekvencije osvježavanje. Ovo može + smanjiti FPS ako je računalo presporo. alwaysMultiplace: title: Višestruko postavljanje - description: >- - Ako je omogućeno, sve građevine će ostati odabrane nakon što su postavljene, dok se poništenje ne odradi ručno. - + description: Ako je omogućeno, sve građevine će ostati odabrane nakon što su + postavljene, dok se poništenje ne odradi ručno. offerHints: title: Savjeti i Upute - description: >- - Opcija za pokazivanje savjeta i uputa za vrijeme igre. Dodatno sakriva određene elemente sučelja dok nisu otključani za lakše učenje igre. - + description: Opcija za pokazivanje savjeta i uputa za vrijeme igre. Dodatno + sakriva određene elemente sučelja dok nisu otključani za lakše + učenje igre. enableTunnelSmartplace: title: Pametni Tuneli - description: >- - Ako je omogućeno, postavljanje tunela automatski briše nepotrebne pokretne trake. Također omogućuje povlačenje tunela i brisanje višak tunela. - + description: Ako je omogućeno, postavljanje tunela automatski briše nepotrebne + pokretne trake. Također omogućuje povlačenje tunela i brisanje + višak tunela. vignette: title: Vinjeta - description: >- - Omogućeva efekt vinjete - zatamnjenje rubova ekrana. - + description: Omogućeva efekt vinjete - zatamnjenje rubova ekrana. 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. - + 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 - description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. - + description: Shortens info boxes for buildings by only showing their ratios. + Otherwise a description and image is shown. disableCutDeleteWarnings: title: Disable Cut/Delete Warnings - description: >- - Disables the warning dialogs brought up when cutting/deleting more than 100 entities. - + description: Disables the warning dialogs brought up when cutting/deleting more + than 100 entities. + soundVolume: + title: Sound Volume + description: Set the volume for sound effects + musicVolume: + title: Music Volume + description: Set the volume for music + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: Tipka - hint: >- #TODO - Savjet: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - + hint: "Savjet: Be sure to make use of CTRL, SHIFT and ALT! They enable different + placement options." resetKeybindings: Ponovno postavi sve tipke - categoryLabels: general: Aplikacija ingame: Igra @@ -818,8 +910,6 @@ keybindings: massSelect: Masovno Odabiranje buildings: Kratice Građevina placementModifiers: Modifikatori Smještanja - - #TODO mappings: confirm: Potvrdi back: Nazad @@ -829,70 +919,73 @@ keybindings: mapMoveLeft: Idi lijevo mapMoveFaster: Brže kretanje centerMap: Center Map - mapZoomIn: Zumiraj mapZoomOut: Umanji createMarker: Stvori novi Putokaz - menuOpenShop: Nadogradnje menuOpenStats: Statistika - toggleHud: Upali/Ugasi HUD toggleFPSInfo: Upali/Ugasi informacije o traženju grešaka u kodu switchLayers: Promijeni sloj exportScreenshot: Izvezi cijelu Bazu kao Sliku - 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 - + belt: Pokretna Traka + underground_belt: Tunel + miner: Rudar + cutter: Rezač + rotater: Obrtač (↻) + stacker: Slagač + mixer: Miješalica boja + painter: Bojač + trash: Smeće + wire: Žica pipette: Pipeta rotateWhilePlacing: Rotiraj - rotateInverseModifier: >- - Modifikator: Rotiraj u smjeru suprotnom od kazaljke na satu + rotateInverseModifier: "Modifikator: Rotiraj u smjeru suprotnom od kazaljke na satu" cycleBuildingVariants: Mijenjaj Varijante confirmMassDelete: Potvrdi Masovno Brisanje pasteLastBlueprint: Zalijepi posljednji Nacrt cycleBuildings: Mijenjaj građevine lockBeltDirection: Omogući planer pokretnih traka - switchDirectionLockSide: >- - Planer: Obrni stranu - + switchDirectionLockSide: "Planer: Obrni stranu" massSelectStart: Pritisni i zadrži za započinjanje massSelectSelectMultiple: Odaberi više područja massSelectCopy: Kopiraj područje massSelectCut: Izreži područje - placementDisableAutoOrientation: Onemogući automatsku orijentaciju placeMultiple: Ostani u modusu za smještanje placeInverse: Obrni automatsku orijentaciju pokretnih traka menuClose: Close Menu -#TODO + balancer: Balancer + storage: Storage + constant_signal: Constant Signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" about: title: O Igri 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.

- 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. - changelog: title: Ispravci - demo: features: restoringGames: Obnavljanje spremljenih igara @@ -900,5 +993,65 @@ demo: oneGameLimit: Ograničeno na jednu spremljenu igru customizeKeybindings: Prilagodba Tipki exportingBase: Izvoz cijele Baze u obliku Slike - settingNotAvailable: Nije dostupno u demo verziji. +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-hu.yaml b/translations/base-hu.yaml index ebdf03af..81e6d7ab 100644 --- a/translations/base-hu.yaml +++ b/translations/base-hu.yaml @@ -1,111 +1,64 @@ -# -# 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 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. + discordLinkShort: Official Discord + intro: >- + Shapez.io is a relaxed game in which you have to build factories for the + automated production of geometric shapes. - # 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] + As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map. - 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. + And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! - 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]! + While you only process shapes at the beginning, you have to color them later - for this you have to extract and mix colors! - 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. + Buying the game on Steam gives you access to the full version, but you can also play a demo on shapez.io first and decide later! + title_advantages: Standalone Advantages + advantages: + - 12 New Level for a total of 26 levels + - 18 New Buildings for a fully automated factory! + - 20 Upgrade Tiers for many hours of fun! + - Wires Update for an entirely new dimension! + - Dark Mode! + - Unlimited Savegames + - Unlimited Markers + - Support me! ❤️ + title_future: Planned Content + planned: + - Blueprint Library (Standalone Exclusive) + - Steam Achievements + - Puzzle Mode + - Minimap + - Mods + - Sandbox mode + - ... and a lot more! + title_open_source: This game is open source! + title_links: Links + links: + discord: Official Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Help translate + text_open_source: >- + Anybody can contribute, I'm actively involved in the community and + attempt to review all suggestions and take feedback into consideration + where possible. - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! - global: loading: Betöltés error: Hiba - - # 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. + thousandsDivider: . + decimalSeparator: "," suffix: - thousands: E + thousands: e millions: M - billions: Mlrd - trillions: T - - # Shown for infinitely big numbers - infinite: inf - + billions: Mrd + trillions: Tr + infinite: végtelen time: - # Used for formatting past time dates oneSecondAgo: egy másodperccel ezelőtt xSecondsAgo: másodperccel ezelőtt oneMinuteAgo: egy perccel ezelőtt @@ -114,14 +67,10 @@ global: xHoursAgo: órával ezelőtt oneDayAgo: egy nappal ezelőtt xDaysAgo: nappal ezelőtt - - # Short formats for times, e.g. '5h 23m' secondsShort: mp minutesAndSecondsShort: p mp hoursAndMinutesShort: ó p - xMinutes: perc - keys: tab: TAB control: CTRL @@ -129,584 +78,743 @@ global: escape: ESC shift: SHIFT space: SPACE - demoBanners: - # This is the "advertisement" shown in the main menu and other various places - title: Demó verzi - intro: >- - Get the standalone to unlock all features! - + title: Demó verzió + intro: 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! - - # 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. - + helpTranslate: Segíts fordítani! + madeBy: Készítette + browserWarning: 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 - + savegameUnnamed: Unnamed 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. - + text: "Nem sikerült importálni a mentésed:" importSavegameSuccess: title: Mentés Importálva - text: >- - A mentésed sikeresen importálva lett. - + text: A mentésed sikeresen importálva lett. gameLoadFailure: - title: Game is broken - text: >- - Failed to load your savegame: Nem sikerült betölteni a mentésed - + title: A játék elromlott + text: "Nem sikerült betölteni a mentésed:" confirmSavegameDelete: - title: Confirm deletion - text: >- - Biztos, hogy ki akarod törölni? - + title: Törlés megerősítése + text: Are you sure you want to delete the following game?

+ '' at level

This can not be + undone! savegameDeletionError: title: Sikertelen törlés - text: >- - Failed to delete the savegame: Nem sikerült törölni a mentésed. - + text: "Nem sikerült törölni a mentésed:" restartRequired: title: Újraindítás szükséges - text: >- - Újra kell indítanod a játékot, hogy életbe lépjenek a módosítások. - + text: Ú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: - + desc: "Íme a változások a legutóbbi játékod óta:" upgradesIntroduction: - title: Unlock Upgrades - 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. - + title: Szerezz Fejlesztéseket + desc: 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 - desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? - + title: Törlés megerősítése + desc: 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. - + desc: A Tervrajzokat a 12-es szinten fogod feloldani. keybindingsIntroduction: - title: Useful 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 area to copy / delete.
- SHIFT: Hold to place multiple of one building.
- ALT: Invert orientation of placed belts.
- + title: Hasznos billentyűk + desc: "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: Give it a meaningful name, you can also include a short + key of a shape (Which you can generate here) + 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 - 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? - + title: Képernyőkép exportálása + desc: 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! + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: Rename Savegame + desc: You can rename your savegame here. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? 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 - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + 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 + 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 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. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - + cycleBuildingVariants: Nyomd meg a -t, a variációk váltogatásához. + hotkeyLabel: "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 - - # The notification when completing a level + tiles: csempe 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. - - # The "Upgrades" window + gameSaved: A játékállás mentve. + freeplayLevelComplete: Level has been completed! shop: title: Fejlesztések buttonUnlock: Fejlesztés - - # Gets replaced to e.g. "Tier IX" - tier: Tier - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - - maximumLevel: MAXIMUM LEVEL (Speed x) - - # The "Statistics" window + tier: . Szint + maximumLevel: LEGMAGASABB SZINT (x Sebesség) statistics: title: Statisztikák 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. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / p - - # Settings menu, when you press "ESC" + 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. + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Játékidő - - buildingsPlaced: Épület - beltsPlaced: Futószalag - - buttons: - continue: Folytatás - settings: Beállítások - menu: Vissza a menübe - - # Bottom left tutorial hints + buildingsPlaced: Épületek száma + beltsPlaced: Futószalagok hossza tutorialHints: title: Segítségre van szükséged? showHint: Segítség mutatása hideHint: Bezárás - - # When placing a blueprint blueprintPlacer: cost: Ár - - # 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. - - # Interactive tutorial - interactiveTutorial: - title: Tutorial - hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! - 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. - - colors: - red: Red - green: Green - blue: Blue - yellow: Yellow - purple: Purple - cyan: Cyan - white: White - uncolored: No color - black: Black + 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. shapeViewer: - title: Layers - empty: Empty - copyKey: Copy Key - -# All shop upgrades + title: Rétegek + empty: Üres + copyKey: Gyorskód másolása + interactiveTutorial: + title: Oktatás + hints: + 1_1_extractor: Helyezz egy bányát egy kör + alakzat tetejére a kibányászásához! + 1_2_conveyor: "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: "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." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limited to + watermark: + title: Demo version + desc: Click here to see the Steam version advantages! + get_on_steam: Get on steam + standaloneAdvantages: + title: Get the full version! + no_thanks: No, thanks! + points: + levels: + title: 12 New Levels + desc: For a total of 26 levels! + buildings: + title: 18 New Buildings + desc: Fully automate your factory! + savegames: + title: ∞ Savegames + desc: As many as your heart desires! + upgrades: + title: 20 Upgrade Tiers + desc: This demo version has only 5! + markers: + title: ∞ Markers + desc: Never get lost in your factory! + wires: + title: Wires + desc: An entirely new dimension! + darkmode: + title: Dark Mode + desc: Stop hurting your eyes! + support: + title: Support me + desc: I develop it in my spare time! 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 - -# Buildings and their name / description + name: Keverés & Festés + description: x → x Sebesség 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 + endOfDemo: End of Demo + belt: + default: + name: Futószalag + description: Elemeket szállít, tartsd nyomva az egérgombot egyszerre több + lerakásához. wire: default: name: Energy Wire description: Allows you to transport energy. - advanced_processor: + second: + name: Wire + description: Transfers signals, which can be items, colors or booleans (1 / 0). + Different colored wires do not connect. + miner: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For + name: 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ó. + underground_belt: default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: + name: 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. + cutter: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: 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! + rotater: + default: + name: 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. + rotate180: + name: Rotate (180) + description: Rotates shapes by 180 degrees. + stacker: + default: + name: 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: Színkeverő + description: Összekever két színt összeadó színkeveréssel. + painter: + default: + name: Festő + description: Beszínezi az alakzatot a baloldali bemeneten a jobboldali bemeneten + érkező színnel. + mirrored: + name: Festő + description: Beszínezi az alakzatot a baloldali bemeneten a jobboldali bemeneten + érkező színnel. + double: + name: Festő (Dupla) + description: Beszínezi az alakzatokat a baloldali bemeneteken a fenti bemeneten + érkező színnel. + quad: + name: Festő (Négyszeres) + description: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! + trash: + default: + name: Kuka + description: Bármelyik irányból lehet hozzá csatlakozni, és megsemmisíti a + beleküldött elemeket. Örökre. + balancer: + default: + name: Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Merger (compact) + description: Merges two conveyor belts into one. + merger-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + storage: + default: + name: Storage + description: Stores excess items, up to a given capacity. Prioritizes the left + output and can be used as an overflow gate. + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: Switch + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means + shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. + (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means + shape, color or boolean "1") + transistor: + default: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + mirrored: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: Belt Reader + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: Virtual Cutter + description: Virtually cuts the shape into two halves. + rotater: + name: Virtual Rotater + description: Virtually rotates the shape, both clockwise and counter-clockwise. + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the + remaining ones to the left. + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the shape on + the right input. + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the + wires layer on the regular layer. 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, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! reward_rotater: title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. - + desc: The rotater has been unlocked! It rotates shapes + clockwise by 90 degrees. 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! - + 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!" reward_mixer: title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! - + desc: The mixer has been unlocked - Combine two colors using + additive blending with this building! 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! - + 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! 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!

- + desc: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! reward_tunnel: title: Tunnel - desc: The tunnel has been unlocked - You can now pipe items through belts and buildings with it! - + desc: The tunnel has been unlocked - You can now pipe items + through belts and buildings with it! 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 to + rotate counter clockwise! To build it, select the rotater and + press 'T' to cycle its variants! 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! - + desc: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" 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! - - 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! - + 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! 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! - + desc: You have unlocked a variant of the cutter - It allows you + to cut shapes in four parts instead of just two! 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! - - 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 works as + the regular painter but processes two shapes at + once consuming just one color instead of two! 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 the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! 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!) - + desc: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. 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). - - # Special reward, which is shown when there is no reward actually + 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). 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! - + 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: >- - Congratulations! By the way, more content is planned for the standalone! - + desc: Congratulations! By the way, more content is planned for the standalone! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: End of Demo + desc: You have reached the end of the demo version! settings: title: Beállítások categories: - game: Game - app: Application - + general: General + userInterface: User Interface + advanced: Advanced + performance: Performance versionBadges: dev: Development staging: Staging prod: Production buildDate: Built - labels: uiScale: title: Interfész nagyság - 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. + 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. scales: super_small: Szuper kicsi small: Kicsi regular: Közepes large: Nagy huge: Hatalmas - scrollWheelSensitivity: title: Zoom sensitivity - description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + description: Changes how sensitive the zoom is (Either mouse wheel or trackpad). sensitivity: super_slow: Szuper lassú slow: Lassú regular: Közepes fast: Gyors super_fast: Szuper gyors - language: title: Nyelv - description: >- - Change the language. All translations are user contributed and might be incomplete! - + description: Change the language. All translations are user contributed and + might be incomplete! fullscreen: title: Fullscreen - description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. - + description: It is recommended to play the game in fullscreen to get the best + experience. Only available in the standalone. soundsMuted: title: Hangok Némítása - description: >- - If enabled, mutes all sound effects. - + description: If enabled, mutes all sound effects. musicMuted: title: Zene Némítása - description: >- - If enabled, mutes all music. - + description: If enabled, mutes all music. theme: title: Game theme - description: >- - Choose the game theme (light / dark). - + description: Choose the game theme (light / dark). themes: dark: Sötét light: Világos - refreshRate: title: Simulation Target - 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. - + 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: Multiplace - description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. - + description: If enabled, all buildings will stay selected after placement until + you cancel it. This is equivalent to holding SHIFT permanently. 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. - + 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. movementSpeed: title: Movement speed description: Changes how fast the view moves when using the keyboard. @@ -719,20 +827,17 @@ settings: 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. + description: When enabled, placing tunnels will automatically remove unnecessary + belts. This also enables 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. - + description: Enables the vignette which darkens the screen corners and makes + text easier to read. autosaveInterval: title: Autosave Interval - description: >- - Controls how often the game saves automatically. You can also disable it - entirely here. + description: Controls how often the game saves automatically. You can also + disable it entirely here. intervals: one_minute: 1 Minute two_minutes: 2 Minutes @@ -742,32 +847,77 @@ settings: disabled: Disabled compactBuildingInfo: title: Compact Building Infos - description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a - description and image is shown. + description: 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. - + 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. + 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. - + 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. + soundVolume: + title: Sound Volume + description: Set the volume for sound effects + musicVolume: + title: Music Volume + description: Set the volume for music + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: Keybindings - hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - + hint: "Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different + placement options." resetKeybindings: Reset Keyinbindings - categoryLabels: general: Application ingame: Game @@ -776,7 +926,6 @@ keybindings: massSelect: Mass Select buildings: Building Shortcuts placementModifiers: Placement Modifiers - mappings: confirm: Confirm back: Vissza @@ -785,38 +934,30 @@ keybindings: mapMoveDown: Move Down mapMoveLeft: Move Left centerMap: Center Map - mapZoomIn: Zoom in mapZoomOut: Zoom out createMarker: Create Marker - menuOpenShop: Fejlesztések menuOpenStats: Statisztikák - toggleHud: Toggle HUD toggleFPSInfo: Toggle FPS and Debug Info - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + belt: Futószalag + underground_belt: Alagút + miner: Bányász + cutter: Vágó + rotater: Forgató + stacker: Egyesítő + mixer: Színkeverő + painter: Festő + trash: Kuka rotateWhilePlacing: Rotate - rotateInverseModifier: >- - Modifier: Rotate CCW instead + rotateInverseModifier: "Modifier: Rotate CCW instead" cycleBuildingVariants: Cycle Variants confirmMassDelete: Confirm Mass Delete cycleBuildings: Cycle Buildings - massSelectStart: Hold and drag to start massSelectSelectMultiple: Select multiple areas massSelectCopy: Copy area - placementDisableAutoOrientation: Disable automatic orientation placeMultiple: Stay in placement mode placeInverse: Invert automatic belt orientation @@ -829,33 +970,38 @@ keybindings: pipette: Pipette menuClose: Close Menu switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator wire: Energy Wire - + balancer: Balancer + storage: Storage + constant_signal: Constant Signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" about: title: A játékról 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.

- - Finally, huge thanks to my best friend Niklas - Without our - factorio sessions this game would never have existed. + 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. changelog: title: Changelog - demo: features: restoringGames: Mentések visszaállítása @@ -863,5 +1009,65 @@ demo: oneGameLimit: Egy mentésre van limitálva customizeKeybindings: Customizing Keybindings exportingBase: Exporting whole Base as Image - settingNotAvailable: Nem elérhető a demóban. +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-ind.yaml b/translations/base-ind.yaml index 64b1777a..0c041a6a 100644 --- a/translations/base-ind.yaml +++ b/translations/base-ind.yaml @@ -1,129 +1,73 @@ -# -# 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 is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. + shortText: shapez.io adalah game tentang membangun pabrik untuk mengotomatiskan + pembuatan dan pemrosesan bentuk-bentuk yang semakin lama semakin kompleks + di dalam peta yang meluas tanpa batas. + discordLinkShort: Server Discord Resmi + intro: >- + Kamu suka game otomasi? Maka kamu berada di tempat yang tepat! - # This is the text shown above the discord link - discordLink: Official Discord - Chat with me! + shapez.io adalah game santai dimana kamu harus membuat pabrik untuk mengotomatiskan produksi bentuk-bentuk geometris. Semakin meningkatnya level, bentuk-bentuknya menjadi lebih kompleks, dan kamu perlu meluaskan pabrikmu semakin jauh lagi. - # 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] + Dan jita itu tidak cukup, kamu juga perlu memproduksi bentuk secara eksponensial untuk memenuhkan kebutuhan - hal yang membantu hanyalah memperbesar pabrik! Walaupun kamu hanya perlu memproses bentuk di awal, nantinya kamu harus memberinya warna - dengan mengekstrak dan mencampur warna! - 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'll progress within the game and unlock upgrades to speed up your factory. - - 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]! - - 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. - - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/b] - - 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) - [*] 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] - - 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://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] + Membeli game ini di Steam memberikan kamu akses ke versi lengkap, namun kamu juga dapat mencoba demo dan memutuskan nanti! + title_advantages: Keuntungan Versi Lengkap + advantages: + - 12 Level Baru dengan total 26 level + - 18 Bangunan Baru untuk membuat pabrik yang otomatis sepenuhnya! + - 20 Tingkatan Upgrade untuk keseruan berjam-jam! + - Update Kabel untuk dimensi yang benar-benar baru! + - Mode Gelap! + - Data Simpanan Tidak Terbatas + - Penanda Tidak Terbatas + - Dukung saya! ❤️ + title_future: Konten Terencana + planned: + - Penyimpanan Cetak Biru (Eksklusif Versi Lengkap) + - Achievement Steam + - Mode Puzzle + - Peta Kecil + - Modifikasi + - Mode Sandbox + - ... dan masih banyak lagi! + title_open_source: Game ini open source! + title_links: Tautan (Links) + links: + discord: Server Discord Resmi + roadmap: Peta Jalan + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Bantu menterjemahkan + text_open_source: >- + Semua orang bisa berpartisipasi, saya aktif terlibat dalam komunitas dan + mencoba untuk meninjau semua saran dan mempertimbangkan segala umpan + balik jika memungkinkan. + Pastikan untuk memeriksa papan trello saya untuk peta jalan selengkapnya! global: - loading: Loading - error: Error - - # 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. + loading: Memuat + error: Terjadi kesalahan + thousandsDivider: "." + decimalSeparator: "," suffix: - thousands: k - millions: M - billions: B + thousands: rb + millions: Jt + billions: M trillions: T - - # Shown for infinitely big numbers - infinite: inf - + infinite: tak terhingga 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 - - # Short formats for times, e.g. '5h 23m' - secondsShort: s - minutesAndSecondsShort: m s - hoursAndMinutesShort: h m - - xMinutes: minutes - + oneSecondAgo: sedetik yang lalu + xSecondsAgo: detik yang lalu + oneMinuteAgo: semenit yang lalu + xMinutesAgo: menit yang lalu + oneHourAgo: sejam yang lalu + xHoursAgo: jam yang lalu + oneDayAgo: sehari yang lalu + xDaysAgo: hari yang lalu + secondsShort: dtk + minutesAndSecondsShort: m dtk + hoursAndMinutesShort: j m + xMinutes: menit keys: tab: TAB control: CTRL @@ -131,744 +75,1012 @@ global: escape: ESC shift: SHIFT space: SPACE - 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! - + title: Versi Demo + intro: Dapatkan versi lengkap untuk membuka semua fitur! mainMenu: - play: Play - continue: Continue - newGame: New Game - changelog: Changelog + play: Mulai Permainan + continue: Lanjutkan + newGame: Permainan Baru + changelog: Catatan Perubahan 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: >- - Sorry, but the game is known to run slow on your browser! Get the standalone version or download chrome for the full experience. - + importSavegame: Impor Data Simpanan + openSourceHint: Game ini open source! + discordLink: Server Discord Resmi + helpTranslate: Bantu Terjemahkan! + madeBy: Dibuat oleh + browserWarning: Maaf, tetapi permainan ini biasanya lambat pada + browser kamu! Dapatkan versi lengkap atau unduh Chrome untuk + pengalaman sepenuhnya. savegameLevel: Level - savegameLevelUnknown: Unknown Level - + savegameLevelUnknown: Level tidak diketahui + savegameUnnamed: Tidak Dinamai 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 - + delete: Hapus + cancel: Batal + later: Nanti + restart: Mulai Ulang + reset: Setel Ulang + getStandalone: Dapatkan Versi Lengkap + deleteGame: Aku tahu apa yang aku lakukan + viewUpdate: Tampilkan Update + showUpgrades: Tunjukkan Tingkatan + showKeybindings: Tunjukkan Tombol Pintas importSavegameError: - title: Import Error - text: >- - Failed to import your savegame: - + title: Kesalahan pada Impor + text: "Gagal memasukkan data simpanan kamu:" importSavegameSuccess: - title: Savegame Imported - text: >- - Your savegame has been successfully imported. - + title: Impor Berhasil + text: Data simpanan kamu berhasil dimasukkan. gameLoadFailure: - title: Game is broken - text: >- - Failed to load your savegame: - + title: Permainan Rusak + text: "Gagal memuat data simpanan kamu:" confirmSavegameDelete: - title: Confirm deletion - text: >- - Are you sure you want to delete the game? - + title: Konfirmasi Penghapusan + text: Apakah kamu yakin ingin menghapus game berikut?

'' + pada level

Hal ini tak dapat diulang! savegameDeletionError: - title: Failed to delete - text: >- - Failed to delete the savegame: - + title: Gagal Menghapus + text: "Gagal untuk menghapus data simpanan:" restartRequired: - title: Restart required - text: >- - You need to restart the game to apply the settings. - + title: Diperlukan untuk Restart + text: kamu harus memulai kembali permainan untuk menerapkan pengaturan. editKeybinding: - title: Change Keybinding - desc: Press the key or mouse button you want to assign, or escape to cancel. - + title: Ganti Tombol Pintas (Keybinding) + desc: Tekan tombol pada keyboard atau mouse yang ingin kamu ganti, atau + tekan escape untuk membatalkan. resetKeybindingsConfirmation: - title: Reset keybindings - desc: This will reset all keybindings to their default values. Please confirm. - + title: Setel Ulang Tombol-tombol Pintas (Keybinding) + desc: Ini akan menyetel ulang semua tombol pintas kepada pengaturan awalnya. + Harap konfirmasi. keybindingsResetOk: - title: Keybindings reset - desc: The keybindings have been reset to their respective defaults! - + title: Setel Ulang + desc: Tombol-tombol pintas sudah disetel ulang ke pengaturan awalnya! 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: Versi Demo + desc: Kamu mencoba untuk mengakses fitur () yang tidak tersedia pada + versi demo. Pertimbangkan untuk mendapatkan versi lengkap untuk + pengalaman sepenuhnya! 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: Penyimpanan Permainan Terbatas + desc: Kamu hanya dapat memiliki satu data simpanan dalam versi demo. Harap + hapus yang telah ada atau dapatkan versi lengkap! updateSummary: - title: New update! - desc: >- - Here are the changes since you last played: - + title: Update Baru! + desc: "Berikut perubahan-perubahan yang telah dibuat sejak kamu main terakhir + kali:" upgradesIntroduction: - title: Unlock Upgrades - 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. - + title: Buka Tingkatan-tingkatan + desc: Semua bentuk yang kamu produksi dapat digunakan untuk membuka tingkatan + baru - Jangan hancurkan pabrik-pabrik lama kamu! + Tab tingkatan dapat ditemukan di sudut kanan atas layar kamu. massDeleteConfirm: - title: Confirm delete - desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? - + title: Konfirmasi Penghapusan + desc: Kamu akan menghapus banyak bangunan (tepatnya )! Apakah kamu yakin + untuk melakukannya? massCutConfirm: - title: Confirm cut - desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you want to do this? - + title: Konfirmasi Pemindahan (Cut) + desc: Kamu akan memindahkan (cut) banyak bangunan (tepatnya )! Apakah kamu + yakin untuk melakukannya? massCutInsufficientConfirm: - title: Confirm cut - desc: >- - You can not afford to paste this area! Are you sure you want to cut it? - + title: Tidak Mampu Memindahkan + desc: Kamu tidak mampu menanggung biaya pemindahan area ini! Apakah kamu yakin + untuk memindahkannya? blueprintsNotUnlocked: - title: Not unlocked yet - desc: >- - Complete level 12 to unlock Blueprints! - + title: Belum Terbuka + desc: Selesaikan level 12 untuk membuka Cetak Biru! keybindingsIntroduction: - title: Useful 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.
- + title: Tombol Pintas (Keybindings) Berguna + desc: "Permainan ini memiliki banyak tombol pintas yang membuatnya lebih mudah + untuk membangun pabrik-pabrik besar. Berikut adalah beberapa, namun + pastikan kamu perhatikan tombol-tombol + pintasnya!

CTRL + + Tarik: Pilih sebuah area.
SHIFT: + Tahan untuk meletakkan beberapa bangunan sekaligus.
ALT: Ganti orientasi sabuk konveyor yang + telah diletakkan.
" createMarker: - title: New Marker - titleEdit: Edit Marker - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) - + title: Penanda Baru + titleEdit: Sunting Penanda + desc: Berikan nama yang berguna, kamu juga bisa memasukkan short key + dari sebuah bentuk (Yang bisa kamu buat sendiri + disini) markerDemoLimit: - desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! - + desc: Kamu hanya dapat membuat dua penanda pada versi demo. Dapatkan versi + lengkap untuk penanda-penanda tak terhingga! 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: Ekspor Screenshot + desc: Kamu meminta untuk mengekspor pabrikmu sebagai screenshot. + Harap ketahui bahwa ini bisa menjadi lambat untuk pabrik + yang besar dan bahkan dapat membuat permainanmu berhenti! + editSignal: + title: Atur Tanda + descItems: "Pilih item yang telah ditentukan sebelumnya:" + descShortKey: ... atau masukkan shortkey dari bentuk (Yang + bisa Kamu buat sendiri disini) + renameSavegame: + title: Ganti Nama Data Simpanan + desc: Kamu bisa mengganti nama data simpanan di sini. + tutorialVideoAvailable: + title: Tutorial Tersedia + desc: Ada video tutorial yang tersedia untuk level ini! Apakah kamu ingin menontonnya? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Tersedia + desc: Ada video tutorial yang tersedia untuk level ini, tetapi hanya dalam Bahasa Inggris. + Apakaha kamu ingin menontonnya? 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 - - # Names of the colors, used for the color blind mode + moveMap: Geser + selectBuildings: Pilih area + stopPlacement: Hentikan peletakan + rotateBuilding: Putar bangunan + placeMultiple: Letakkan beberapa + reverseOrientation: Balikkan orientasi + disableAutoOrientation: Nonaktifkan orientasi otomatis. + toggleHud: Ganti HUD + placeBuilding: Letakan bangunan + createMarker: Buat penanda + delete: Hapus + pasteLastBlueprint: Tempel (paste) cetak biru terakhir + lockBeltDirection: Aktifkan perencana sabuk konveyor + plannerSwitchSide: Balikkan sisi perencana + cutSelection: Pindahkan (Cut) + copySelection: Salin (Copy) + clearSelection: Hapus pilihan + pipette: Pipet + switchLayers: Ganti lapisan 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) + red: Merah + green: Hijau + blue: Biru + yellow: Kuning + purple: Ungu + cyan: Biru kehijauan + white: Putih + black: Hitam + uncolored: Abu-abu 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. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - + cycleBuildingVariants: Tekan untuk ganti varian. + hotkeyLabel: "Hotkey: " infoTexts: - speed: Speed - range: Range - storage: Storage - oneItemPerSecond: 1 item / second - itemsPerSecond: items / s + speed: Kecepatan + range: Jangkauan + storage: Penyimpanan + oneItemPerSecond: 1 item/dtk + itemsPerSecond: item/dtk itemsPerSecondDouble: (x2) - - tiles: tiles - - # The notification when completing a level + tiles: ubin levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Level - completed: Completed - unlockText: Unlocked ! - buttonNextLevel: Next Level - - # Notifications on the lower right + completed: Selesai + unlockText: terbuka! + buttonNextLevel: Level Selanjutnya notifications: - newUpgrade: A new upgrade is available! - gameSaved: Your game has been saved. - - # The "Upgrades" window + newUpgrade: Tingkatan baru tersedia! + gameSaved: Permainan kamu telah disimpan. + freeplayLevelComplete: Level telah selesai! shop: - title: Upgrades - buttonUnlock: Upgrade - - # Gets replaced to e.g. "Tier IX" - tier: Tier - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - - maximumLevel: MAXIMUM LEVEL (Speed x) - - # The "Statistics" window + title: Tingkatan-tingkatan + buttonUnlock: Tingkatkan + tier: Tingkat + maximumLevel: LEVEL MAKSIMUM (Kecepatan x) statistics: - title: Statistics + title: Statistik dataSources: stored: - title: Stored - description: Displaying amount of stored shapes in your central building. + title: Tersimpan + description: Menunjukan semua bentuk yang tersimpan pada bangunan pusatmu. produced: - title: Produced - description: Displaying all shapes your whole factory produces, including intermediate products. + title: Terproduksi + description: Menunjukkan semua bentuk yang diproduksi pabrikmu, + termasuk produk-produk antara. delivered: - title: Delivered - 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 - - # Settings menu, when you press "ESC" + title: Terkirim + description: Menunjukkan bentuk-bentuk yang sedang dikirim ke bangunan pusatmu. + noShapesProduced: Sejauh ini belum diproduksi. + shapesDisplayUnits: + second: /dtk + minute: /m + hour: /j settingsMenu: - playtime: Playtime - - buildingsPlaced: Buildings - beltsPlaced: Belts - - buttons: - continue: Continue - settings: Settings - menu: Return to menu - - # Bottom left tutorial hints + playtime: Waktu bermain + buildingsPlaced: Bangunan + beltsPlaced: Sabuk konveyor tutorialHints: - title: Need help? - showHint: Show hint - hideHint: Close - - # When placing a blueprint + title: Butuh bantuan? + showHint: Tampilkan petunjuk + hideHint: Tutup blueprintPlacer: - cost: Cost - - # Map markers + cost: Biaya 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. - - # Shape viewer + waypoints: Penanda + hub: PUSAT + description: Klik tombol kiri mouse pada penanda untuk melompat ke penanda, 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. shapeViewer: - title: Layers - empty: Empty - copyKey: Copy Key - - # Interactive tutorial + title: Lapisan-lapisan + empty: Kosong + copyKey: Tombol Salin (Copy) interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! - 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. - -# All shop upgrades + 1_1_extractor: Letakkan ekstraktor diatas bentuk + lingkaran untuk mengekstrak bentuk tersebut! + 1_2_conveyor: "Hubungkan ekstraktor dengan sabuk konveyor ke + bangunan pusatmu!

Tip: Klik dan + seret sabuk konveyor dengan mouse!" + 1_3_expand: "Ini BUKAN permainan menganggur! Bangun lebih + banyak ekstraktor dan sabuk konveyor untuk menyelesaikan + objektif dengan lebih cepat.

Tip: Tahan tombol + SHIFT untuk meletakkan beberapa ekstraktor sekaligus, dan + gunakan tombol R untuk memutar." + 2_1_place_cutter: "Sekarang letakkan Pemotong untuk memotong lingkaran + menjadi 2 bagian!

NB: Pemotong akan selalu memotong dari atas ke + bawah apapun orientasinya." + 2_2_place_trash: Pemotong dapat tersumbat dan macet!

Gunakan + tong sampah untuk membuang sisa (!) yang saat ini tidak diperlukan. + 2_3_more_cutters: "Kerja yang bagus! Sekarang letakkan 2 pemotong lagi untuk mempercepat + proses ini!

NB: Gunakan tombol 0-9 + untuk mengakses bangunan lebih cepat!" + 3_1_rectangles: "Sekarang ekstrak beberapa persegi! Bangun 4 + ekstraktor dan hubungkan mereka ke bangunan pusat.

NB: + Tahan SHIFT saat meletakkan konveyor untuk mengaktifkan + perencana sabuk konveyor!" + 21_1_place_quad_painter: Letakkan pemotong empat bagian dan ekstrak beberapa + lingkaran, warna putih dan + merah! + 21_2_switch_to_wires: Pindah ke lapisan kabel dengan menekan tombol + E!

Lalu hubungkan keempat + input dari pengecat dengan menggunakan kabel! + 21_3_place_button: Mantap! Sekarang letakkan saklar dan hubungkan + dengan menggunakan kabel! + 21_4_press_button: "Tekan saklar untuk memancarkan sinyal yang + benar dan mengaktifkan pengecat.

NB: Kamu + tidak perlu menghubungkan semua input! Cobalah hanya menghubungkan dua." + connectedMiners: + one_miner: 1 Ekstraktor + n_miners: Ekstraktor + limited_items: Terbatas hingga + watermark: + title: Versi Demo + desc: Klik disini untuk melihat keunggulan pada versi Steam! + get_on_steam: Dapatkan di Steam + standaloneAdvantages: + title: Dapatkan versi lengkap! + no_thanks: Tidak, terima kasih! + points: + levels: + title: 12 Level Baru + desc: Dengan total 26 level! + buildings: + title: 18 Bangunan Baru + desc: Untuk membuat pabrik yang otomatis sepenuhnya! + savegames: + title: ∞ Data Simpanan + desc: Sebanyak yang kamu mau! + upgrades: + title: 20 Tingkatan Upgrade + desc: Versi demo ini hanya punya 5! + markers: + title: ∞ Penanda + desc: Kamu tidak akan tersesat di pabrikmu sendiri! + wires: + title: Kabel + desc: Sebuah dimensi yang benar-benar berbeda! + darkmode: + title: Mode Gelap + desc: Berhenti merusak matamu! + support: + title: Dukung saya + desc: Saya membuat game ini di waktu luang! shopUpgrades: belt: - name: Belts, Distributor & Tunnels - description: Speed x → x + name: Sabuk konveyor, Pembagi Arus & Terowongan + description: Kecepatan x → x miner: - name: Extraction - description: Speed x → x + name: Ekstraksi + description: Kecepatan x → x processors: - name: Cutting, Rotating & Stacking - description: Speed x → x + name: Memotong, Memutar & Menumpuk + description: Kecepatan x → x painting: - name: Mixing & Painting - description: Speed x → x - -# Buildings and their name / description + name: Mencampur & Mengecat + description: Kecepatan x → x buildings: hub: - deliver: Deliver - toUnlock: to unlock + deliver: Kirim + toUnlock: untuk membuka levelShortcut: LVL - + endOfDemo: Akhir dari Demo belt: default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. - + name: Sabuk Konveyor + description: Mengangkut sumber daya, tahan dan seret untuk meletakkan beberapa sekaligus. wire: default: - name: &wire Energy Wire - description: Allows you to transport energy. - - miner: # Internal name for the Extractor + name: Kabel + description: Mentransfer sinyal, dapat berupa bentuk, warna, atau boolean (1 + atau 0). Kabel dengan warna berbeda tidak akan menyambung. + second: + name: Kabel + description: Mentransfer sinyal, dapat berupa bentuk, warna, atau boolean (1 + atau 0). Kabel dengan warna berbeda tidak akan menyambung. + miner: default: - name: &miner Extractor - description: Place over a shape or color to extract it. - + name: Ekstraktor + description: Letakkan diatas sumber bentuk atau warna untuk mengekstraksi + mereka. chainable: - name: Extractor (Chain) - description: Place over a shape or color to extract it. Can be chained. - - underground_belt: # Internal name for the Tunnel + name: Ekstraktor (Berantai) + description: Letakkan di atas sumber bentuk atau warna untuk mengekstraksi + mereka. Dapat dirantai. + underground_belt: default: - name: &underground_belt Tunnel - description: Allows you to tunnel resources under buildings and belts. - + name: Terowongan + description: Memungkinkan kamu untuk mengangkut sumber-sumber daya dibawah + bangunan-bangunan atau sabuk konveyor. tier2: - name: Tunnel Tier II - description: Allows you 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. - + name: Terowongan Tingkat II + description: Memungkinkan kamu untuk mengangkut sumber-sumber daya dibawah + bangunan-bangunan atau sabuk konveyor. 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: Pemotong + description: Memotong bentuk-bentuk secara vertikal dan mengeluarkan kedua + bagian. Apabila kamu hanya menggunakan satu bagian, + pastikan kamu lenyapkan bagian lain atau mesin akan tersumbat + macet! 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. - + name: Pemotong (Empat Bagian) + description: Memotong bentuk-bentuk menjadi empat bagian. Apabila kamu + hanya menggunakan satu bagian, pastikan kamu lenyapkan + bagian-bagian lain atau mesin akan tersumbat dan macet! rotater: default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. + name: Pemutar + description: Memutar bentuk searah jarum jam sebesar 90 derajat. ccw: - name: Rotate (CCW) - description: Rotates shapes counter-clockwise by 90 degrees. - + name: Pemutar (Berlawanan Arah Jarum Jam) + description: Memutar bentuk berlawanan arah jarum jam sebesar 90 derajat. + rotate180: + name: Pemutar (180 derajat) + description: Memutar bentuk searah jarum jam sebesar 180 derajat. 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: Penumpuk + description: Menggabungkan kedua input. Apabila mereka tidak dapat digabungkan, + bentuk kanan akan diletakkan diatas bentuk kiri. mixer: default: - name: &mixer Color Mixer - description: Mixes two colors using additive blending. - + name: Pencampur Warna + description: Mencampurkan dua warna. painter: default: - name: &painter Painter - description: &painter_desc Colors the whole shape on the left input with the color from the top input. - + name: Pengecat + description: Mengecat keseluruhan bentuk dari input kiri dengan warna dari input + atas. mirrored: - name: *painter - description: *painter_desc - + name: Pengecat + description: Mengecat keseluruhan bentuk dari input kiri dengan warna dari input + bawah. double: - name: Painter (Double) - description: Colors the shapes on the left inputs with the color from the top input. + name: Pengecat (Ganda) + description: Mengecat bentuk-bentuk dari input kiri dengan warna dari input + atas. quad: - name: Painter (Quad) - description: Allows you to color each quadrant of the shape with a different color. - + name: Pengecat (Empat Bagian) + description: Memungkinkan kamu untuk mengecat tiap kuadrannya masing - masing + pada bentuk. Hanya menyambung dengan sinyal yang + benar pada lapisan kabel yang akan dicat! 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. - - energy_generator: - deliver: Deliver - - # This will be shown before the amount, so for example 'For 123 Energy' - toGenerateEnergy: For - + name: Tong Sampah + description: Menerima input dari segala sisi dan menghancurkannya. Selamanya. + balancer: default: - name: &energy_generator Energy Generator - description: Generates energy by consuming shapes. - - wire_crossings: - default: - name: &wire_crossings Wire Splitter - description: Splits a energy wire into two. - + name: Penyeimbang + description: Multifungsional - Mendistribusikan seluruh input secara merata ke + seluruh output. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Penggabung Kompak + description: Menggabungkan dua sabuk konveyor menjadi satu. + merger-inverse: + name: Penggabung Kompak + description: Menggabungkan dua sabuk konveyor menjadi satu. + splitter: + name: Pemisah Kompak + description: Memisahkan satu sabuk konveyor menjadi dua. + splitter-inverse: + name: Pemisah Kompak + description: Memisahkan satu sabuk konveyor menjadi dua. + storage: + default: + name: Tempat Penyimpanan + description: Menyimpan bentuk yang berlebihan, hingga kapasitas tertentu. + Memprioritaskan output dari kiri dan dapat digunakan sebagai gerbang luapan. + wire_tunnel: + default: + name: Terowongan Kabel + description: Memungkinkan untuk menyebrangkan 2 kabel tanpa menyambungkannya. + constant_signal: + default: + name: Sinyal Konstan + description: Memancarkan sinyal yang konstan, dapat berupa bentuk, warna atau + boolean (1 atau 0). + lever: + default: + name: Saklar + description: Dapat digunakan untuk mengeluarkan sinyal boolean (1 atau 0) pada + lapisan kabel, yang bisa digunakan untuk mengontrol komponen, seperti + filter item. + logic_gate: + default: + name: Gerbang AND + description: Mengeluarkan boolean "1" jika kedua input adalah benar. (Benar + berarti sebuah bentuk, warna atau boolean "1") + not: + name: Gerbang NOT + description: Mengeluarkan boolean "1" jika input adalah tidak benar. (Benar + berarti sebuah bentuk, warna atau boolean "1") + xor: + name: Gerbang XOR + description: Mengeluarkan boolean "1" jika salah satu input adalah benar, namun bukan + keduanya. (Benar berarti sebuah bentuk, warna atau boolean "1") + or: + name: Gerbang OR + description: Mengeluarkan boolean "1" jika satu input adalah benar. (Benar + berarti sebuah bentuk, warna atau boolean "1") + transistor: + default: + name: Transistor + description: Melanjutkan sinyal dari input bawah jika input samping adalah benar + (sebuah bentuk, warna atau boolean "1") + mirrored: + name: Transistor + description: Melanjutkan sinyal dari input bawah jika input samping adalah benar + (sebuah bentuk, warna atau boolean "1") + filter: + default: + name: Filter + description: Hubungkan sebuah sinyal untuk merutekan semua benda yang cocok ke + atas dan sisanya ke kanan. Dapat juga dikontrol dengan sinyal + boolean. + display: + default: + name: Layar + description: Hubungkan sebuah sinyal untuk ditunjukkan pada layar - Dapat + berupa bentuk, warna atau boolean. + reader: + default: + name: Pembaca Sabuk Konveyor + description: Memungkinkan untuk mengukur rata-rata benda yang melewati sabuk + konveyor. Mengeluarkan output benda terakhir yang dilewati pada + lapisan kabel (Setelah terbuka). + analyzer: + default: + name: Penganalisa bentuk + description: Menganalisa bentuk bagian kanan atas pada lapisan paling bawah + lalu mengeluarkan bentuk dan warnanya. + comparator: + default: + name: Pembanding + description: Mengeluarkan boolean "1" jika kedua sinyalnya adalah sama. Dapat + membandingkan bentuk, warna dan boolean. + virtual_processor: + default: + name: Pemotong Virtual + description: Memotong bentuk menjadi dua bagian secara virtual. + rotater: + name: Pemutar Virtual + description: Memutar bentuk searah jarum jam secara virtual. + unstacker: + name: Pemisah Tumpukan Virtual + description: Memisahkan lapisan paling atas ke output kanan dan + sisanya ke output kiri secara virtual. + stacker: + name: Penumpuk Virtual + description: Menumpuk bentuk kanan ke bentuk kiri secara virtual. + painter: + name: Pengecat Virtual + description: Mengecat bentuk dari input bawah dengan warna dari input kanan secara virtual. + item_producer: + default: + name: Pembuat Bentuk + description: Hanya tersedia di dalam mode sandbox, mengeluarkan sinyal yang + diberikan dari lapisan kabel ke lapisan biasa. 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: Memotong Bentuk + desc: Pemotong telah dibuka, yang dapat memotong bentuk menjadi + dua secara vertikal apapun + orientasinya!

Pastikan untuk membuang sisanya, jika + tidak ini dapat tersumbat dan macet - + Oleh karena itu kamu diberikan tong sampah, yang + menghapus semua yang kamu masukkan! reward_rotater: - title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. - + title: Memutar + desc: Pemutar telah dibuka! Ia memutar bentuk-bentuk searah + jarum jam sebesar 90 derajat. 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 colorblind mode in the settings! - + title: Mengecat + desc: "Pengecat telah dibuka – Ekstrak beberapa warna + (seperti yang kamu lakukan dengan bentuk) dan kemudian kombinasikan + dengan bentuk di dalam pengecat untuk mewarnai mereka!

+ NB: Apabila kamu buta warna, terdapat mode buta + warna di dalam pengaturan!" reward_mixer: - title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! - + title: Mencampur Warna + desc: Pencampur Warna telah dibuka – Ia mencampur dua warna menjadi satu! 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: Penumpuk + desc: Kamu sekarang dapat mengombinasikan bentuk-bentuk dengan + penumpuk! Kedua input akan dikombinasikan, dan + apabila mereka dapat diletakan disebelah satu sama lain, mereka + akan terpadukan. Apabila tidak bisa, maka input kanan + akan diletakkan diatas input kiri! 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: Pembagi Sederhana + desc: Kamu telah membuka varian pembagi dari + penyeimbang - Menerima satu input dan membaginya + menjadi dua! reward_tunnel: - title: Tunnel - desc: The tunnel has been unlocked - You can now tunnel items through belts and buildings with it! - + title: Terowongan + desc: Terowongan telah dibuka – Sekarang kamu dapat memindahkan + bentuk-bentuk melalui terowongan di bawah sabuk-sabuk konveyor dan + bangungan-bangunan dengannya! 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: Memutar Berlawanan Arah Jarum Jam + desc: Kamu telah membuka varian dari Pemutar - Bangunan ini memungkinkan + kamu untuk memutar bentuk-bentuk berlawanan arah jarum jam! Untuk + membangunnya, pilih pemutar dan tekan 'T' to memilih + varian! 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: Ekstraktor Merantai + desc: "Kamu telah membuka Ekstraktor (Berantai)! Bangunan ini dapat + mengoper sumber daya ke ekstraktor depannya + sehingga kamu dapat mengekstrak sumber daya dengan lebih + efisien!

NB: Ekstraktor yang lama sudah diganti pada toolbar + kamu sekarang!" 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! - - 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 belt! - + title: Terowongan Tingkat II + desc: Kamu telah membuka varian baru terowongan - Bangunan ini memiliki + jangkauan yang lebih panjang, dan sekarang kamu + juga dapat memadukan terowongan-terowongan tersebut! 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: Pemotongan Empat Bagian + desc: Kamu telah membuka varian dari pemotong - Bangunan ini memungkinkan + kamu untuk memotong bentuk-bentuk menjadi empat bagian + daripada hanya dua bagian! 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! - - 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! - + title: Pengecatan Ganda + desc: Kamu telah membuka varian dari pengecat - Bangunan ini bekerja + seperti pengecat biasa namun dapat memproses dua bentuk + sekaligus, dan mengonsumsi hanya satu warna daripada dua! 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! - + title: Tempat Penyimpanan + desc: Kamu telah membuka Tempat Penyimpanan - Bangunan ini memungkinkan + kamu untuk menyimpan item hingga kapasitas tertentu!

Bangunan ini + mengutamakan output kiri, sehingga kamu dapat menggunakannya sebagai + gerbang luapan (overflow gate)! 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: Permainan Bebas + desc: Kamu berhasil! Kamu telah membuka mode permainan bebas! + Ini artinya bentuk-bentuk akan dibuat secara + acak!

Karena bangunan pusat akan + membutuhkan penghasilan dari sekarang, Saya sangat + menyarankan untuk membangun mesin yang secara otomatis mengirim + bentuk yang diminta!

Bangunan pusat mengeluarkan bentuk + yang diminta pada lapisan kabel, jadi yang harus kamu lakukan adalah + menganalisa dan membangun pabrik secara otomatis berdasarkan itu. 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). - - # Special reward, which is shown when there is no reward actually + title: Cetak Biru + desc: Kamu sekarang dapat menyalin (copy) dan menempel (paste) bagian dari + pabrikmu! Pilih sebuah area (tahan CTRL, lalu seret dengan + mouse), dan tekan 'C' untuk menyalinnya.

Untuk + menempelnya tidak gratis, Kamu harus memproduksi + bentuk cetak biru untuk dapat melakukannya! (Bentuk + yang baru saja kamu kirim). 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! - + title: Level Selanjutnya + desc: "Level ini tidak memiliki hadiah, namun yang selanjutnya akan!

+ NB: Sebaiknya kamu jangan hancurkan pabrik yang telah ada – + Kamu akan membutuhkan semua bentuk-bentuk tersebut lagi + nanti untuk membuka tingkatan-tingkatan + selanjutnya!" no_reward_freeplay: - title: Next level - desc: >- - Congratulations! By the way, more content is planned for the standalone! - + title: Level Selanjutnya + desc: Selamat! Omong-omong, lebih banyak konten telah direncanakan untuk versi + lengkap! + reward_balancer: + title: Penyeimbang + desc: Penyeimbang multifungsional telah terbuka - Bangunan ini dapat + digunakan untuk membuat pabrik yang lebih besar lagi dengan memisahkan + dan menggabungkan item ke beberapa sabuk konveyor! + reward_merger: + title: Penggabung Sederhana + desc: Kamu telah membuka varianpenggabung dari + penyeimbang - Bangunan ini menerima dua input dan + menggabungkannya dalam satu sabuk konveyor! + reward_belt_reader: + title: Pembaca Sabuk Konveyor + desc: Kamu telah membuka pembaca sabuk konveyor! Bangunan ini + memungkinkan kamu untuk mengukur penghasilan dalam sebuah sabuk + konveyor.

Dan tunggu sampai kamu membuka kabel - maka bangunan ini + akan sangat berguna! + reward_rotater_180: + title: Pemutar (180 derajat) + desc: Kamu telah membuka pemutar 180 derajat! - Bangunan ini + memungkinkan kamu untuk memutar bentuk dalam 180 derajat (Kejutan! + :D) + reward_display: + title: Layar + desc: "Kamu baru saja membuka Layar - Hubungkan sebuah sinyal + dalam lapisan kabel untuk memvisualisasikannya!

NB: Apakah + kamu memperhatikan pembaca sabuk dan penyimpanan mengeluarkan item + bacaan terakhir? Coba tampilkan pada layar!" + reward_constant_signal: + title: Sinyal Konstan + desc: Kamu telah membuka bangunan sinyal konstan pada lapisan + kabel! Bangunan ini berguna untuk menyambungkannya ke filter item + contohnya.

Sinyal konstannya dapat memancarkan + bentuk, warna atau + boolean (1 atau 0). + reward_logic_gates: + title: Gerbang Logis + desc: Kamu telah membuka gerbang logis! Kamu tidak perlu bersemangat + tentang ini, tetapi sebenarnya ini sangat keren!

Dengan gerbang-gerbang tersebut + kamu sekarang dapat mengkalkulasi operasi AND, OR, XOR dan NOT.

Sebagai bonus + kamu juga telah mendapatkan transistor! + reward_virtual_processing: + title: Prosesi Virtual + desc: Kamu baru saja mendapatkan banyak bangunan yang memungkinkan kamu untuk + menstimulasi prosesi pembuatan bentuk!

Kamu sekarang + dapat menstimulasi pemotongan, pemutaran, penumpukan dan masih banyak lagi pada lapisan kabel! + Dengan ini kamu sekarang memiliki tiga opsi untuk melanjutkan permainan:

- + Membuat sebuah mesin otomatis untuk membuat segala bentuk + yang diminta oleh PUSAT (Saya sarankan kamu untuk mencobanya!).

- Membuat + sesuatu yang keren dengan kabel.

- Melanjutkan permainan seperti + biasa.

Apapun yang kamu pilih, ingatlah untuk bersenang-senang! + reward_wires_painter_and_levers: + title: Kabel & Pengecat (Empat Bagian) + desc: "Kamu baru saja membuka Lapisan Kabel: Ini adalah sebuah + lapisan terpisah diatas lapisan biasa dan memperkenalkan banyak mekanisme + baru!

Untuk permulaan kamu telah membuka Pengecat (Empat + Bagian) - Hubungkan slot yang ingin kamu cat pada + lapisan kabel!

Untuk mengubah ke lapisan kabel, tekan tombol + E.

NB: Nyalakan petunjuk di + pengaturan untuk mengaktifkan tutorial kabel!" + reward_filter: + title: Filter Item + desc: Kamu telah membuka Filter! Bangunan ini akan mengarahkan item baik + ke output atas atau output kanan tergantung apakah mereka cocok dengan + sinyal dari lapisan kabel atau tidak.

Kamu juga bisa memasukkan + sinyal boolean (1 atau 0) untuk mengaktifkan atau menonaktifkannya. + reward_demo_end: + title: Akhir dari Demo + desc: Kamu telah mencapai akhir dari versi demo! settings: - title: Settings + title: Pengaturan categories: - game: Game - app: Application - + general: Umum + userInterface: Antarmuka Pengguna + advanced: Terdepan + performance: Performa versionBadges: - dev: Development - staging: Staging - prod: Production - buildDate: Built - + dev: Pengembangan + staging: Tahapan + prod: Produksi + buildDate: Dibangun labels: uiScale: - title: Interface scale - 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. + title: Skala Antarmuka (User Interface) + description: Ganti ukuran antarmuka pengguna. Antarmuka tetap akan berskalakan + berdasar resolusi perangkatmu, tetapi pengaturan ini + mengontrol besar skala. scales: - super_small: Super small - small: Small - regular: Regular - large: Large - huge: Huge - + super_small: Sangat kecil + small: Kecil + regular: Reguler + large: Besar + huge: Sangat besar autosaveInterval: - title: Autosave Interval - description: >- - Controls how often the game saves automatically. You can also disable it entirely here. - + title: Jeda Penyimpanan Otomatis + description: Mengatur seberapa sering permainan menyimpan secara otomatis. Kamu + juga dapat menonaktifkannya secara total disini. 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 Menit + two_minutes: 2 Menit + five_minutes: 5 Menit + ten_minutes: 10 Menit + twenty_minutes: 20 Menit + disabled: Dinonaktifkan scrollWheelSensitivity: - title: Zoom sensitivity - description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + title: Kepekaan Zoom + description: Mengubah seberapa peka zoom yang dilakukan (baik dengan roda + mouse atau trackpad). sensitivity: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super fast - + super_slow: Sangat lambat + slow: Lambat + regular: Reguler + fast: Cepat + super_fast: Sangat cepat movementSpeed: - title: Movement speed - description: >- - Changes how fast the view moves when using the keyboard. + title: Kecepatan gerakan + description: Mengubah seberapa cepat pandangan bergerak ketika menggunakan keyboard atau mouse. speeds: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super Fast - extremely_fast: Extremely Fast - + super_slow: Sangat lambat + slow: Lambat + regular: Reguler + fast: Cepat + super_fast: Sangat cepat + extremely_fast: Luar biasa cepat language: - title: Language - description: >- - Change the language. All translations are user-contributed and might be incomplete! - + title: Bahasa + description: Ganti bahasa. Semua terjemahan adalah kontribusi pengguna dan + mungkin saja tidak lengkap! enableColorBlindHelper: - title: Color Blind Mode - description: >- - Enables various tools which allow you to play the game if you are color blind. - + title: Mode buta warna + description: Mengaktifkan berbagai peralatan yang memungkinkan kamu bermain + apabila kamu buta warna. fullscreen: - title: Fullscreen - description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. - + title: Layar penuh + description: Direkomendasikan untuk bermain dengan layar penuh untuk mendapatkan + pengalaman terbaik. Hanya tersedia dalam versi lengkap. soundsMuted: - title: Mute Sounds - description: >- - If enabled, mutes all sound effects. - + title: Bisukan suara + description: Apabila diaktifkan, membisukan semua efek suara. musicMuted: - title: Mute Music - description: >- - If enabled, mutes all music. - + title: Bisukan musik + description: Apabila diaktifkan, membisukan semua musik. theme: - title: Game theme - description: >- - Choose the game theme (light / dark). + title: Tema permainan + description: Pilih tema permainan (terang/gelap). themes: - dark: Dark - light: Light - + dark: Gelap + light: Terang refreshRate: - title: Simulation Target - 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. - + title: Laju Penyegaran (Tick Rate) + description: Apabila kamu 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 komputer kamu terlalu lambat. alwaysMultiplace: - title: Multiplace - description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. - + title: Peletakkan Ganda + description: Apabila diaktifkan, semua bangunan akan tetap terpilih setelah + penempatan sampai kamu membatalkannya. Ini sama saja dengan + menahan tombol SHIFT secara permanen. offerHints: - title: Hints & Tutorials - 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. - + title: Petunjuk & Tutorial + description: Akan menawarkan petunjuk dan tutorial ketika bermain. Juga + menyembunyikan elemen-elemen antarmuka pengguna (user interface) + tertentu sampai level tertentu untuk membuat lebih mudah untuk + bermain. enableTunnelSmartplace: - title: Smart Tunnels - description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. This also enables you to drag tunnels and excess tunnels will get removed. - + title: Terowongan Cerdas + description: Ketika diaktifkan, proses penempatan terowongan akan menghapus + konveyor yang tidak berguna secara otomatis. Ini juga + memungkinkan kamu untuk menyeret terowongan dan kelebihan + terowongan akan dihilangkan. vignette: title: Vignette - description: >- - Enables the vignette, which darkens the screen corners and makes text easier to read. - + description: Mengaktifkan vignette, yang menggelapkan sudut-sudut layar dan + membuat teks lebih mudah dibaca. 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. - + title: Pemutaran masing-masing tipe bangunan + description: Setiap tipe bangunan mengingat putaran atau rotasi yang kamu tetapkan + kepadanya. Ini mungkin lebih nyaman apabila kamu sering berganti + untuk menempatkan berbagai tipe bangunan. compactBuildingInfo: - title: Compact Building Infos - description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. - + title: Pemadatan Informasi Bangunan + description: Memendekkan kotak-kotak informasi bangunan-bangunan dengan hanya + menampilkan rasionya. Jika tidak, deskripsi dan gambar + ditampilkan. disableCutDeleteWarnings: - title: Disable Cut/Delete Warnings - description: >- - Disables the warning dialogs brought up when cutting/deleting more than 100 entities. - + title: Nonaktifkan Peringatan Pemindahan/Penghapusan + description: Menonaktifkan peringatan yang muncul ketikan pemindahkan/menghapus + lebih dari 100 entitas. + soundVolume: + title: Volume Suara + description: Mengatur volume untuk efek suara + musicVolume: + title: Volume Musik + description: Mengatur volume untuk musik + lowQualityMapResources: + title: Kualitas Peta Sumber Daya Rendah + description: Menyederhanakan rendering sumber daya pada peta saat diperbesar untuk meningkatkan performa. + Bahkan terlihat lebih rapi, jadi pastikan untuk mencobanya! + disableTileGrid: + title: Nonaktifkan Grid + description: Menonaktifkan ubin grid dapat membantu performa. + Ini juga membuat game menjadi lebih rapi! + clearCursorOnDeleteWhilePlacing: + title: Menghapus Kursor dengan Klik Kanan + description: Diaktifkan secara default, menghapus kursor setiap kali kamu mengklik kanan saat kamu memiliki bangunan yang dipilih untuk penempatan. Jika dinonaktifkan, kamu dapat menghapus bangunan dengan mengklik kanan saat meletakkan bangunan. + lowQualityTextures: + title: Tekstur kualitas rendah (Jelek) + description: Menggunakan kualitas rendah untuk menyelamatkan performa. + Ini akan membuat penampilan game menjadi jelek! + displayChunkBorders: + title: Tampilkan Batasan Chunk + description: Game ini dibagi-bagi menjadi ubin 16x16 bagian, jika pengaturan ini + diaktifkan maka batas dari tiap chunk akan diperlihatkan. + pickMinerOnPatch: + title: Memilih ekstraktor pada tampungan sumber daya + description: Diaktifkan secara default, memilih ekstraktor apabila kamu menggunakan pipet ketika + mengarahkan pada tampungan sumber daya. + simplifiedBelts: + title: Sabuk Sederhana (Jelek) + description: Tidak merender item pada sabuk konveyor kecuali ketika mengarahkan ke konveyor + untuk menyelamatkan performa. Saya tidak merekomendasikan untuk bermain dengan pengaturan ini + jika kamu tidak benar-benar perlu performanya. + enableMousePan: + title: Bergeser pada Layar Tepi + description: Memungkinkan untuk memindahkan peta dengan menggerakkan kursor ke tepi layar. Kecepatannya tergantung pada pengaturan Kecepatan Gerakan. + zoomToCursor: + title: Zoom ke arah Kursor + description: Jika dinyalakan maka zoom akan terjadi pada arah dan posisi kursor, + sebaliknya zoom kana mengarah pada tengah layar. + mapResourcesScale: + title: Ukuran Sumber Daya Peta + description: Mengontrol ukuran bentuk-bentuk pada gambaran peta (ketika zoom out). + rangeSliderPercentage: % keybindings: - title: Keybindings - hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - - resetKeybindings: Reset Keybindings - + title: Tombol Pintas + hint: "Petunjuk: Pastikan kamu menggunakan CTRL, SHIFT and ALT! Mereka + memungkinkan berbagai opsi penempatan." + resetKeybindings: Setel Ulang Tombol Pintas categoryLabels: - general: Application - ingame: Game - navigation: Navigating - placement: Placement - massSelect: Mass Select - buildings: Building Shortcuts - placementModifiers: Placement Modifiers - + general: Aplikasi + ingame: Permainan + navigation: Navigasi + placement: Penempatan + massSelect: Pemilihan Massal + buildings: Tombol Pintas Bangunan + placementModifiers: Pengubah Penempatan mappings: - confirm: Confirm - back: Back - mapMoveUp: Move Up - mapMoveRight: Move Right - mapMoveDown: Move Down - mapMoveLeft: Move Left - mapMoveFaster: Move Faster - centerMap: Center Map - + 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: Zoom in mapZoomOut: Zoom out - createMarker: Create Marker - - 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: 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 - + createMarker: Buat penanda + menuOpenShop: Tingkatan-tingkatan + menuOpenStats: Statistik + menuClose: Tutup menu + toggleHud: Aktifkan HUD + toggleFPSInfo: Aktifkan FPS dan Informasi Debug + switchLayers: Ganti lapisan + exportScreenshot: Ekspor keseluruhan pabrik sebagai Screenshot + belt: Sabuk Konveyor + underground_belt: Terowongan + miner: Ekstraktor + cutter: Pemotong + rotater: Pemutar + stacker: Penumpuk + mixer: Pencampur Warna + painter: Pengecat + trash: Tong Sampah + wire: Kabel + pipette: Pipet + rotateWhilePlacing: Putar + rotateInverseModifier: "Modifier: Putar berlawanan arah jarum jam sebagai gantinya" + cycleBuildingVariants: Ganti varian + confirmMassDelete: Hapus area + pasteLastBlueprint: Tempel (paste) 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: Salin (copy) area + massSelectCut: Pindahkan (cut) area + placementDisableAutoOrientation: Nonaktifkan orientasi otomatis + placeMultiple: Tinggal di mode penempatan + placeInverse: Balikkan orientasi otomatis konveyor + balancer: Penyeimbang + storage: Tempat Penyimpanan + constant_signal: Sinyal Konstan + logic_gate: Gerbang Logis + lever: Saklar + filter: Filter + wire_tunnel: Terowongan Kabel + display: Layar + reader: Pembaca Sabuk Konveyor + virtual_processor: Pemotong Virtual + transistor: Transistor + analyzer: Penganalisa Bentuk + comparator: Pembanding + item_producer: Pembuat Item + copyWireValue: "Kabel: Salin nilai di bawah kursor" about: - title: About this Game + title: Tentang permainan ini body: >- - This game is open source and developed by Tobias Springer (this is me).

+ Permainan ini bekerja secara open source dan dikembangkan oleh Tobias Springer + (ini adalah saya).

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

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

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

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

- 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. + Lagunya dibuat oleh Peppsen - Dia mengagumkan.

+ Akhir kata, banyak terima kasih kepada teman baik saya Niklas - Tanpa sesi-sesi factorio kami, permainan ini tidak mungkin tercipta. changelog: - title: Changelog - + title: Catatan Perubahan demo: features: - restoringGames: Restoring savegames - importingGames: Importing savegames - oneGameLimit: Limited to one savegame - customizeKeybindings: Customizing Keybindings - exportingBase: Exporting whole Base as Image - - settingNotAvailable: Not available in the demo. + 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. +tips: + - Bangunan pusat menerima segala input, tidak hanya bentuk sekarang! + - Pastikan pabrikmu berbentuk modul - akan membantu! + - Jangan membangun terlalu dekat PUSAT, atau akan terjadi kericuhan yang besar! + - Apabila penumpukkan tidak bekerja, cobalah tukar kedua input. + - Kamu bisa mengaktifkan Perencana Sabuk Konveyor dengan menekan tombol R. + - Menahan CTRL memungkinkan untuk menyeret sabuk konveyor tanpa rotasi otomatis. + - Rasio akan tetap sama, selama semua upgrade berada pada Tingkatan yang sama. + - Eksekusi atau pembuatan secara serial lebih efisian daripada paralel. + - Kamu akan membuka lebih banyak variasi bangunan nanti dalam game! + - Kamu bisa menggunakan tombol T untuk berganti antara varian. + - Simetri adalah kunci! + - Kamu dapat memadukan dua varian terowongan dalam satu baris ubin. + - Cobalah untuk membuat pabrik yang kompak dan padat - akan membantu! + - Pengecat memiliki varian lain yang bisa kamu pilih dengan menekan tombol T + - Memiliki rasio bangunan yang tepat dapat memaksimalkan efektivitas. + - Pada level maksimum, 5 ekstraktor akan memenuhi 1 sabuk konveyor. + - Jangan lupa tentang terowongan! + - Kamu tidak perlu membagi item secara merata untuk meraih efisiensi maksimal. + - Menahan SHIFT akan mengaktifkan Perencana Sabuk Konveyor, memungkinkan kamu untuk meletakkan sabuk konveyor yang panjang dengan mudah + - Pemotong selalu memotong secara vertikal, bagaimanapun orientasinya. + - Untuk mendapatkan warna putih, campurkan ketiga warna. + - Tempat penyimpanan memprioritaskan output pertama. + - Gunakan waktu untuk menciptakan desain yang dapat diulang - itu sangat berharga! + - Menahan CTRL memungkinkan untuk meletakkan beberapa bangunan. + - Kamu dapat menahan ALT untuk memutar arah pada sabuk konveyor yang sudah diletakkan. + - Efisiensi adalah kunci! + - Tampungan bentuk yang semakin jauh dari pusat maka akan semakin kompleks. + - Mesin-mesin memiliki kecepatan maksimum, bagilah mereka untuk mendapatkan efisiensi maksimal. + - Gunakan penyeimbang untuk memaksimalkan efisiensi pabrikmu. + - Pabrik yang terorganisir itu penting. Cobalah untuk tidak banyak menyebrangi konveyor. + - Rencanakan terlebih dahulu, atau akan menjadi kericuhan yang besar! + - Jangan hapus pabrik-pabrik lama kamu! Kamu akan memerlukannya untuk membuka tingkatan. + - Cobalah untuk menyelesaikan level 20 sebelum mencari bantuan! + - Jangan mempersulit hal-hal, cobalah untuk tetap simpel dan kamu akan maju. + - Kamu mungkin perlu menggunakan ulang pabrik-pabrik yang telah kamu buat. Rencanakan pabrik kamu supaya dapat digunakan kembali. + - Terkadang, kamu dapat menemukan bentuk yang diperlukan pada peta tanpa harus menumpuknya. + - Bentuk penuh windmills dan pinwheels tidak akan pernah muncul secara natural. + - Warnai bentuk sebelum memotongnya untuk meningkatkan efisiensi. + - Dengan modul-modul, ruang hanyalah persepsi; sebuah kekhawatiran untuk seorang yang hidup. + - Buatlah pabrik Cetak Biru yang terpisah. Mereka sangat penting untuk membuat modul. + - Perhatikan lebih dekat pencampur warnanya, dan pertanyaanmu akan terjawab. + - Gunakan CTRL + Klik untuk memilih sebuah area. + - Bangunan yang terlau dekat dengan pusat dapat menghalangi projek yang akan datang. + - Ikon pin di samping tiap bentuk pada tab upgrade akan mem-pin bentuknya ke layar. + - Campur semua warna utama untuk menciptakan warna putih! + - Kamu punya peta yang tak terbatas, jadi jangan memadatkan pabrikmu di pusat, luaskan! + - Cobalah Factorio juga! Itu game favorit saya. + - Pemotong (Empat Bagian) memotong searah jarum jam mulai dari bagian kanan atas! + - Kamu bisa mengunduh data simpananmu di menu utama (main menu)! + - Game ini memiliki banyak tombol pintas yag sangat berguna! Pastikan untuk mengeceknya di pengaturan. + - Game ini memiliki banyak pengaturan, Pastikan untuk mengeceknya! + - Penanda ke bangunan pusatmu memiliki kompas yang menunjukkan lokasinya! + - Untuk membersihkan sabuk konveyor, pindahkan bagian dan tempel di lokasi yang sama. + - Tekan F4 untuk menunjukkan FPS dan Tick Rate kamu. + - Tekan F4 dua kali untuk menunjukkan ubin mouse dan kameramu. + - Kamu bisa mengklik bentuk yang di-pin di sebelah kiri untuk tidak mem-pinnya lagi. diff --git a/translations/base-it.yaml b/translations/base-it.yaml index 8583a102..f03072e1 100644 --- a/translations/base-it.yaml +++ b/translations/base-it.yaml @@ -1,111 +1,64 @@ -# -# 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: In shapez.io potrai costruire delle fabbriche per automatizzare la creazione e la combinazione di forme sempre più complesse, in una mappa infinita. + shortText: In shapez.io potrai costruire delle fabbriche per automatizzare la + creazione e la combinazione di forme sempre più complesse, in una mappa + infinita. + discordLinkShort: Discord ufficiale + intro: >- + Shapez.io è un gioco tranquillo nel quale dovrai costruire delle + fabbriche per la produzione automatizzata di forme geometriche. - # 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] + All'aumentare del livello, le forme diventeranno sempre più complesse e dovrai espanderti sempre di più nella mappa infinita. - 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. + E come se non bastasse, dovrai produrre esponenzialmente di più per soddisfare le richieste, l'unica possibilità è andare su grande scala! - 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]! + All'inizio lavorerai solo con le forme, ma in seguito dovrai colorarle; a questo scopo dovrai estrarre e mescolare i colori! - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! + Comprare il gioco su Steam ti garantirà l'accesso alla versone completa, ma puoi anche giocare una demo su shapez.io e decidere in seguito! + title_advantages: Vantaggi della versione completa + advantages: + - 12 nuovi livelli per un totale di 26 livelli + - 18 nuovi edifici per una fabbrica completamente automatizzata! + - 20 gradi di miglioramenti per molte ore di divertimento! + - L'aggiornamento dei Cavi per una dimensione completamente nuova! + - Modalità scura! + - Salvataggi illimitati + - Etichette illimitate + - Mi sostieni! ❤️ + title_future: Contenuti pianificati + planned: + - Archivio dei progetti (esclusiva della versione completa) + - Achievement di steam + - Modalità puzzle + - Minimappa + - Mod + - Modalità sandbox + - ... e molto altro! + title_open_source: Questo gioco è open source! + title_links: Link + links: + discord: Server Discord ufficiale + roadmap: Tabella di marcia + subreddit: Reddit + source_code: Codice sorgente (GitHub) + translate: Aiutaci a tradurre + text_open_source: >- + Chiunque può contribuire, partecipo attivamente nella community e cerco + di leggere tutti i suggerimenti e di prendere in considerazione tutti i + feedback, quando possibile. + Controlla la mia pagina di trello per la tabella di marcia completa! global: loading: Caricamento error: Errore - - # 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. + thousandsDivider: "'" + decimalSeparator: "," suffix: thousands: k millions: M - billions: B + billions: G trillions: T - - # Shown for infinitely big numbers infinite: inf - time: - # Used for formatting past time dates oneSecondAgo: un secondo fa xSecondsAgo: secondi fa oneMinuteAgo: un minuto fa @@ -114,14 +67,10 @@ global: xHoursAgo: ore fa oneDayAgo: un giorno fa xDaysAgo: giorni fa - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s hoursAndMinutesShort: h m - xMinutes: minuti - keys: tab: TAB control: CTRL @@ -129,588 +78,765 @@ global: escape: ESC shift: MAIUSC space: SPAZIO - 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! - + intro: Ottieni la versione completa per sbloccare tutte le funzioni! mainMenu: - play: Play - changelog: Changelog + play: Gioca + changelog: Registro modifiche importSavegame: Importa openSourceHint: Questo gioco è open source! discordLink: Server ufficiale Discord helpTranslate: Aiutaci a tradurre! - - # 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. - + browserWarning: 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 subreddit: Reddit - + savegameUnnamed: Senza nome dialogs: buttons: ok: OK 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: title: Errore di importazione - text: >- - Impossibile caricare il salvataggio: - + text: "Impossibile caricare il salvataggio:" importSavegameSuccess: title: Salvataggio importato - text: >- - Il tuo salvataggio è stato importato correttamente. - + text: Il tuo salvataggio è stato importato correttamente. gameLoadFailure: title: Partita malfunzionante - text: >- - Impossibile caricare il salvataggio: - + text: "Impossibile caricare il salvataggio:" confirmSavegameDelete: title: Conferma eliminazione - text: >- - Vuoi davvero eliminare la partita? - + text: Sei sicuro di voler eliminare la partita seguente?

+ '' al livello

Da qui in poi + non si può più tornare indietro! savegameDeletionError: title: Impossibile eliminare - text: >- - Impossibile eliminare il salvataggio: - + text: "Impossibile eliminare il salvataggio:" restartRequired: - title: Restart richiesto - text: >- - Per applicare le nuove impostazioni è necessario il Restart del gioco. - + title: Riavvio richiesto + text: 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! - desc: >- - Qui puoi trovare i cambiamenti dall'ultima volta che hai giocato: - + title: Nuovo aggiornamento! + desc: "Qui puoi trovare i cambiamenti dall'ultima volta che hai giocato:" upgradesIntroduction: - title: Aggiornamenti 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. - + title: Miglioramenti sbloccati + desc: Tutte le forme che produci possono essere utilizzate per i miglioramenti. + Non distruggere le tue vecchie fabbriche! 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)! - Sei sicuro di volerlo fare? - + desc: Stai rimuovendo molte strutture ( per essere precisi)! Sei sicuro + di volerlo fare? blueprintsNotUnlocked: title: Non ancora sbloccato - desc: >- - I progetti non sono stati ancora sbloccati! Completa più livelli per sbloccarli. - + desc: I progetti non sono stati ancora sbloccati! Completa più livelli per + sbloccarli. keybindingsIntroduction: 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!

- CTRL + Drag: Seleziona l'area da copiare / cancella.
- SHIFT: Tieni premuto per costruire copie dalla struttura.
- ALT: Invert l'orientamento dei nastri trasportatori.
- + desc: "Questo gioco ha molti comandi utili che possono rendere più semplice la + costruzione delle fabbriche. 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 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: Nuova etichetta + desc: Dagli un nome significativo, puoi anche inserire un + codice di una forma (Che puoi generare + qui) + titleEdit: Modifica etichetta markerDemoLimit: - desc: Puoi creare solo due Marker personalizzati nella Demo. Prendi la versione standalone per Marker personalizzati illimitati! + desc: Puoi creare solo due etichette personalizzate nella Demo. Ottieni la + versione completa per avere etichette personalizzate illimitati! massCutConfirm: title: Conferma taglio - desc: >- - Stai tagliando molte strutture ( to be exact)! - Sei sicuro di volerlo fare? - + desc: 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! - + desc: Hai richiesto di esportare la tua base come screenshot. Perfavore tieni + conto che potrebbe 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? + editSignal: + title: Imposta il segnale + descItems: "Scegli un oggetto predefinito:" + descShortKey: ... o inserisci il codice di una forma (Che puoi + generare qui) + renameSavegame: + title: Rinomina salvataggio. + desc: Qui puoi cambiare il nome del salvataggio. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: 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 - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + switchLayers: Cambia livello 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: Premi per cambiare variante. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - + hotkeyLabel: "Hotkey: " infoTexts: speed: Velocità range: Raggio storage: Spazio oneItemPerSecond: 1 oggetto / secondo - itemsPerSecond: oggetti / s + itemsPerSecond: oggetti / secondo itemsPerSecondDouble: (x2) - - tiles: titles - - # The notification when completing a level + tiles: caselle 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. - - # The "Upgrades" window + newUpgrade: È disponibile un nuovo aggiornamento! + gameSaved: Partita salvata. + freeplayLevelComplete: Il livello è stato completato! shop: - title: Aggiornamenti + title: Miglioramenti buttonUnlock: Sblocca - - # Gets replaced to e.g. "Tier IX" - tier: Tier - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - - maximumLevel: LIVELLO MASSIMO (Speed x) - - # The "Statistics" window + tier: Grado + maximumLevel: GRADO MASSIMO (Velocità x) 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 immagazzinate 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. - noShapesProduced: No shapes have been produced so far. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + title: Consegnate + description: Mostra le forme che vengono consegnate all'edificio centrale. + noShapesProduced: Nessuna forma prodotta finora. + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Tempo di gioco - - buildingsPlaced: Buildings + buildingsPlaced: Edifici beltsPlaced: Nastri - - buttons: - continue: Continua - settings: Impostazioni - menu: Torna al menù - - # Bottom left tutorial hints tutorialHints: title: Serve aiuto? showHint: Mostra indizio hideHint: Chiudi - - # When placing a blueprint blueprintPlacer: cost: Costo - - # Map markers waypoints: - waypoints: Markers + waypoints: Punti di interesse 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. - - # Interactive tutorial + description: Clic sinistro su un etichetta per raggiungerla, clic destro per + cancellarla.

Premi per creare un etichetta + dalla visuale corrente, oppure click destro per + creare un etichetta nella posizione selezionata. + creationSuccessNotification: L'etichetta è stata creata. interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! - 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. - + 1_1_extractor: Posiziona un estrattore sopra una forma + circolare per estrarla! + 1_2_conveyor: "Connetti l'estrattore all'Edificio centrale utilizzando un + nastro trasportatore!

Suggerimento: + Clicca e trascina il nastro con il mouse!" + 1_3_expand: "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." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." colors: red: Rosso green: Verde blue: Blu yellow: Giallo - purple: Viola + purple: Magenta cyan: Azzurro white: Bianco - uncolored: No colore - black: Black + uncolored: Senza colore + black: Nero shapeViewer: - title: Livelli + title: Strati empty: Vuoto - copyKey: Copy Key - -# All shop upgrades + copyKey: Copia codice + connectedMiners: + one_miner: 1 trivella + n_miners: trivelle + limited_items: Limitato a + watermark: + title: Versione demo + desc: Clicca qui per vedere i vantaggi della versione Completa! + get_on_steam: Ottieni su Steam + standaloneAdvantages: + title: Ottieni la versione completa! + no_thanks: No, grazie! + points: + levels: + title: 12 nuovi livelli! + desc: Per un totale di 26 livelli! + buildings: + title: 18 nuovi edifici + desc: Automatizza completamente la tua fabbrica! + savegames: + title: ∞ salvataggi + desc: Quanti ne desideri! + upgrades: + title: 20 gradi di miglioramenti + desc: Questa demo ne ha solo 5! + markers: + title: ∞ etichette + desc: Non perderti nella tua fabbrica! + wires: + title: Cavi + desc: Un'intera nuova dimensione! + darkmode: + title: Modalità scura + desc: Smettila di maltrattare i tuoi occhi! + support: + title: Sostienimi + desc: Lo sviluppo nel tempo libero! 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 buildings: belt: default: - name: &belt Nastro Trasportatore - description: Trasporta oggetti, clicca e trascina per posizionare in sequenza. - - miner: # Internal name for the Extractor + name: Nastro Trasportatore + description: Trasporta oggetti, clicca e trascina per posizionarli in sequenza. + miner: default: - name: &miner Estrattore - description: Posiziona sopra una forma o un colore per estrarlo. - + name: Estrattore + description: Posizionalo sopra una forma o un colore per estrarlo. chainable: name: Estrattore (Catena) - description: Posiziona sopra una forma o un colore per estrarlo. Puoi combinarlo con altri estrattori. - - underground_belt: # Internal name for the Tunnel + description: Posizionalo sopra una forma o un colore per estrarlo. Puoi + combinarlo con altri estrattori. + underground_belt: default: - name: &underground_belt Tunnel - description: Permette di far passare delle risorse sotto a costruzioni e nastri trasportatori. - + name: Tunnel + description: Permette di far passare le risorse sotto alle costruzioni e ai + nastri trasportatori. tier2: name: Tunnel Grado II - description: Permette di far passare delle risorse sotto a costruzioni e nastri trasportatori. - - splitter: # Internal name for the Balancer - default: - name: &splitter Bilanciatore - description: Multifunzionale - Distribuisce equamente tutti gli ingressi su tutte le uscite. - - compact: - name: Aggregatore (compatto) - description: Unisce due nastri trasportatori in uno solo. - - compact-inverse: - name: Aggregatore (compatto) - description: Unisce due nastri trasportatori in uno solo. - + description: Permette di far passare le risorse sotto alle costruzioni e ai + nastri trasportatori. 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: Taglierino + description: Taglia le forme verticalmente e restituisce le due metà a destra e + a 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: Taglierino (4x) + description: Taglia le forme in quattro parti. Se usi meno di quattro + parti, distruggi le altre o la macchina si fermerà! rotater: default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. + name: Ruotatore + description: Ruota le forme di 90 gradi in senso orario. ccw: - name: Rotate (CCW) - description: Rotates shapes counter clockwise by 90 degrees. - + name: Ruotatore (Ant.) + description: Ruota le forme di 90 gradi in senso antiorario. + rotate180: + name: Ruotatore (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: Impilatrice + description: Unisce o impila i due oggetti, se gli oggetti non possono essere + uniti, l'oggetto destro è posizionato sopra il sinstro. mixer: default: - name: &mixer Mixer Colori + name: Miscelatore di vernice description: Mescola due colori mediante sintesi additiva. - painter: default: - name: &painter Verniciatore - description: &painter_desc Colora l'intera forma dell'ingresso sinistro con il colore dell'ingresso destro. + name: Verniciatore + description: Colora l'intera forma dall'ingresso sinistro con il colore + dall'ingresso superiore. double: - name: Verniciatore (Doppio) - description: Colors the shapes on the left inputs with the color from the top input. + name: Verniciatore (2x) + description: Colora le forme dagli ingressi sinistri con il colore dall'ingresso + superiore. quad: - name: Verniciatore (Quadruplo) - description: Allows to color each quadrant of the shape with a different color. + name: Verniciatore (4x) + description: Ti permette di colorare ogni quadrante della forma individualmente. + Solo gli spazi con un Vero sul livello + elettrico saranno colorati! mirrored: - name: *painter - description: *painter_desc - + name: Verniciatore + description: Colora l'intera forma dall'ingresso sinistro con il colore + dall'ingresso inferiore. trash: default: - name: &trash Cestino - description: Accetta ingressi 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: Cestino + description: Accetta oggetti da tutti i lati e li distrugge. Per sempre. hub: deliver: Consegna toUnlock: per sbloccare levelShortcut: LVL + endOfDemo: Fine della demo wire: default: - name: Energy Wire - description: Allows you to transport energy. - advanced_processor: + name: Cavo energetico + description: Ti consente di trasportare energia. + second: + name: Cavo + description: Trasmette segnali, che possono essere oggetti, colori o booleani (1 + / 0). Cavi di colore diverso non si connettono. + balancer: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For - default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Bilanciatore + description: Multifunzione, distribuisce equamente gli oggetti in ingresso tra + tutte le uscite. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Aggregatore (compatto) + description: Unisce due nastri in uno. + merger-inverse: + name: Aggregatore (compatto) + description: Unisce due nastri in uno. + splitter: + name: Separatore (compatto) + description: Divide un nastro in due. + splitter-inverse: + name: Separatore (compatto) + description: Divide un nastro in due. + storage: + default: + name: Magazzino + description: Immagazzina gli oggetti in eccesso, fino ad una capacità massima. + Dà priorità all'uscita sinistra e può quindi essere usato per + gestire le eccedenze. + wire_tunnel: + default: + name: Incrocio fra cavi + description: Consente a due cavi di attraversarsi senza connettersi. + constant_signal: + default: + name: Segnale costante + description: Emette un segnale costante, che può essere una forma, un colore o + un booleano (1 / 0). + lever: + default: + name: Interruttore + description: Può essere azionato per emettere un segnale booleano (1 / 0) nel + livello elettrico, che può essere usato per controllare, per + esempio, un filtro. + logic_gate: + default: + name: Porta AND + description: Emette un "1" booleano se entrambi gli ingressi sono veri. (Vero + significa forma, colore o "1" booleano) + not: + name: Porta NOT + description: Emette un "1" booleano se l'ingresso è falso. (Vero significa + forma, colore o "1" booleano) + xor: + name: Porta XOR + description: Emette un "1" booleano se uno degli ingressi è vero, ma non se lo + sono entrambi. (Vero significa forma, colore o "1" booleano) + or: + name: Porta OR + description: Emette un "1" booleano se uno degli ingressi è vero. (Vero + significa forma, colore o "1" booleano) + transistor: + default: + name: Transistore + description: Inoltra il segnale dall'ingresso inferiore se l'ingresso laterale è + vero (una forma, un colore o "1"). + mirrored: + name: Transistore + description: Inoltra il segnale dall'ingresso inferiore se l'ingresso laterale è + vero (una forma, un colore o "1"). + filter: + default: + name: Filtro + description: Collega un segnale per mandare tutti gli oggetti corrispondenti + verso l'alto e i restanti verso destra. Può essere controllato + anche con segnali booleani. + display: + default: + name: Display + description: Collega un segnale per mostrarlo sul display. Può essere una forma, + un colore o un booleano. + reader: + default: + name: Lettore di nastri + description: Misura la portata media del nastro. Emette l'ultimo oggetto + transitato come segnale sul livello dei cavi (una volta + sbloccato). + analyzer: + default: + name: Analizzatore di forma + description: Analizza il quadrante in alto a destra dello strato più basso della + forma e ne restituisce forma e colore. + comparator: + default: + name: Comparatore + description: Emette un "1" booleano se i due segnali sono identici. Può + comparare forme, colori e booleani. + virtual_processor: + default: + name: Taglierino virtuale + description: Taglia virtualmente la forma in due metà. + rotater: + name: Ruotatore virtuale + description: Ruota virtualmente la forma, sia in senso orario sia antiorario. + unstacker: + name: Disimpilatrice virtuale + description: Estrae virtualmente lo strato più alto e lo emette a destra, i + restanti sono emessi a sinistra. + stacker: + name: Impilatrice virtuale + description: Impila virtualmente la forma destra sulla sinistra. + painter: + name: Verniciatore virtuale + description: Vernicia virtualmente la forma dall'ingresso inferiore con il + colore dall'ingresso destro. + item_producer: + default: + name: Generatore di oggetti + description: Disponibile solo nella modalità sandbox, emette il segnale dal + livello elettrico come oggetti sul livello normale. 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: Il taglierino è stato bloccato! Taglia le forme a metà da + sopra a sotto indipendentemente dal suo + orientamento!

Assicurati di buttare via lo scarto, + sennò si intaserà e andrà in stallo - Per questo + ti ho dato il certino, che distrugge tutto quello + che riceve! reward_rotater: - title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. - + title: Rotazione + desc: Il ruotatore è stato sbloccato! Ruota le forme di 90 + gradi in senso orario. 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! - + title: Verniciatura + desc: "Il verniciatore è stato sbloccato! 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 + impostazion!" reward_mixer: - title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! - - 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: Mix colori + desc: Il miscelatore è stato sbloccato! Con questo edificio, + puoi combinare due colori mediante la sintesi + additiva! 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 separatore è stato sbloccato! è una variante del + bilanciatore - Accetta un imput e lo divide in due! 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 del ruotatore! 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: "L'estrattore a catena è stato sbloccato! Può + passare le sue risorse agli altri estrattori, così + tu puoi estrarre le risorse in modo più efficiente!

PS: Il + primo estrattore è stato rimpiazzato nel tuo inventario!" 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! - - 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! - + title: Tunnel grado II + desc: Hai sbloccato una variante del tunnel! Ha un + raggio più ampio e puoi anche mischiare le due + varianti ora! 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 del taglierino! Consente 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! - - 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: Verniciatura doppia + desc: Hai sbloccato una variante del verniciatore! Funziona + come un normale verniciatore, ma processa due forme alla + volta consumando solo un'unità di colore invece che due! 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 il magazzino! Ti permette di immagazzinare + le forme fino a un certo limite!

Dà priorità all'uscita a + sinistra, puoi quindi usarlo per gestire le + eccedenze! 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 le forme da adesso in poi sono generate + casualmente!

Visto che la HUB avrà bisogno + di una portata maggiore Ti consiglio vivamente di + costruire un macchinario che consegna automaticamente la forma + richiesta!

La HUB da come output la forma richiesta sul + livello elettrico, quindi ti basta solo analizzarla e configurare + automaticamente la tua fabbrica in base a quei dati. 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). - - # Special reward, which is shown when there is no reward actually + title: Progetti + desc: Ora puoi copiare ed incollare componenti 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). 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! - + title: Prossimo livello + desc: "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 - desc: >- - Congratulations! By the way, more content is planned for the standalone! - + title: Prossimo livello + desc: Congratulazioni! Ci sono altri contenuti in prgramma per la versione + completa! + reward_stacker: + title: Impilatrice + desc: Ora puoi combinare forme con l'impilatrice! I due + ingressi vengono combinati e se possono essere messi uno accanto + all'altro, verranno fusi. Altrimenti, l'ingresso + destro è impilato sopra il sinistro! + reward_balancer: + title: Bilanciatore + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Aggregatore compatto + desc: Hai sbloccato un aggregatore, variante del + bilanciatore! Acetta due ingressi e li aggrega su + un unico nastro! + reward_belt_reader: + title: Lettore di nastri + desc: Hai sbloccato il lettore di nastri! Consente di misurare + la portata di un nastro.

E aspetta di sbloccare i cavi, + allora sì che sarà molto utile! + reward_rotater_180: + title: Ruotatrice (180 gradi) + desc: Hai appena sbloccato il ruotatore a 180 gradi! Consente + di ruotare una forma di 180 gradi (Sorpresa! :D) + reward_display: + title: Display + desc: "Hai sbloccato il Display! Connetti un segnale sul + livello elettrico per visualizzarlo!

PS: Hai notato che il + lettore di nastri e il magazzino mostrano l'ultimo oggetto da loro + letto? Prova a mostrarlo su di un display!" + reward_constant_signal: + title: Sengale costante + desc: Hai sblocatto l'edificio segnale costante sul livello + elettrico! È utile collegarlo ai filtri di oggetti + per esempio.

Il segnale costante può emettere una + forma, un colore o un + booleano (1 / 0). + reward_logic_gates: + title: Porte logiche + desc: Hai sbloccato le porte logiche! Magari non ne sarai + entusiasta, ma in realtà sono fantastiche!

Con quelle porte + ora puoi eseguire le operazioni logiche di AND, OR, XOR e + NOT.

Come bonus extra ti ho anche regalato un + transistore! + reward_virtual_processing: + title: Lavorazione virtuale + desc: Ti ho appena dato un bel po' di nuovi edifici che ti consentono di + simulare la lavorazione delle forme!

Ora + puoi simulare un taglierino, un ruotatore, un'impilatrice e molto + altro sul livello elettrico! In questo modo hai tre opzioni per + continuare il gioco:

-Costruisci una macchina + automatica per creare ogni possibile forma richiesta + dall'HUB (ti consiglio di provarci!).

- Costruisci qualcosa + di interessante con i cavi.

- Continua a giocare + normalmente.

Qualsiasi cosa tu scelga, ricordati di + divertirti! + reward_wires_painter_and_levers: + title: Cavi e Verniciatrice quadrupla + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Filtro oggetti + desc: Hai sbloccato il filtro oggetti! Smisterà gli oggetti + verso l'alto o verso destra a seconda del segnale dal livello + elettrico o meno.

Puoi anche mandargli un segnale booleano + (1 / 0) per attivarlo o disattivarlo completamente. + reward_demo_end: + title: Fine della demo + desc: Hai raggiunto la fine della demo! settings: title: Impostazioni categories: - game: Gioco - app: Applicazione - + general: Generali + userInterface: Interfaccia utente + advanced: Avanzate + performance: Prestazioni versionBadges: dev: Sviluppo staging: Staging prod: Produzione - buildDate: Built - + buildDate: Build del labels: 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. + title: Dimensione interfaccia + description: 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 - description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + title: Sensibilità zoom + description: 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 - description: >- - Cambia la lingua. Tutte le traduzioni sono realizzate dagli utenti e potrebbero essere incomplete! - + description: Cambia la lingua. Tutte le traduzioni sono realizzate dagli utenti + e potrebbero essere incomplete! fullscreen: - title: Fullscreen - description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. - + title: Schermo intero + description: È consigliabile giocare a schermo intero per la migliore + esperienza. Disponibile solo nella versione completa. soundsMuted: title: Silenzia Suoni - description: >- - Se abilitato, spegne tutti gli effetti sonori. - + description: Se abilitato, spegne tutti gli effetti sonori. musicMuted: title: Silenzia Musica - description: >- - Se abilitato, spegne la musica. - + description: Se abilitato, spegne la musica. theme: title: Tema del gioco - description: >- - Scegli il tema (chiaro / scuro). - + description: Scegli il tema (chiaro / scuro). themes: dark: Scuro light: Chiaro - refreshRate: - title: Simulation Target - 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. - + title: Obiettivo della simulazione + description: 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 - description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. - + title: Posizionamento multiplo + description: Se abilitato, tutti gli edifici rimarranno selezionati dopo il + posizionamento finchè non lo annullerai. È equivalente a tenere + costantemente premuto MAIUSC. 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. - + title: Indizi e tutorial + description: 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 @@ -719,144 +845,185 @@ settings: super_fast: Molto veloce extremely_fast: Velocissimo 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. + title: Tunnel intelligenti + description: "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 - description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. - + title: Vignettatura + description: Abilita la vignettatura che scurisce gli angoli dello schermo e + rende i testi più leggibili. autosaveInterval: - title: Autosave Interval - description: >- - Controls how often the game saves automatically. You can also disable it - entirely here. + title: Intervallo salvataggio automatico + description: 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 - description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a - description and image is shown. + title: Info edifici compatte + description: Accorcia le informazioni sugli edifici mostrandone solo la + velocità. In caso contrario saranno mostrate immagine e + descrizione. disableCutDeleteWarnings: - title: Disable Cut/Delete Warnings - description: >- - Disable the warning dialogs brought up when cutting/deleting more than 100 - entities. - + title: Disabilita avvertimenti taglia/cancella + description: 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 - 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. - + title: Rotazione per tipo di edificio + description: Ogni tipo di edificio ricorderà l'ultimo orientamento che hai + selezionato indipendentemente dagli altri tipi. È utile se cambi + spesso tipo di edificio. + soundVolume: + title: Volume suoni + description: Imposta il volume per gli effetti sonori + musicVolume: + title: Volume musica + description: Imposta il volume per la musica + lowQualityMapResources: + title: Risorse sulla mappa a bassa qualità + description: Semplifica il rendering delle risorse sulla mappa quando ingrandita + per migliorare le prestazioni. Ha anche un aspetto più pulito, + provalo! + disableTileGrid: + title: Disattiva griglia + description: Disattivare la griglia può migliorare le prestazioni. Rende anche + il gioco visualmente più pulito! + clearCursorOnDeleteWhilePlacing: + title: Deseleziona edificio con il clic destro + description: Abilitato di default, se hai un edificio selezionato e premi il + tasto destro, deselezionerai l'edificio. Se disabilitato, puoi + cancellare edifici premendo il tasto destro mentre posizioni + edifici. + lowQualityTextures: + title: Texture in bassa qualità (Brutto) + description: Usa texture a bassa qualità per migliorare le prestazioni. Quesro + renderà il gioco molto brutto! + displayChunkBorders: + title: Mostra confini dei Chunk + description: Il gioco è diviso in blocchi 16x16 (Chunk), se attivi questa + opzione, i confini tra i Chunk verranno mostrati. + pickMinerOnPatch: + title: Scegli estrattore sui giacimenti di risorse + description: Attivato di default, seleziona l'estrattore se usi il contagocce + quando il cursore è su un giacimento risorse. + simplifiedBelts: + title: Nastri semplificati (Brutto) + description: Non renderizza gli oggetti sui nastri a meno che il cursore non sia + sopra il nastro per migliorare le prestazioni. Non lo raccomando + a meno che tu non abbia assolutamente bisogno di migliorare le + prestazioni. + enableMousePan: + title: Abilita scorrimento con il mouse + description: Consente di spostare la mappa spostando il mouse verso il bordo + dello schermo. La velocità dipende dall'impostazione Velocità di + movimento. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: - title: Keybindings - hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - - resetKeybindings: Reset Keyinbindings - + title: Comandi + hint: "Suggerimento: Usa spesso CTRL, MAIUSC e ALT! Abilitano opzioni di + posizionamento alternative." + 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 - - menuOpenShop: Upgrade + mapZoomIn: Aumenta zoom + mapZoomOut: Riduci zoom + createMarker: Crea Etichetta + menuOpenShop: Miglioramenti menuOpenStats: Statistiche - toggleHud: Mostra/Nascondi HUD toggleFPSInfo: Mostra/Nascondi FPS e info debug - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + belt: Nastro Trasportatore + underground_belt: Tunnel + miner: Estrattore + cutter: Taglierino + rotater: Ruotatore + stacker: Impilatrice + mixer: Miscelatore di vernice + painter: Verniciatore + trash: Cestino rotateWhilePlacing: Ruota - rotateInverseModifier: >- - Modifier: Rotate CCW instead + rotateInverseModifier: "Modificatore: Ruota in senso antiorario" cycleBuildingVariants: Cicla varianti confirmMassDelete: Conferma eliminazione di massa - cycleBuildings: Cycle Buildings - - massSelectStart: Hold and drag to start + cycleBuildings: Cambia variante + 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 + wire: Cavo + balancer: Bilanciatore + storage: Magazzino + constant_signal: Segnale costante + logic_gate: Porta logica + lever: Interruttore (normale) + filter: Filtro + wire_tunnel: Incrocio cavi + display: Display + reader: Lettore nastri + virtual_processor: Taglierino virtuale + transistor: Transistore + analyzer: Analizzatore forme + comparator: Comparatore + item_producer: Generatore di oggetti (Sandbox) + copyWireValue: "Cavi: Copia valore sotto il cursore" 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.

- - Finally, huge thanks to my best friend Niklas - Without our - factorio sessions this game would never have existed. + La colonna sonora è stata composta daPeppsen - È un grande.

+ 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 - + title: Registro modifiche demo: features: restoringGames: Recupero salvataggi @@ -864,5 +1031,78 @@ demo: oneGameLimit: Limite di un salvataggio customizeKeybindings: Scorciatoie personalizabili exportingBase: Esportazione dell'intera base come immagine - settingNotAvailable: Non disponibile nella demo. +tips: + - L'hub centrale accetta qualsiasi forma, non solo l'obiettivo corrente! + - Costruisci fabbriche modulari, sarà utile! + - Non costruire troppo vicino all'hub o diventerà tutto caotico! + - Se l'impilamento non funziona, prova a scambiare gli ingressi. + - Puoi cambiare la direzione del pianificatore nastri premendo R. + - Tenere premuto CTRL consente di trascinare i nastri senza + auto-orientamento. + - I rapporti rimangono uguali, fintanto che tutti i miglioramenti sono allo + stesso livello, + - L'esecuzione seriale è più efficiente di quella parallela. + - Più avanti nel gioco sbloccherai altre varianti degli edifici! + - Puoi usare T per cambiare variante. + - La simmetria è la chiave! + - Puoi intrecciare gradi diversi del tunnel. + - Cerca di costruire fabbriche compatte, sarai ricompensato! + - Il verniciatore ha una variante speculare che puoi selezionare con T + - Avere i giusti rapporti tra gli edifici massimizzerà l'efficienza. + - Al massimo livello, 5 estrattori saturano un singolo nastro. + - Non dimenticare i tunnel! + - Non devi per forza dividere gli oggetti equamente per la massima + efficienza. + - Tenere premuto SHIFT attiva il pianificatore nastri, facilitando il + posizionamento dei nastri più lunghi + - I taglierini tagliano sempre in verticale, indipendentemente + dall'orientamento. + - Mischia tutti i tre colori per fare il bianco. + - Il magazzino prioritizza la prima uscita. + - Impiega tempo per costruire design replicabili, ne vale la pena! + - Tenere premuto CTRL ti consente di piazzare multipli edifici. + - Puoi tenere premuto ALT per invertire la direzione dei nastri + posizionati. + - L'efficienza è la chiave! + - I giacimenti più lontani dall'hub contengono forme più complesse. + - Le macchine hanno una velocità limitata, distribuisci il carico per la + massima efficienza. + - Usa i bilanciatori per massimizzare l'efficienza. + - L'organizzazione è importante. Cerca di non incrociare troppo i nastri. + - Pianifica in anticipo, o diventerà tutto caotico! + - Non distruggere le tue vecchie fabbriche! Ti serviranno per sbloccare dei + miglioramenti. + - Cerca di risolvere il livello 20 da solo prima di chiedere aiuto! + - Non complicare le cose, cerca di mantenere la semplicità e farai strada. + - Dovrai riusare le tue fabbriche più avanti nel gioco. Pianifica le tue + fabbriche in modo che siano reutilizzabili. + - A volte, puoi trovare la forma che ti serve nella mappa senza crearla con + le impilatrici. + - Non troverai mai giacimenti di girandole complete. + - Colora le tue forme prima di tagliarle per la massima efficienza. + - Con i moduli, lo spazio è solo percezione, una preoccupazione per uomini + mortali. + - Costruisci una fabbrica dedicata per i progetti. Sono importanti per i + moduli. + - Guarda da vicino il miscelatore di colori, e le tue domande avranno + risposta. + - Usa CTRL + Clic per selezionare un'area. + - Costruire troppo vicino all'hub potrebbe intralciare progetti futuri. + - Premere la puntina vicino a ogni forma nel menù miglioramenti la farà + visualizzare sempre a schermo + - Mescola tutti i colori primari per fare il bianco! + - Hai una mappa infinita, non incastrare la tua fabbrica, espanditi! + - Prova anche factorio! È il mio gioco preferito. + - Il taglierino quadruplo taglia in senso orario a partire dal quadrante in + alto a destra! + - Puoi scaricare i salvataggi dal menù principale! + - Questo gioco ha molti tasti di scelta rapida! Dai un'occhiata alla pagina + delle impostazioni + - Questo gioco ha molte impostazioni, dai un'occhiata! + - L'etichetta dell'hub ha una piccola bussola per indicarne la direzione! + - Per svuotare i nastri, taglia e re-incolla l'area nello stesso punto. + - Premi F4 per mostrare FPS e Tick al secondo. + - Press F4 due volte per mostrare la casella del cursore e della telecamera. + - Puoi cliccare a sinistra di una forma fermata a schermo per rimuoverla + dalla lista. diff --git a/translations/base-ja.yaml b/translations/base-ja.yaml index 3829d1b8..ed10eab3 100644 --- a/translations/base-ja.yaml +++ b/translations/base-ja.yaml @@ -1,127 +1,68 @@ -# -# 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は無限のマップ内で様々な"形"を資源とし、段々と複雑になっていく形の作成や合成の自動化を目指して工場を構築するゲームです。 + discordLinkShort: 公式Discord + intro: >- + 工場の自動化ゲームはお好きですか?それなら間違いないでしょう! - # 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は、様々な幾何学的形状を生成するために工場を建設する、落ち着いたゲームです。レベルが上がる毎に生成すべき形はどんどん複雑になり、工場を無限に広がるマップに拡張する必要があります。 - shapez.ioは無限のマップ内で様々な"形"を資源とし、段々と複雑になっていく形の作成や合成の自動化を目指して工場を構築するゲームです。 - 求められた"形"を届けることで様々なアップグレードを手に入れることができ、さらに工場の効率を上げることができます。 - - "形"の需要が増えるにつれ、工場を拡大する必要があります - より多くの資源を手に入れるために[b]無限のマップ[!b]を開拓していく必要があります。 - - "形"に色を塗る必要もあります - 赤、緑、青を混ぜ、さまざまな色を作り需要に応じて色が塗られた"形"を製造できます。 - - 現在このゲームには18個のレベルがあり、今後これを拡大していく予定です - 他にも様々なアップデートを準備しています! - - このゲームを買うことによってスタンドアローン版の様々な機能が使えるようになり、新しいアップデートもすぐに手に入ります。 - - [b]スタンドアローン版で使える機能[/b] - - [list] - [*] ダークモード - [*] ウェイポイントの制限がありません - [*] セーブの数の制限がありません - [*] 様々な設定 - [*] 追加予定: ワイヤーとエネルギー! (7月末を目指しています) - [*] 追加予定: より多くのレベル - [*] shapez.io開発が助けられます❤️ - [/list] - - [b]今後の予定[/b] - - 週に一回はアップデートを出せることを目指しています。 - - [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]このゲームはオープンソースです![/b] - - 誰でもこのげむの開発を手伝うことができ、私もプレーヤーの意見をできるだけゲームに取り入れようとしています。 - Trelloで今後の予定が全て確認できます。 - - [b]外部リンク[/b] - - [list] - [*] [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: 公式Discord - 私と話せます! + しかし、それだけでは不十分です。需要は指数関数的に上昇し、より多くの形状を生産する必要があり――"スケーリング"が、唯一の対抗策と成り得ます。最初は形状を加工するだけですが、後々着色も必要になってきます――それには色を抽出して、混ぜ合わせることが必要です! + Steamでゲームを購入するとフルバージョンで遊ぶことができますが、まずshapez.ioでデモをプレイし、その後で決めることもできます! + title_advantages: スタンドアロン版の特典 + advantages: + - 新しい12個のレベルが追加され、全部で26個のレベルになります。 + - 新しい18個のパーツが自動化工場建設のために使用できます! + - 20個のアップデートティアによって多くの時間楽しむことができます! + - ワイヤアップデートによって全く新次元の体験を得られます! + - ダークモード! + - セーブ数の上限がなくなります。 + - マップマーカー数の上限がなくなります。 + - 私をサポートできる!❤️ + title_future: 計画中の要素 + planned: + - ブループリント (スタンドアロン版専用) + - Steamの実績 + - パズルモード + - ミニマップ + - MOD対応 + - サンドボックスモード + - ……あともっとたくさんの要素! + title_open_source: このゲームはオープンソースです! + text_open_source: |- + 誰でも参加することができます。私はコミュニティに積極的に参加し、すべての提案を確認し、可能な場合はフィードバックしようとしています。 + 完全なロードマップについては、Trello boardを確認してください! + title_links: リンク + links: + discord: 公式Discord + roadmap: ロードマップ + subreddit: Subreddit + source_code: ソースコード(GitHub) + translate: 翻訳を助けてください! global: loading: ロード中 error: エラー - - # 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. + decimalSeparator: . suffix: thousands: k millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: 無限 - time: - # Used for formatting past time dates - oneSecondAgo: 1 秒前 - xSecondsAgo: 秒前 - oneMinuteAgo: 1 分前 - xMinutesAgo: 分前 - oneHourAgo: 1 時間前 - xHoursAgo: 時間前 - oneDayAgo: 1 日前 - xDaysAgo: 日前 - - # Short formats for times, e.g. '5h 23m' + oneSecondAgo: 1秒前 + xSecondsAgo: 秒前 + oneMinuteAgo: 1分前 + xMinutesAgo: 分前 + oneHourAgo: 1時間前 + xHoursAgo: 時間前 + oneDayAgo: 1日前 + xDaysAgo: 日前 secondsShort: 秒 - minutesAndSecondsShort: 秒 - hoursAndMinutesShort: 時間 分 - - xMinutes: 分 - + minutesAndSecondsShort: 秒 + hoursAndMinutesShort: 時間分 + xMinutes: 分 keys: tab: TAB control: CTRL @@ -129,34 +70,24 @@ global: escape: ESC shift: SHIFT space: SPACE - demoBanners: - # This is the "advertisement" shown in the main menu and other various places title: デモ版 - intro: >- - スタンドアローン版を手に入れ、すべての機能をアンロックしましょう! - + intro: スタンドアローン版を手に入れ、すべての機能をアンロックしましょう! mainMenu: play: プレイ - changelog: 更新履歴 - importSavegame: インポート - openSourceHint: このゲームはオープンソースです - discordLink: 公式Discord - helpTranslate: 翻訳に参加 - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - このゲームはお使いのブラウザでは速度が落ちることがあります。スタンドアローン版を入手するか、Chromeでプレイすることでこの問題は避けられます。 - - savegameLevel: レベル - savegameLevelUnknown: 不明なレベル - - continue: 続きから newGame: 新規ゲーム - madeBy: 制作者 + changelog: 更新履歴 subreddit: Reddit - + importSavegame: インポート + openSourceHint: このゲームはオープンソースです + discordLink: 公式Discordサーバー + helpTranslate: 翻訳を助けてください! + madeBy: によって作られました + browserWarning: このゲームはお使いのブラウザでは速度が落ちることがあります。スタンドアローン版を入手するか、Chromeでプレイすることでこの問題は避けられます。 + savegameLevel: レベル + savegameLevelUnknown: 不明なレベル + savegameUnnamed: 無名のデータ dialogs: buttons: ok: OK @@ -170,113 +101,90 @@ dialogs: viewUpdate: アップデートを見る showUpgrades: アップグレード表示 showKeybindings: キー設定表示 - importSavegameError: title: インポートエラー - text: >- - セーブデータのインポートに失敗しました: - + text: "セーブデータのインポートに失敗しました:" importSavegameSuccess: title: セーブデータのインポートに成功 - text: >- - セーブデータをインポートしました - + text: セーブデータをインポートしました。 gameLoadFailure: title: ゲームが壊れています - text: >- - セーブデータのロードに失敗しました: - + text: "セーブデータのロードに失敗しました:" confirmSavegameDelete: title: 削除確認 - text: >- - 本当に削除しますか? - + text: "本当に削除しますか?

レベル: ''

+ この操作は取り消しできません!" savegameDeletionError: title: 削除に失敗 - text: >- - セーブデータの削除に失敗しました: - + text: "セーブデータの削除に失敗しました:" restartRequired: title: 再起動が必要 - text: >- - 設定を反映するには再起動が必要です - + text: 設定を反映するには再起動が必要です editKeybinding: title: キー設定の変更 - desc: 割当てるキーかマウスボタンを押してください。ESCでキャンセルします。 - + desc: 割り当てるキーかマウスボタンを押してください。ESCでキャンセルします。 resetKeybindingsConfirmation: title: キー設定のリセット desc: すべてのキー設定を初期値に戻します。実行する前によく確認してください。 - keybindingsResetOk: title: キー設定のリセット desc: キー設定を初期値に設定しました! - featureRestriction: title: デモ版 desc: アクセスした要素 () はデモ版では利用できません。スタンドアローン版の入手をご検討ください! - oneSavegameLimit: title: セーブデータ制限 desc: デモ版ではひとつのセーブデータのみ保持できます。既存のデータを削除するか、スタンドアローン版の入手をご検討ください! - updateSummary: title: 新アップデート! - desc: >- - 前回からの変更点: - + desc: "前回からの変更点:" upgradesIntroduction: title: アップグレード解除 - desc: >- - すべての納品された形はアップグレードの解除のためにカウントされています。作った生産ラインを削除しないようにしてください! アップグレードタブは画面の右上から確認できます。 - + desc: すべての納品された形はアップグレードの解除のためにカウントされています。作った生産ラインを削除しないようにしてください! アップグレードタブは画面の右上から確認できます。 massDeleteConfirm: title: 削除確認 - desc: >- - 多数の建造物を削除しようとしています! ( 個の選択) 続行しますか? - + desc: 多数の建造物を削除しようとしています! ( 個の選択) 続行しますか? + massCutConfirm: + title: カット確認 + desc: 多数の建造物をカットしようとしています! ( 個の選択) 続行しますか? + massCutInsufficientConfirm: + title: カット確認 + desc: 設置コストが不足しています! 続行しますか? blueprintsNotUnlocked: title: 未解除 - desc: >- - レベル12をクリアしてブループリント機能を解除してください! - + desc: レベル12をクリアしてブループリント機能を解除してください! keybindingsIntroduction: title: 便利なキー設定 - desc: >- - このゲームには大規模な工場の構築をスムーズにするため、沢山のキー設定があります。 - 以下に数例を示します。詳細はキー設定を確認してください

- CTRL + ドラッグ: 削除範囲を指定
- SHIFT: 押し続けると1種の建造物を連続配置
- ALT: 設置されたベルトの方向を逆転させる
- + desc: "このゲームには大規模な工場の構築をスムーズにするため、沢山のキー設定があります。 + 以下に数例を示します。詳細はキー設定を確認してください

CTRL + ドラッグ: 削除範囲を指定
SHIFT: 押し続けると1種の建造物を連続配置
ALT: 設置されたベルトの方向を逆転させる
" createMarker: title: マーカーを設置 titleEdit: マーカーを編集 - desc: わかりやすい名前をつけてください。形を表す短いキーを含めることもできます。(ここから生成できます) - + desc: わかりやすい名前をつけてください。形を表す短いキーを含めることもできます。(ここから生成できます) + editSignal: + title: 信号を設定 + descItems: "プリセットを選択:" + descShortKey: もしくは形を表す短いキーを入力してください。 (ここから生成できます) markerDemoLimit: desc: デモ版ではマーカー設置は2つまでに制限されています。スタンドアローン版は無制限です! - - massCutConfirm: - title: カット確認 - desc: >- - 多数の建造物をカットしようとしています! ( 個の選択) 続行しますか? - - massCutInsufficientConfirm: - title: カット確認 - desc: >- - 設置コストが不足しています! 続行しますか? - exportScreenshotWarning: title: スクリーンショット出力 - desc: >- - スクリーンショット出力を実行します。この処理は工場の全体像があまりに大きいと、 - ゲームが遅くなったりクラッシュしてしまう可能性があります! - + desc: スクリーンショット出力を実行します。この処理は工場の全体像があまりに大きいと、 ゲームが遅くなったりクラッシュしてしまう可能性があります! + renameSavegame: + title: セーブデータの名前を変更 + desc: セーブデータの名前を変更することができます + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: マップ移動 selectBuildings: 範囲選択 @@ -296,19 +204,20 @@ ingame: copySelection: コピー clearSelection: 選択範囲をクリア pipette: ピペット - switchLayers: Switch layers - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + switchLayers: レイヤーを変更 + colors: + red: 赤 + green: 緑 + blue: 青 + yellow: 黄 + purple: マゼンタ + cyan: シアン + white: 白 + black: 黒 + uncolored: 無色 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: キーを押して変更 - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - ホットキー: - + hotkeyLabel: "ホットキー: " infoTexts: speed: スピード range: レンジ @@ -316,36 +225,21 @@ ingame: oneItemPerSecond: 1 アイテム / 秒 itemsPerSecond: アイテム / 秒 itemsPerSecondDouble: (x2) - tiles: タイル - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: レベル completed: 完了 unlockText: を解除! buttonNextLevel: 次のレベル - - # Notifications on the lower right notifications: newUpgrade: 新しいアップグレードが利用可能です! gameSaved: ゲームをセーブしました。 - - # The "Upgrades" window + freeplayLevelComplete: レベル をクリアしました! shop: title: アップグレード buttonUnlock: アップグレード - - # Gets replaced to e.g. "Tier IX" tier: 第 段階 - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: 最大レベル (スピード x) - - # The "Statistics" window statistics: title: 統計情報 dataSources: @@ -359,412 +253,549 @@ ingame: title: 納品済 description: 中央の建造物に納品された形の総数です。 noShapesProduced: まだ形が生産されていません。 - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / 分 - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / 秒 + minute: / 分 + hour: / 時間 settingsMenu: playtime: プレイ時間 - buildingsPlaced: 建造物 beltsPlaced: ベルト - - buttons: - continue: コンティニュー - settings: 設定 - menu: メニューに戻る - - # Bottom left tutorial hints tutorialHints: title: ヒントが必要ですか? showHint: ヒントを見る hideHint: 閉じる - - # When placing a blueprint blueprintPlacer: cost: コスト - - # Map markers waypoints: waypoints: マーカー hub: HUB - description: マーカーを左クリックでその場所にジャンプ、右クリックで削除します。

キーを押すことで現在地にマーカーを設置します。選択した位置で右クリックすることでもマーカー設置できます。 + description: マーカーを左クリックでその場所にジャンプ、右クリックで削除します。

+ キーを押すことで現在地にマーカーを設置します。選択した位置で右クリックすることでもマーカー設置できます。 creationSuccessNotification: マーカーを設置しました - - # Interactive tutorial + shapeViewer: + title: レイヤー + empty: 空 + copyKey: キーをコピー interactiveTutorial: title: チュートリアル hints: 1_1_extractor: 抽出機円の形 の上において抽出しましょう! - 1_2_conveyor: >- - 抽出機を コンベアベルト でHUBまで繋げましょう!

Tip: マウスのドラッグ でベルトを引けます。 - - 1_3_expand: >- - このゲームは放置系のゲームではありません! もっと早く要件を満たせるように、追加の抽出機とベルトを設置しましょう。

Tip: SHIFT キーを押し続けると抽出機を連続配置できます。Rキーで設置方向を回転できます。 - - colors: - red: 赤 - green: 緑 - blue: 青 - yellow: 黄 - purple: 紫 - cyan: シアン - white: 白 - uncolored: 無色 - black: Black - shapeViewer: - title: レイヤー - empty: 空 - copyKey: Copy Key - -# All shop upgrades + 1_2_conveyor: "抽出機を コンベアベルト でHUBまで繋げましょう!

Tip: + マウスのドラッグ でベルトを引けます。" + 1_3_expand: "このゲームは放置系のゲームではありません! + もっと早く要件を満たせるように、追加の抽出機とベルトを設置しましょう。

Tip: + SHIFT + キーを押し続けると抽出機を連続配置できます。Rキーで設置方向を回転できます。" + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." + connectedMiners: + one_miner: 1個の抽出機 + n_miners: 個の抽出機 + limited_items: に制限されます + watermark: + title: デモバージョン + desc: Steamバージョンの特典を確認するには、ここをクリックしてください! + get_on_steam: steamで購入 + standaloneAdvantages: + title: フルバージョンを購入 + no_thanks: いいえ、結構です + points: + levels: + title: 新しい12個のレベル + desc: 全部で26個のレベルになります! + buildings: + title: 新しい18個の設置物 + desc: あなたの工場を完全自動化しましょう! + savegames: + title: 無限個のセーブデータ + desc: あなたが望むだけデータを作成できます! + upgrades: + title: 20個のアップデートティア + desc: このデモバージョンでは5ティアのみです! + markers: + title: 無限個のマップマーカー + desc: これでもうあなたの工場を見失いません! + wires: + title: ワイヤ + desc: 新次元の体験を得られます! + darkmode: + title: ダークモード + desc: 目に優しい! + support: + title: 製作者をサポート + desc: 余暇に制作しています! shopUpgrades: belt: - name: ベルト、ディストリビュータ & トンネル + name: ベルト、ディストリビュータとトンネル description: スピード x → x miner: name: 抽出機 description: スピード x → x processors: - name: 切断、回転 & 積み重ね + name: 切断、回転と積み重ね description: スピード x → x painting: - name: 混合 & 着色 + name: 混合と着色 description: スピード x → x - -# Buildings and their name / description buildings: hub: deliver: 納品 toUnlock: 解除 levelShortcut: レベル - + endOfDemo: お試し終了 belt: default: - name: &belt コンベアベルト + name: コンベアベルト description: アイテムを輸送します。マウスドラッグで連続配置できます。 - - miner: # Internal name for the Extractor + miner: default: - name: &miner 抽出機 + name: 抽出機 description: 形や色の上に設置することで抽出できます。 - chainable: name: 連鎖抽出機 description: 形や色の上に設置することで抽出できます。連鎖設置可能です。 - - underground_belt: # Internal name for the Tunnel + underground_belt: default: - name: &underground_belt トンネル + name: トンネル description: 建造物や他のベルトの地下を通してベルトを配置できます。 - tier2: name: トンネル レベルII description: 建造物や他のベルトの地下を通してベルトを配置できます。 - - splitter: # Internal name for the Balancer + balancer: default: - name: &splitter 分配機 + name: 分配機/合流機 description: 多機能 - すべての入力をすべての出力に均等に分配します。 - - compact: - name: 合流機 (コンパクト) - description: 2本のベルトの内容を1本のベルトに合流します。 - - compact-inverse: - name: 合流機 (コンパクト) - description: 2本のベルトの内容を1本のベルトに合流します。 - + merger: + name: 合流機(コンパクト) + description: 2つの入力を1つの出力に合流させます。 + merger-inverse: + name: 合流機(コンパクト) + description: 2つの入力を1つの出力に合流させます。 + splitter: + name: 分配機(コンパクト) + description: 1つの入力を2つの出力に分配します。 + splitter-inverse: + name: 分配機(コンパクト) + description: 1つの入力を2つの出力に分配します。 cutter: default: - name: &cutter 切断機 + name: 切断機 description: 形を上下の直線で切断し、双方を出力します。もしひとつの出力しか使わない場合、他の出力を破棄しないと出力が詰まって停止することに注意してください! quad: name: 切断機 (四分割) description: 形を四分割します。もしひとつの出力しか使わない場合、他の出力を破棄しないと出力が詰まって停止することに注意してください! - rotater: default: - name: &rotater 回転機 + name: 回転機 description: 形を時計回り方向に90度回転します。 ccw: name: 回転機 (逆) description: 形を反時計回り方向に90度回転します。 - + rotate180: + name: 回転機 (180度) + description: 形を180度回転します。 stacker: default: - name: &stacker 積層機 + name: 積層機 description: 入力アイテムを積み重ねます。もしうまく統合できなかった場合は、右の入力アイテムを左の入力アイテムの上に重ねます。 - mixer: default: - name: &mixer 混合機 + name: 混合機 description: 2つの色を加算混合で混ぜ合わせます。 - painter: default: - name: &painter 着色機 - description: &painter_desc 左から入力された形の全体を、右から入力された色で着色します。 + name: 着色機 + description: 左から入力された形の全体を、上から入力された色で着色します。 + mirrored: + name: 着色機 + description: 左から入力された形の全体を、下から入力された色で着色します。 double: name: 着色機 (ダブル) description: 左から入力された形を、上から入力された色で着色します。 quad: name: 着色機 (四分割) description: 入力された形を四分割づつ別の色で塗り分けられます。 - mirrored: - name: *painter - description: *painter_desc - + 真らしい信号が流れているスロットのみがペイントされます! trash: default: - name: &trash ゴミ箱 + name: ゴミ箱 description: すべての辺からの入力を破棄します。永遠に。 - - storage: - name: 格納庫 - description: 余ったアイテムを指定の上限まで格納します。余剰の受け口としても使用可能です。 + storage: + default: + name: ストレージ + description: 所定の容量まで、アイテムを蓄えることができます。左側の出力が優先され、オーバーフローゲートとして利用できます。 wire: default: - name: Energy Wire - description: Allows you to transport energy. - advanced_processor: + name: ワイヤ + description: 形状、色、真偽値(1/0)の信号を運ぶことができます。異なる色のワイヤは互いに接続しません。 + second: + name: ワイヤ + description: 形状、色、真偽値(1/0)の信号を運ぶことができます。異なる色のワイヤは互いに接続しません。 + wire_tunnel: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For + name: 交差ワイヤ + description: 2本のワイヤを接続させることなく交差させることができます。 + constant_signal: default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: + name: 定値信号 + description: 常に同じ値を出力します。形状、色、真偽値(1/0)が使用できます。 + lever: default: - name: Wire Splitter - description: Splits a energy wire into two. - merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: スイッチ + description: ワイヤ上に真偽値(1/0)を出力できます。スイッチを押すことで1と0を切り替えることができ、 + それを利用してアイテムフィルタ等を制御できます。 + logic_gate: + default: + name: ANDゲート + description: 両方の入力が真らしいなら、真偽値"1"を出力します。(真らしいとは、形状、色、または真偽値"1"のことです) + not: + name: NOTゲート + description: 入力が真らしくないなら、真偽値"1"を出力します。(真らしいとは、形状、色、または真偽値"1"のことです) + xor: + name: XORゲート + description: 両方の入力のうち片方のみが真らしいなら、真偽値"1"を出力します。(真らしいとは、形状、色、または真偽値"1"のことです) + or: + name: ORゲート + description: 両方の入力のうち少なくとも片方が真らしいなら、真偽値"1"を出力します。(真らしいとは、形状、色、または真偽値"1"のことです) + transistor: + default: + name: トランジスタ + description: 横からの入力が真らしいなら、下からの入力を通過させます。(真らしいとは、形状、色、または真偽値"1"のことです) + mirrored: + name: トランジスタ + description: 横からの入力が真らしいなら、下からの入力を通過させます。(真らしいとは、形状、色、または真偽値"1"のことです) + filter: + default: + name: アイテムフィルタ + description: 入力された信号と一致するアイテムを上部に通過させ、残りを右側に通過させます。 真偽値(1/0)でも制御できます。 + display: + default: + name: ディスプレイ + description: 入力された信号をディスプレイに表示します。 形状、色、真偽値のいずれでも可能です。 + reader: + default: + name: ベルトリーダ + description: 平均スループットを計測できます。 アンロック後は、 最後に通過したアイテムの情報を出力します。 + analyzer: + default: + name: 形状解析機 + description: 形状の最下層の右上の形状を分析し、形状と色に分解します。 + comparator: + default: + name: 比較機 + description: 両方の信号が完全に一致している場合、真偽値"1"を出力します。 形状、色、真偽値を比較できます。 + virtual_processor: + default: + name: 仮想切断機 + description: 形状の信号を2つに切断できます。 + rotater: + name: 仮想回転機 + description: 形状の信号を時計回り、反時計回りに回転させます。 + unstacker: + name: 仮想分離機 + description: 形状の信号の最上層を右側に出力し、残りの層を左側に出力します。 + stacker: + name: 仮想積層機 + description: 左側の形状の信号の上に右側の形状の信号を合成します。 + painter: + name: 仮想着色機 + description: 下の形状の信号を右の色の信号で着色します。 + item_producer: + default: + name: なんでも抽出機 + description: サンドボックスモードでのみ使用可能で、ワイヤレイヤーで与えられた信号の形状を通常レイヤーに出力します。 storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: 形の切断 - desc: 切断機が利用可能になりました。これは入力された形を、向きを考慮せず上下の直線で半分に切断します。

利用しない側の出力に注意しましょう。破棄するなどをしない限り詰まって停止してしまいます - このためにゴミ箱も用意しました。入力アイテムをすべて破棄できます。 - + desc: 切断機が利用可能になりました。これは入力された形を、向きを考慮せず上下の直線で半分に切断します。

利用しない側の出力に注意しましょう。破棄するなどをしない限り詰まって停止してしまいます + - このためにゴミ箱も用意しました。入力アイテムをすべて破棄できます! reward_rotater: title: 回転 desc: 回転機が利用可能になりました。形を時計回り方向に90度回転させます。 - 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! - + desc: "着色機が利用可能になりました。(今まで形状でやってきた方法で)色を抽出し、 + 形状と合成することで着色します!

追伸: もし色覚特性をお持ちでしたら、 + 設定に色覚特性モードがあります!" reward_mixer: title: 色の混合 - desc: 混合機が利用可能になりました。 - この建造物は2つの色を加算混合で混ぜ合わせます。 - + desc: 混合機が利用可能になりました。 - + この建造物は2つの色を加算混合で混ぜ合わせます。 reward_stacker: title: 積層機 desc: 積層機で形を組み合わせ可能になりました。双方の入力を組み合わせ、もし連続した形になっていればそれらは融合してひとつになります! もしできなかった場合は、左の入力の上に右の入力が重なります。 - - reward_splitter: + reward_balancer: title: 分配機/合流機 - desc: 多機能な分配機/合流機が利用可能になりました。 - より大規模な工場を構築するため、複数のベルト間でアイテムを合流、分配できます!

- + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! reward_tunnel: title: トンネル desc: トンネルが利用可能になりました。 - 他のベルトや建造物の地下を通してベルトが配置可能です! - reward_rotater_ccw: title: 反時計回りの回転 - desc: 回転機のバリエーションが利用可能になりました。 - 反時計回りの回転ができるようになります! 回転機を選択し、'T'キーを押すことで方向の切り替えができます - + desc: 回転機のバリエーションが利用可能になりました。 - + 反時計回りの回転ができるようになります! 回転機を選択し、'T'キーを押すことで方向の切り替えができます reward_miner_chainable: title: 連鎖抽出機 - desc: 連鎖抽出機が利用可能になりました。他の抽出機に出力を渡すことができるので、資源の抽出がより効率的になります! - + desc: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" reward_underground_belt_tier_2: title: トンネル レベルII - desc: トンネルのバリエーションが利用可能になりました。 - 距離拡張版が追加され、以前のものと組み合わせて目的に応じて利用することができます! - - reward_splitter_compact: - title: 合流機 (コンパクト) - desc: >- - 合流機のコンパクト版が利用可能になりました。 - 2つの入力をひとつに合流できます! - + desc: トンネルのバリエーションが利用可能になりました。 - + 距離拡張版が追加され、以前のものと組み合わせて目的に応じて利用することができます! + reward_merger: + title: コンパクトな合流機 + desc: 合流機コンパクトバージョンが利用可能になりました! - + 2つの入力を1つの出力に合流させます! + reward_splitter: + title: コンパクトな分配機 + desc: 分配機コンパクトバージョンが利用可能になりました! - + 1つの入力を2つの出力に分配します! + reward_belt_reader: + title: ベルトリーダ + desc: ベルトリーダが利用可能になりました!ベルトのスループットを計測できます。

ワイヤーのロックが解除されれば、より便利になります! reward_cutter_quad: title: 四分割 - desc: 切断機のバリエーションが利用可能になりました。 - 上下の二分割ではなく、四分割に切断できます! - + desc: 切断機のバリエーションが利用可能になりました。 - + 上下の二分割ではなく、四分割に切断できます! reward_painter_double: title: 着色機 (ダブル) - desc: 着色機のバリエーションが利用可能になりました。 - 通常の着色機と同様に機能しますが、ひとつの色の消費で一度に2つの形を着色処理できます! - - reward_painter_quad: - title: 四分割着色 - desc: 着色機のバリエーションが利用可能になりました。 - 形のすべてのパーツを別の色で塗り分けることができます! - + desc: 着色機のバリエーションが利用可能になりました。 - + 通常の着色機と同様に機能しますが、ひとつの色の消費で一度に2つの形を着色処理できます! reward_storage: title: 余剰の貯蓄 - desc: ゴミ箱のバリエーションが利用可能になりました。 - 容量上限までアイテムを格納することができます! - - reward_freeplay: - title: フリープレイ - desc: やりましたね! フリープレイモードが利用可能になりました。 - これからは形はランダムに生成されます! (ご心配なく。スタンドアローン版はさらなる追加コンテンツが計画されています) - + desc: ゴミ箱のバリエーションが利用可能になりました。 - 容量上限までアイテムを格納することができます!

+ 左側の出力を優先するため、オーバーフローゲートとしても使用できます! reward_blueprints: title: ブループリント desc: 工場の建造物のコピー&ペーストが利用可能になりました! 範囲選択(CTRLキーを押したままマウスドラッグ)した状態で、'C'キーを押すことでコピーができます。

ペーストはタダではありません。ブループリントの形を生産することで可能になります!(たった今納品したものです) - - # Special reward, which is shown when there is no reward actually + reward_rotater_180: + title: 180度の回転 + desc: 回転機のバリエーションが利用可能になりました! 180度の回転ができるようになります!(サプライズ! :D) + reward_wires_painter_and_levers: + title: ワイヤ&着色機(四分割) + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: アイテムフィルタ + desc: アイテムフィルタが利用可能になりました! ワイヤレイヤの信号と一致するかどうかに応じて、 + アイテムを上部または右側の出力に分離します。

真偽値(0/1)信号を利用することで + どんなアイテムでも通過させるか、または通過させないかを選ぶこともできます。 + reward_display: + title: ディスプレイ + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: 定数信号 + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 or 0). + reward_logic_gates: + title: 論理ゲート + desc: 論理ゲートが利用可能になりました! 興奮するほどでは ありませんが、これらは非常に優秀です!

+ AND, OR, XOR and + NOTを計算できます!

ボーナスとしてトランジスタも追加しました! + reward_virtual_processing: + title: 仮想処理 + desc: 形状処理をシミュレートできる新しい部品を沢山追加しました!

+ ワイヤレイヤで切断、回転、積層をシミュレートできるようになりました。 + これからゲームを続けるにあたり、3つの方法があります:

- + 完全自動化された機械を構築し、HUBが要求する形状を作成する(試してみることをオススメします!)。

+ - ワイヤでイカしたものを作る。

- 今までのように工場を建設する。

いずれにしても、楽しんでください! no_reward: title: 次のレベル - desc: >- - このレベルには報酬はありません。次にはあるでしょう!

PS: すでに作った生産ラインは削除しないようにしましょう。 - 生産された形はすべて、後にアップグレードの解除のために必要になります! - + desc: "このレベルには報酬はありません。次にはあるでしょう!

補足: すでに作った生産ラインは削除しないようにしましょう。 - + 生産された形はすべて、後にアップグレードの解除のために必要になりま\ + す!" no_reward_freeplay: title: 次のレベル - desc: >- - おめでとうございます! スタンドアローン版ではさらなる追加要素が計画されています! - + desc: おめでとうございます! + reward_freeplay: + title: フリープレイ + desc: やりましたね! フリープレイモードが利用可能になりました。 - + これからは納品すべき形はランダムに生成されます!

+ 今後、ハブにはスループットが必要になるため、要求する形状を自動的に納品するマシンを構築することを強くお勧めします!

+ ハブは要求する形状をワイヤー層に出力するので、それを分析し自動的に調整する工場を作成するだけです。 + reward_demo_end: + title: お試し終了 + desc: デモ版の最後に到達しました! settings: title: 設定 categories: - game: ゲーム - app: アプリケーション - + general: 一般設定 + userInterface: ユーザーインターフェイス + advanced: 高度な設定 + performance: パフォーマンス versionBadges: - dev: Development + dev: 開発 staging: Staging prod: Production - buildDate: Built - + buildDate: にビルド + rangeSliderPercentage: % labels: uiScale: title: 画面表示サイズ - description: >- - ユーザーインターフェイスのサイズを変更します。解像度をベースに調整されますが、この設定でそれを変更できます。 + description: ユーザーインターフェイスのサイズを変更します。解像度をベースに調整されますが、この設定でそれを変更できます。 scales: super_small: 極小 small: 小 regular: 普通 large: 大 huge: 極大 - + autosaveInterval: + title: オートセーブ間隔 + description: ゲームが自動的にセーブされる頻度を設定します。無効化することも可能です。 + intervals: + one_minute: 1分 + two_minutes: 2分 + five_minutes: 5分 + ten_minutes: 10分 + twenty_minutes: 20分 + disabled: 無効 scrollWheelSensitivity: title: ズーム感度 - description: >- - マウスやトラックパッドでのズーム感度を変更します。 + description: マウスやトラックパッドでのズーム感度を変更します。 sensitivity: super_slow: 極遅 slow: 遅 regular: 普通 fast: 速 super_fast: 超速 - - language: - title: 言語 - description: >- - 言語を変更します。すべての翻訳はユーザーからの協力で成り立っており、まだ完全には完了していない可能性があります! - - fullscreen: - title: フルスクリーン - description: >- - フルスクリーンでのプレイが推奨です。スタンドアローン版のみ変更可能です。 - - soundsMuted: - title: 効果音ミュート - description: >- - 有効に設定するとすべての効果音をミュートします。 - - musicMuted: - title: BGMミュート - description: >- - 有効に設定するとすべてのBGMをミュートします。 - - theme: - title: ゲームテーマ - description: >- - ゲームテーマを選択します。 (ライト / ダーク). - - themes: - dark: ダーク - light: ライト - - refreshRate: - title: シミュレーション対象 - description: >- - もし144hzのモニターを利用しているなら、この設定でリフレッシュレートを変更することで、ゲームが高リフレッシュレートを正しくシミュレーションします。利用しているPCが非力な場合、この設定により実効FPSが遅くなる可能性があります。 - - alwaysMultiplace: - title: 連続配置 - description: >- - この設定を有効にすると、建造物を選択後に意図的にキャンセルするまで選択された状態を維持します。これはSHIFTキーを押し続けている状態と同等です。 - - offerHints: - title: ヒントとチュートリアル - description: >- - ゲーム中、ヒントとチュートリアルを表示します。レベルごとに不要なUI要素も非表示になり、ゲームに集中しやすくなります。 - movementSpeed: title: 移動速度 description: キーボードを使用した際の画面の移動速度を変更します。 speeds: - super_slow: 極遅 - slow: 遅 + super_slow: 激遅 + slow: 遅い regular: 普通 - fast: 速 + fast: 速い super_fast: 超速 - extremely_fast: 超々速 + extremely_fast: ちょっぱや + language: + title: 言語 + description: 言語を変更します。すべての翻訳はユーザーからの協力で成り立っており、まだ完全には完了していない可能性があります! + enableColorBlindHelper: + title: 色覚モード + description: 色覚特性を持っていてもゲームがプレイできるようにするための各種ツールを有効化します。 + fullscreen: + title: フルスクリーン + description: フルスクリーンでのプレイが推奨です。スタンドアローン版のみ変更可能です。 + soundsMuted: + title: 効果音ミュート + description: 有効に設定するとすべての効果音をミュートします。 + musicMuted: + title: BGMミュート + description: 有効に設定するとすべてのBGMをミュートします。 + soundVolume: + title: 音量(SE) + description: 効果音の音量を設定してください。 + musicVolume: + title: 音量(BGM) + description: 音楽の音量を設定してください。 + theme: + title: ゲームテーマ + description: ゲームテーマを選択します。 (ライト / ダーク). + themes: + dark: ダーク + light: ライト + refreshRate: + title: シミュレーション対象 + description: もし144hzのモニターを利用しているなら、この設定でリフレッシュレートを変更することで、ゲームが高リフレッシュレートを正しくシミュレーションします。利用しているPCが非力な場合、この設定により実効FPSが遅くなる可能性があります。 + alwaysMultiplace: + title: 連続配置 + description: この設定を有効にすると、建造物を選択後に意図的にキャンセルするまで選択された状態を維持します。これはSHIFTキーを押し続けている状態と同等です。 + offerHints: + title: ヒントとチュートリアル + description: ゲーム中、ヒントとチュートリアルを表示します。レベルごとに不要なUI要素も非表示になり、ゲームに集中しやすくなります。 enableTunnelSmartplace: title: スマートトンネル - description: >- - 有効にすると、トンネルを設置した際に不要なベルトを自動的に除去します。 + description: 有効にすると、トンネルを設置した際に不要なベルトを自動的に除去します。 また、トンネルをドラッグできるようになり、不要なトンネルは除去されます。 vignette: title: ビネット - description: >- - 画面の隅を暗くして文字を読みやすくするビネットを有効化します。 - - autosaveInterval: - title: オートセーブ間隔 - description: >- - ゲームが自動的にセーブされる頻度を設定します。無効化することも可能です。 - intervals: - one_minute: 1 分 - two_minutes: 2 分 - five_minutes: 5 分 - ten_minutes: 10 分 - twenty_minutes: 20 分 - disabled: 無効 + description: 画面の隅を暗くして文字を読みやすくするビネットを有効化します。 + rotationByBuilding: + title: 回転の記憶(部品別) + description: それぞれの部品ごとの回転を記憶させます。頻繁に設置物を変更する場合、より快適に建設が行なえます。 compactBuildingInfo: title: コンパクトな建造物情報 - description: >- - レートのみを表示することで、建造物の情報ボックスを短くします。選択しない場合は、説明文と画像も表示されます。 + description: レートのみを表示することで、建造物の情報ボックスを短くします。選択しない場合は、説明文と画像も表示されます。 disableCutDeleteWarnings: title: カット/削除の警告を無効化 - description: >- - 100個以上のエンティティをカット/削除する際に表示される警告ダイアログを無効にします。 - - enableColorBlindHelper: - title: 色覚モード - description: 色覚異常を持っていてもゲームがプレイできるようにするための各種ツールを有効化します。 - 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. - + description: 100個以上のエンティティをカット/削除する際に表示される警告ダイアログを無効にします。 + lowQualityMapResources: + title: リソース表示の簡易化 + description: ズームインしたときのリソース表示を簡素化して、パフォーマンスを向上させます。 外見もすっきりしますので、ぜひお試しください! + disableTileGrid: + title: グリッドの無効化 + description: 配置用のグリッドを無効にして、パフォーマンスを向上させます。 これにより、ゲームの見た目もすっきりします。 + clearCursorOnDeleteWhilePlacing: + title: 右クリックで配置をキャンセル + description: デフォルトで有効です。建物を設置しているときに右クリックすると、選択中の建物がキャンセルされます。 + 無効にすると、建物の設置中に右クリックで建物を削除できます。 + lowQualityTextures: + title: 低品質のテクスチャ(視認性低下) + description: 低品質のテクスチャを使用してパフォーマンスを向上させます。 ゲームの視認性が非常に低下します! + displayChunkBorders: + title: チャンクの境界線を表示する + description: このゲームでは16x16タイルのチャンクで構成されています。 有効にすると、チャンクの境界線が表示されます。 + pickMinerOnPatch: + title: 資源で抽出機を選択 + description: デフォルトで有効です。資源の上でスポイトを使用すると、抽出機を選択します。 + simplifiedBelts: + title: ベルトを単純化(視認性低下) + description: ベルトにカーソルを合わせているとき以外、ベルトで運ばれているアイテムを描画しません。 + パフォーマンスを向上させますが、パフォーマンスが極端に必要な場合以外でこの設定で遊ぶことは推奨しません。 + enableMousePan: + title: マウスで画面を移動 + description: 画面の端にカーソルを合わせることで移動できます。移動速度を設定することで、速度を変更できます。 + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). keybindings: title: キー設定 - hint: >- - Tip: CTRL, SHIFT, ALTを利用するようにしてください。これらはそれぞれ建造物配置の際の機能があります。 - + hint: "Tip: CTRL, SHIFT, ALTを利用するようにしてください。これらはそれぞれ建造物配置の際の機能があります。" resetKeybindings: キー設定をリセット - categoryLabels: general: アプリケーション ingame: ゲーム @@ -773,7 +804,6 @@ keybindings: massSelect: 複数選択 buildings: 建造物ショートカット placementModifiers: 配置時バリエーション - mappings: confirm: 確認 back: 戻る @@ -781,71 +811,74 @@ keybindings: mapMoveRight: 右移動 mapMoveDown: 下移動 mapMoveLeft: 左移動 + mapMoveFaster: より速く移動 centerMap: マップ中央移動 - mapZoomIn: ズームイン mapZoomOut: ズームアウト createMarker: マーカー設置 - menuOpenShop: アップグレード menuOpenStats: 統計情報 menuClose: メニューを閉じる - toggleHud: HUD切り替え toggleFPSInfo: FPS、デバッグ情報表示切り替え - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + switchLayers: レイヤを変更 + exportScreenshot: 工場の全体像を画像出力 + belt: コンベアベルト + balancer: 分配機/合流機 + underground_belt: トンネル + miner: 抽出機 + cutter: 切断機 + rotater: 回転機 + stacker: 積層機 + mixer: 混合機 + painter: 着色機 + trash: ゴミ箱 + storage: ストレージ + wire: ワイヤ + constant_signal: 定値信号 + logic_gate: Logic Gate + lever: スイッチ + filter: アイテムフィルタ + wire_tunnel: 交差ワイヤ + display: ディスプレイ + reader: ベルトリーダ + virtual_processor: 仮想切断機 + transistor: トランジスタ + analyzer: 形状解析機 + comparator: 比較機 + item_producer: なんでも抽出機(サンドボックス) + pipette: スポイト rotateWhilePlacing: 回転 - rotateInverseModifier: >- - Modifier: 逆時計回りにする + rotateInverseModifier: "Modifier: 逆時計回りにする" cycleBuildingVariants: バリエーション変更 confirmMassDelete: 複数選択削除の確認 + pasteLastBlueprint: 直前のブループリントをペーストする cycleBuildings: 建造物の選択 - + lockBeltDirection: ベルトプランナーを有効化 + switchDirectionLockSide: "プランナー: 通る側を切り替え" + copyWireValue: "ワイヤ: カーソルに合っている形状信号をキーとしてコピー" massSelectStart: マウスドラッグで開始 massSelectSelectMultiple: 複数範囲選択 massSelectCopy: 範囲コピー - + massSelectCut: 範囲カット placementDisableAutoOrientation: 自動向き合わせ無効 placeMultiple: 配置モードの維持 placeInverse: ベルトの自動向き合わせを逆転 - pasteLastBlueprint: 直前のブループリントをペーストする - massSelectCut: 範囲カット - exportScreenshot: 工場の全体像を画像出力 - mapMoveFaster: より速く移動 - lockBeltDirection: ベルトプランナーを有効化 - switchDirectionLockSide: "プランナー: 通る側を切り替え" - pipette: ピペット - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire - about: title: このゲームについて body: >- - このゲームはオープンソースであり、Tobias Springer (私)によって開発されています。

+ このゲームはオープンソースであり、Tobias Springer (私)によって開発されています。

開発に参加したい場合は以下をチェックしてみてください。shapez.io on github.

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

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

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

最後に、私の最高の友人Niklasに大きな感謝を。 - 彼とのFactorioのゲーム体験がなければ、このゲームは存在しませんでした。 - changelog: title: 更新履歴 - demo: features: restoringGames: セーブデータのリストア @@ -853,5 +886,61 @@ demo: oneGameLimit: セーブデータの1個制限 customizeKeybindings: キー設定のカスタマイズ exportingBase: 工場の全体像の画像出力 - settingNotAvailable: デモ版では利用できません。 +tips: + - ハブは現在指定されている形状だけではなく、あらゆる種類の入力を受け付けることができます。 + - あなたの工場が拡張可能か確認してください - あとで報われるでしょう! + - ハブのすぐ近くに建設しないでください。ぐちゃぐちゃになりますよ。 + - 積層が上手く行かない場合は、入力を入れ替えてみてください。 + - Rを押すと、ベルトプランナーの経由方向を切り替えることができます。 + - CTRLを押したままドラッグすると、向きを保ったままベルトを設置できます。 + - アップグレードが同じティアなら、お互いの比率は同じです。 + - 直列処理は、並列処理より効率的です。 + - 後半になると、より多くの建物のバリエーションを解除できます。 + - Tを押すと、建物のバリエーションを切り替えることができます。 + - 対称性が重要です! + - ティアの違うトンネル同士は、同じラインに重ねることができます。 + - コンパクトに工場を作ってみてください - あとで報われるでしょう! + - 着色機には鏡写しのバリエーションがあり、Tで選択できます。 + - 適切な比率で建設することで、効率が最大化できます。 + - 最大レベルでは、1つのベルトは5つの抽出機で満たすことができます。 + - トンネルを忘れないでください。 + - 最大限の効率を得るためには、アイテムを均等に分割する必要はありません。 + - SHIFTを押したままベルトを設置するとベルトプランナーが有効になり、 + - 切断機は向きを考慮せず、常に垂直に切断します。 + - 白を作るためには、3色全てを混ぜます。 + - ストレージは優先出力を優先して出力します。 + - 増築可能なデザインを作るために時間を使ってください - それには価値があります! + - SHIFTを使用すると複数の建物を配置できます。 + - ALTを押しながらベルトを設置すると、逆向きに設置できます。 + - 効率が重要です! + - ハブから遠くに離れるほど、形状資源はより複雑な形になります。 + - 機械の速度には上限があるので、最大効率を得るためには入力を分割します。 + - 効率を最大化するために分配機/合流機を使用できます。 + - 構成が重要です。ベルトを交差させすぎないようにしてください。 + - 事前設計が重要です。さもないとぐちゃぐちゃになりますよ! + - 旧い工場を撤去しないでください!アップグレードを行うために、それらが必要になります。 + - 助けなしでレベル20をクリアしてみてください! + - 複雑にしないでください。単純に保つことができれば、成功することができるでしょう。 + - ゲームの後半で工場を再利用する必要があるかもしれません。 + - 積層機を使用することなく、必要な形状資源を発見することができるかもしれません。 + - 完全な風車の形は資源としては生成されません。 + - 最大の効率を得るためには、切断する前に着色をしてください。 + - モジュールとは、知覚こそが空間を生むものである。これは、人間である限り。 + - 工場の設計図を蓄えておいてください。それらを再利用することで、新たな工場が作成できます。 + - 混合機をよく見ると、色の混ぜ方が解ります。 + - CTRL + クリックで範囲選択ができます。 + - ハブに近すぎる設計物を作ると、のちの設計の邪魔になる可能性があります。 + - アップグレードリストの各形状の横にあるピンのアイコンは、それを画面左に固定します。 + - 原色全てを混ぜ合わせると白になります! + - マップは無限の広さがあります。臆せずに拡張してください。 + - Factorioもプレイしてみてください!私のお気に入りのゲームです。 + - 切断機(四分割)は右上から時計回りに切断します! + - メインメニューからセーブデータを保存できます! + - このゲームには便利なキーバインドがたくさんあります!設定ページを見てみてください。 + - このゲームにはたくさんの設定があります!是非チェックしてみてください! + - ハブを示すマーカーには、その方向を示す小さなコンパスがあります。 + - ベルトをクリアするには、範囲選択して同じ場所に貼り付けをします。 + - F4を押すことで、FPSとTickレートを表示することができます。 + - F4を2回押すと、マウスとカメラの座標を表示することができます。 + - 左のピン留めされた図形をクリックして、固定を解除できます。 diff --git a/translations/base-kor.yaml b/translations/base-kor.yaml index 1f256dc7..34a14fbd 100644 --- a/translations/base-kor.yaml +++ b/translations/base-kor.yaml @@ -1,111 +1,57 @@ -# -# 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는 무한한 공간에서 점점 더 복잡한 도형의 생산과 조합을 자동화하는 공장들을 짓는 게임입니다. + shortText: shapez.io는 무한한 공간에서 점점 더 복잡한 도형의 생산과 조합을 자동화하는 공장을 짓는 게임입니다. + discordLinkShort: 공식 Discord + intro: >- + 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: - # - 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 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]! - - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! + Steam에서 게임을 구매하여 정식 버전의 콘텐츠를 사용하실 수 있지만, 먼저 Shapez.io의 체험판 버전을 플레이해보시고 구매를 고려하셔도 됩니다! + title_advantages: 정식 버전의 장점 + advantages: + - 새로운 12 레벨의 추가로 총 26레벨까지 + - 완벽한 자동화를 위한 새로운 18개의 건물! + - 20 티어 업그레이드로 오랫동안 즐겨보세요! + - 전선 업데이트로 완전히 새로운 차원을 접해보세요! + - 다크 모드! + - 무한한 세이브 파일 + - 무한한 마커 + - 저를 지원해주세요! ❤️ + title_future: 계획된 콘텐츠 + planned: + - 청사진 라이브러리 + - Steam 도전과제 + - 퍼즐 모드 + - 미니맵 + - 모드 + - 샌드박스 모드 + - ... 그리고 더 다양한 것까지! + title_open_source: 이 게임은 오픈 소스입니다! + title_links: 링크 + links: + discord: 공식 Discord + roadmap: 로드맵 + subreddit: Subreddit + source_code: 소스 코드 (GitHub) + translate: 번역에 도움주세요 + text_open_source: >- + 누구나 번역에 기여하실 수 있으며, 저는 커뮤니티에서 적극적으로 참여하여 모든 제안을 검토하고 가능한 모든 피드백도 고려하고자 + 합니다. + 모든 로드맵을 보시려면 저의 trello 보드를 참고해주세요. global: - loading: 로딩중 - error: 에러 - - # How big numbers are rendered, e.g. "10,000" + loading: 불러오는 중 + error: 오류 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. + decimalSeparator: . suffix: thousands: k millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: 무한 - time: - # Used for formatting past time dates oneSecondAgo: 1초 전 xSecondsAgo: 초 전 oneMinuteAgo: 1분 전 @@ -114,14 +60,10 @@ global: xHoursAgo: 시간 전 oneDayAgo: 1일 전 xDaysAgo: 일 전 - - # Short formats for times, e.g. '5h 23m' secondsShort: 초 minutesAndSecondsShort: 초 hoursAndMinutesShort: 시간 분 - xMinutes: 분 - keys: tab: TAB control: CTRL @@ -129,33 +71,25 @@ global: escape: ESC shift: SHIFT space: SPACE - demoBanners: - # This is the "advertisement" shown in the main menu and other various places - title: 무료 버전 - intro: >- - 유료 버전을 구매해서 모든 컨탠츠를 사용해 보세요! - + title: 체험판 버전 + intro: 정식 버전을 구매해서 모든 콘텐츠를 사용해 보세요! mainMenu: play: 시작 changelog: 버전 기록 - importSavegame: 불러오기 + importSavegame: 가져오기 openSourceHint: 이 게임은 오픈 소스입니다! discordLink: 공식 디스코드 서버 helpTranslate: 번역을 도와주세요! - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - 이 게임은 당신의 브라우저에서 느리게 작동하는 것으로 알려져 있습니다. 더 좋은 성능을 위해 유료 버전을 구매하거나 크롬을 다운받으세요. + browserWarning: 이 게임은 현재 브라우저에서 느리게 작동하는 것으로 알려져 있습니다! 더 좋은 성능을 위해 정식 버전을 구매하거나 + Google Chrome 브라우저를 다운로드하세요. savegameLevel: 레벨 - savegameLevelUnknown: 레벨 모름 - - + savegameLevelUnknown: 미확인 레벨 continue: 계속하기 - newGame: 새 게임 + newGame: 새로하기 madeBy: 제작 subreddit: Reddit - + savegameUnnamed: 이름 없음 dialogs: buttons: ok: 확인 @@ -169,258 +103,256 @@ dialogs: viewUpdate: 업데이트 보기 showUpgrades: 업그레이드 보기 showKeybindings: 조작법 보기 - importSavegameError: - title: 불러오기 오류 - text: >- - 저장 파일을 불러오지 못했습니다: - + title: 가져오기 오류 + text: "세이브 파일을 가져오지 못했습니다:" importSavegameSuccess: - title: 저장 파일 불러오기 성공 - text: >- - 저장 파일이 성공적으로 불러와졌습니다. - + title: 세이브 파일 가져오기 성공 + text: 세이브 파일을 성공적으로 불러왔습니다. gameLoadFailure: - title: 저장 파일 에러 - text: >- - 저장 파일을 불러오지 못했습니다: - + title: 세이브 파일 에러 + text: "세이브 파일을 불러오지 못했습니다:" confirmSavegameDelete: title: 삭제 확인 - text: >- - 이 게임 파일을 정말로 삭제하겠습니까? - + text: 이 세이브 파일을 정말로 삭제하시겠습니까?

'' + 레벨

이 작업은 되돌릴 수 없습니다! savegameDeletionError: title: 삭제 실패 - text: >- - 저장 파일을 삭제하지 못했습니다. - + text: 세이브 파일을 삭제하지 못했습니다. restartRequired: - title: 다시 시작 필요 - text: >- - 설정을 적용하려면 게임을 다시 시작해야 됩니다. - + title: 게임 재시작 필요 + text: 설정을 적용하려면 게임을 재시작해야 합니다. editKeybinding: - title: 키바인딩 바꾸기 + title: 조작법 바꾸기 desc: 당신이 원하는 키나 마우스 버튼을 눌러서 바꾸거나 ESC를 눌러 취소하세요. - resetKeybindingsConfirmation: - title: 키바인딩 제설정 - desc: 이것은 모든 키바인딩을 기본값으로 초기화합니다. - + title: 조작법 초기화 + desc: 설정된 모든 조작법이 기본값으로 초기화됩니다. 초기화 전에 확인해 주세요. keybindingsResetOk: - title: 키바인딩 제설정 완료 - desc: 모든 키바인딩이 기본값으로 재설정 되었습니다! - + title: 조작법 초기화 완료 + desc: 모든 조작법이 기본값으로 초기화 되었습니다! featureRestriction: - title: 데모 버전 - desc: 데모 버전에는 없는 컨탠츠()로 시도했습니다. 유료 버전을 구입해서 모든 컨텐츠를 사용해보세요! - + title: 체험판 버전 + desc: 체험판 버전에는 없는 콘텐츠 ()로 시도했습니다. 정식 버전을 구입해서 모든 콘텐츠를 사용해보세요! oneSavegameLimit: - title: 저장파일 개수 제한 - desc: 데모 버전에서는 저장 파일을 한 번에 한 개만 사용할 수 있습니다. 이미 있는 저장 파일을 지우거나 유료 버전을 구입 해주새요. - + title: 세이브 파일 개수 제한 + desc: 체험판 버전에서는 세이브 파일을 한 번에 한 개만 사용할 수 있습니다. 이미 있는 세이브 파일을 지우거나 정식 버전을 구입 해주새요. updateSummary: - title: 신규 버전! - desc: >- - 지난번 플레이 이후 변경사항은 다음과 같습니다. - + title: 새로운 업데이트! + desc: 지난번 플레이 이후 변경 사항은 다음과 같습니다. upgradesIntroduction: title: 업그레이드 하기 - desc: >- - 여러분이 만든 모든 도형은 업그레이드에 사용 될 수 있습니다! - 만들어 놓은 공장을 허물지 마세요! + desc: 기존의 공장을 허물지 마세요! 여러분이 그동안 만들어 수집한 모든 도형은 업그레이드에 사용됩니다. 업그레이드 버튼은 화면의 오른쪽 위에 있습니다. - massDeleteConfirm: title: 삭제 확인 - desc: >- - 당신은 많은 건물을 삭제하려고 하고있습니다! (정확히는 개) 삭제하시겠습니까? - + desc: 굉장히 많은 수 (정확히는 개)의 건물을 삭제하려 합니다! 이 작업을 수행하시겠습니까? massCutConfirm: title: 자르기 확인 - desc: >- - 당신은 많은 건물을 자르려고 하고있습니다! (정확히는 개) 자르시겠습니까? - + desc: 굉장히 많은 수 (정확히는 개)의 건물을 자르려고 합니다! 이 작업을 수행하시겠습니까? blueprintsNotUnlocked: title: 아직 사용 불가 - desc: >- - 복사 기능은 아직 열리지 않았습니다! 레벨을 올려서 잠금을 해제하세요. - + desc: 12 레벨부터 청사진 기능이 해금됩니다! keybindingsIntroduction: - title: 유용한 키바인딩 - desc: >- - 큰 공장을 지을 때 유용한 키바인딩이 많습니다! - 아래를 확인하세요.나머지 키바인딩도 확인해보세요!!

- CTRL + Drag: 영역을 선택해서 복사/삭제하세요.
- SHIFT: 한꺼번에 여러 개의 건물을 배치하세요.
- ALT: 설치된 컨베이어 벨트의 방향을 바꾸세요.
- + title: 유용한 조작법 + desc: "이 게임에는 거대한 공장을 수월하게 세우기 위한 많은 조작법이 있습니다. 아래는 그 대표적인 것이며, 자세한 조작법은 + 조작법 설정을 참고해주세요!

CTRL + 드래그: 영역을 선택합니다.
SHIFT: 누르는 동안 같은 건물을 여러개 배치할 수 있습니다.
+ ALT: 배치된 벨트의 방향을 반전시킵니다.
" createMarker: title: 새로운 마커 - desc: 이 장소에 이름을 지어주세요, 당신은 원하는 모양으로 단축키를 생성할 수 있습니다. (여기에서 만들 수 있습니다.) - titleEdit: Edit Marker - + titleEdit: 마커 변경 + desc: 의미있는 이름을 정해주거나 단축키를 통해 도형을 직접 삽입할 수도 있습니다. + (여기에서 만드실 수 있습니다). markerDemoLimit: - desc: 데모 버전에서는 마커를 2개 까지만 놓을 수 있습니다. 유료 버전을 구입하면 마커를 무제한으로 놓을 수 있습니다! - + desc: 체험판 버전에서는 마커를 2개 까지만 배치할 수 있습니다. 정식 버전을 구입하면 마커를 무제한으로 배치할 수 있습니다! exportScreenshotWarning: title: 스크린샷 내보내기 - desc: >- - 당신은 당신의 공장을 스크린샷으로 내보내려 하고있습니다. 공장이 너무 큰 경우에는 - 시간이 오래 걸리거나 게임이 꺼질 수도 있음을 알려드립니다! - + desc: 당신의 공장을 스크린샷으로 내보내려 합니다. 매우 거대한 크기의 공장이라면 그 처리 시간이 상당히 오래 걸릴 것이며, 최악의 경우 + 게임이 중단될 수 있습니다! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? - + title: 자르기 확인 + desc: 이 영역에는 붙여넣기를 할 수 없습니다! 정말 자르시겠습니까? + editSignal: + title: 신호 설정 + descItems: "미리 정의된 아이템을 선택합니다:" + descShortKey: ... 또는 도형 단축키를 사용합니다 (여기에서 만드실 수 있습니다). + renameSavegame: + title: 세이브 파일 이름 설정 + desc: 여기에서 세이브 파일의 이름을 바꿀 수 있습니다. + tutorialVideoAvailable: + title: 활성화된 튜토리얼 + desc: 현재 레벨에서 사용할 수 있는 튜토리얼 비디오가 있습니다! 보시겠습니까? + tutorialVideoAvailableForeignLanguage: + title: 활성화된 튜토리얼 + desc: 현재 레벨에서 사용할 수 있는 튜토리얼 비디오가 있습니다! 허나 영어로만 + 제공될 것입니다. 보시겠습니까? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: - moveMap: 움직이기 + moveMap: 이동 selectBuildings: 영역 선택 - stopPlacement: 건물 놓기 중지 + stopPlacement: 배치 중단 rotateBuilding: 건물 회전 - placeMultiple: 여러 개 놓기 + placeMultiple: 건물 여러번 배치 reverseOrientation: 방향 뒤집기 disableAutoOrientation: 자동 회전 끄기 - toggleHud: UI 끄기/키기 - placeBuilding: 건물 놓기 - createMarker: 마커 놓기 + toggleHud: HUD 토글 + placeBuilding: 건물 배치 + createMarker: 마커 배치 delete: 삭제 pasteLastBlueprint: 마지막 청사진 붙여넣기 - lockBeltDirection: 벨트 플래너 활성화하기 - plannerSwitchSide: 벨트 플래너 방향바꾸기 - cutSelection: 선택된 부분 자르기 - copySelection: 선택된 부분 복사하기 - clearSelection: 선택된 부분 지우기 - pipette: 스포이드 - switchLayers: Switch layers - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + lockBeltDirection: 벨트 계획기 활성화 + plannerSwitchSide: 벨트 계획기 방향 전환 + cutSelection: 자르기 + copySelection: 복사하기 + clearSelection: 지우기 + pipette: 피펫 + switchLayers: 레이어 전환 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: 를 눌러 변형된 버전 선택 - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - + cycleBuildingVariants: 키를 눌러 변형 전환 + hotkeyLabel: "단축키: " infoTexts: speed: 속도 range: 최대 거리 - storage: 저장공간 + storage: 용량 oneItemPerSecond: 초당 1개 itemsPerSecond: 초당 개 itemsPerSecondDouble: (x2) - tiles: 타일 - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: 레벨 + levelTitle: 레벨 completed: 완료 unlockText: 잠금 해제! buttonNextLevel: 다음 레벨 - - # Notifications on the lower right notifications: - newUpgrade: 새로운 업그레이드를 할 수 있습니다! + newUpgrade: 새로운 업그레이드가 있습니다! gameSaved: 게임이 저장되었습니다. - - # The "Upgrades" window + freeplayLevelComplete: 레벨 성공! shop: title: 업그레이드 - buttonUnlock: 업그레이드하기 - - # Gets replaced to e.g. "Tier IX" - tier: 티어 - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - - maximumLevel: 최대 (Speed x) - - # The "Statistics" window + buttonUnlock: 업그레이드 + tier: 티어 + maximumLevel: 최종 레벨 (속도 x) statistics: title: 통계 dataSources: stored: title: 저장된 도형 - description: 당신의 중앙 건물에 저장되어 있는 도형들의 수 + description: 허브에 저장되어 있는 도형의 개수 produced: title: 제작된 도형 - description: 당신의 공장에서 만들어지고 있는 모든 도형의 개수 + description: 공장에서 만들어지고 있는 모든 도형의 개수 delivered: - title: 도착한 도형 - description: 당신의 중앙 건물에 도착하고 있는 도형의 개수 + title: 운송된 도형 + description: 허브에 도착하고 있는 도형의 개수 noShapesProduced: 지금까지 제작된 도형이 없습니다. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: 분당 개 - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: 초당 + minute: 분당 + hour: 시간당 settingsMenu: playtime: 플레이 시간 - - buildingsPlaced: 배치한 건물 - beltsPlaced: 배치한 컨베이어 벨트 - - buttons: - continue: 계속하기 - settings: 설정 - menu: 메뉴로 돌아가기 - - # Bottom left tutorial hints + buildingsPlaced: 건물 수 + beltsPlaced: 벨트 수 tutorialHints: title: 도움이 필요하세요? showHint: 힌트 보기 hideHint: 닫기 - - # When placing a blueprint blueprintPlacer: cost: 가격 - - # Map markers waypoints: waypoints: 마커 - hub: 중앙 건물 - description: 마커를 좌클릭해서 그곳으로 가고, 우클릭해서 삭제합니다.

을 눌러 지금 있는 곳에 마커를 놓거나 우클릭해서 원하는 곳에 놓으세요. - creationSuccessNotification: 마커가 성공적으로 제작되었습니다. - - # Interactive tutorial + hub: 허브 + description: 마커를 좌클릭하여 그곳으로 이동하고, 우클릭으로 삭제할 수 있습니다.

마커를 배치하기 위해 + 키로 지금 있는 위치에 혹은 우클릭하여 원하는 위치에 배치할 수 + 있습니다. + creationSuccessNotification: 마커가 성공적으로 생성되었습니다. interactiveTutorial: title: 튜토리얼 hints: - 1_1_extractor: 추출기원 모양의 도형에 놓아서 추출하세요! - 1_2_conveyor: >- - 추출기를 컨베이어 벨트로 당신의 중앙 건물에 연결하세요!

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

팁: SHIFT를 눌러 여러 개의 추출기를 놓고 R로 회전 시키세요. - + 1_1_extractor: 원형 도형을 추출하기 위해 그 위에 추출기를 선택한 뒤 + 배치하여 추출하세요! + 1_2_conveyor: "이제 컨베이어 벨트를 추출기와 허브를 서로 연결하세요!

팁: 벨트를 + 마우스로 클릭한 뒤 드래그하세요!" + 1_3_expand: "이 게임은 방치형 게임이 아닙니다! 더 많은 추출기와 벨트를 만들어 지정된 목표를 빨리 + 달성하세요.

팁: SHIFT 키를 누른 상태에서는 빠르게 배치할 수 + 있고, R 키를 눌러 회전할 수 있습니다." + 2_1_place_cutter: "이제 절단기를 배치하여 원형 도형을 둘로 자르세요!

+ 추신: 절단기는 방향에 관계 없이 항상 수직으로 자릅니다." + 2_2_place_trash: 절단기가 막히거나 멈출 수 있습니다!

+ 휴지통을 사용하여 현재 필요없는 쓰레기 도형 (!)을 + 제거하세요. + 2_3_more_cutters: "잘하셨습니다! 느린 처리 속도를 보완하기 위해 절단기를 두 개 + 이상 배치해보세요!

추신: 상단 숫자 단축키 (0~9)를 사용하여 + 건물을 빠르게 선택할 수 있습니다!" + 3_1_rectangles: "이제 사각형 도형을 추출해 볼까요! 추출기 네 개를 + 배치하고 허브와 연결하세요.

추신: 긴 벨트 한 줄을 + 간단히 만들려면 SHIFT 키를 누른 채 드래그하세요!" + 21_1_place_quad_painter: 4단 색칠기를 배치하여 흰색과 + 빨간색이 칠해진 원형 + 도형을 만들어보세요! + 21_2_switch_to_wires: E 키를 눌러 전선 레이어 + 로 전환하세요!

그 후 색칠기의 네 입력 부분을 + 모두 케이블로 연결하세요! + 21_3_place_button: 훌륭해요! 이제 스위치를 배치하고 전선으로 + 연결하세요! + 21_4_press_button: "스위치를 눌러 참 신호를 내보내 + 색칠기를 활성화하세요. 추신: 모든 입력을 연결할 필요는 없습니다! + 지금은 두 개만 연결하세요." colors: - red: 빨강 - green: 초록 - blue: 파랑 - yellow: 노랑 - purple: 보라 - cyan: 청록 - white: 하양 - uncolored: 색 - black: Black + red: 빨간색 + green: 초록색 + blue: 파란색 + yellow: 노란색 + purple: 보라색 + cyan: 시안색 + white: 흰색 + black: 검은색 + uncolored: 회색 shapeViewer: - title: 층 + title: 레이어 empty: 비었음 - copyKey: Copy Key - -# All shop upgrades + copyKey: 키 복사하기 + connectedMiners: + one_miner: 추출기 1 개 + n_miners: 추출기 개 + limited_items: 까지가 한계임 + watermark: + title: 체험판 버전 + desc: 정식 버전의 장점을 보려면 여기를 클릭하세요! + get_on_steam: Steam으로 가기 + standaloneAdvantages: + title: 정식 버전을 구매하세요! + no_thanks: 괜찮아요! + points: + levels: + title: 새로운 12 레벨 + desc: 최대 26 레벨로 확장됩니다! + buildings: + title: 새로운 18개의 건축물 + desc: 완벽한 자동화된 공장을 위한 건물들입니다! + savegames: + title: 무한한 세이브 파일 + desc: 당신이 내키는대로 마음껏 할 수 있습니다! + upgrades: + title: 20 티어까지 확장된 업그레이드 + desc: 체험판에서는 5 티어까지만 사용할 수 있습니다! + markers: + title: 무한한 마커 배치 + desc: 넓은 공장에서 길을 잃지 마세요! + wires: + title: 전선 + desc: 완전히 새로운 차원의 도입! + darkmode: + title: 다크 모드 + desc: 당신의 눈을 피곤하게 만들지 마세요! + support: + title: 저를 지원해주세요 + desc: 저는 여가 시간에 게임을 개발합니다! shopUpgrades: belt: - name: 컨베이어 벨트, 배분기, 터널 + name: 벨트, 밸런서, 터널 description: 속도 x → x miner: name: 추출기 @@ -429,436 +361,597 @@ shopUpgrades: name: 절단기, 회전기, 결합기 description: 속도 x → x painting: - name: 색 혼합기, 도형 색칠기 + name: 혼합기, 색칠기 description: 속도 x → x - -# Buildings and their name / description buildings: hub: deliver: 목표 toUnlock: 보상 levelShortcut: 레벨 - + endOfDemo: 체험판 끝 belt: default: - name: &belt 컨베이어 벨트 - description: 도형을 운반. 클릭 및 드래그해서 여러 개 배치. - - miner: # Internal name for the Extractor + name: 컨베이어 벨트 + description: 아이템을 운송합니다. 클릭 드래그하여 긴 줄을 한번에 배치할 수 있습니다. + miner: default: - name: &miner 추출기 - description: 도형 또는 색소 위에 놓아서 추출하기 - + name: 추출기 + description: 도형이나 색소 위에 배치하여 추출합니다. chainable: - name: 체인 추출기 - description: 도형 또는 색소 위에 놓아서 추출하기. 여러 개를 연결할 수 있음. - - underground_belt: # Internal name for the Tunnel + name: 연쇄 추출기 + description: 도형이나 색소 위에 배치하여 추출합니다. 서로 연결될 수 있습니다. + underground_belt: default: - name: &underground_belt 터널 - description: 도형을 건물과 벨트 밑으로 통과시킴. - + name: 터널 + description: 건물과 벨트 아래로 공간을 만들어 아이템을 통과시킵니다. tier2: name: 터널 티어 II - description: 도형을 건물과 벨트 밑으로 통과시킴. - - splitter: # Internal name for the Balancer - default: - name: &splitter 배분기 - description: 입력되는 도형을 출력에 평등하게 배분. - - compact: - name: 컴팩트 연결기 - description: 컨베이어 벨트 2개를 1개로 연결한다. - - compact-inverse: - name: 컴팩트 연결기 - description: 컨베이어 벨트 2개를 1개로 연결한다. - + description: 건물과 벨트 아래로 공간을 만들어 아이템을 통과시킵니다. cutter: default: - name: &cutter 절단기 - description: 도형을 위에서 아래로 2개로 나눈다. 만약, 출력한 2개중 1개만 사용하면 기계가 멈추니 사용하지 않는 나머지 한 개는 버릴 것 + name: 절단기 + description: 도형을 수직으로 잘라 두 가지 도형으로 나눕니다. 한쪽만 사용할 경우라면 다른 부분을 파괴하지 않을 경우 + 절단기가 막혀 멈추게 됩니다! quad: - name: 절단기 (4단) - description: 도형을 4개로 나눈다. 만약, 한 개만 사용하면 기계가 멈추니 나머지는 버릴 것 - + name: 4단 절단기 + description: 도형을 즉시 네 개로 자릅니다. 한쪽만 사용할 경우라면 다른 부분을 파괴하지 않을 경우 절단기가 막혀 + 멈추게 됩니다! rotater: default: - name: &rotater 회전기 - description: 도형을 시계방향으로 90도 회전시킨다. + name: 회전기 + description: 도형을 시계 방향으로 90도 회전시킵니다. ccw: - name: 회전기 (반시계방향) - description: 도형을 반시계방향으로 90도 회전시킨다. - + name: 반시계 방향 회전기 + description: 도형을 반시계 방향으로 90도 회전시킵니다. + rotate180: + name: 180도 회전기 + description: 도형을 180도 회전시킵니다. stacker: default: - name: &stacker 스택커 - description: 도형 2개를 쌓는다. 합칠 수가 없다면 오른쪽 도형이 왼쪽 도형 위에 놓아진다. - + name: 결합기 + description: 도형을 서로 결합하고 쌓습니다. 서로 결합할 수 있다면 두 도형을 붙여 하나로 만들고, 그렇지 않으면 오른쪽 도형이 왼쪽 + 도형 위에 쌓이게 됩니다. mixer: default: - name: &mixer 색 혼합기 - description: 두가지 색을 섞어서 다른 색을 만든다. - + name: 색소 혼합기 + description: 두 가지의 색소를 혼합해 다른 혼합 색소를 만듭니다. painter: default: - name: &painter 도형 색칠기 - description: &painter_desc 도형을 색소로 색칠한다. + name: 색칠기 + description: 색소를 이용해 도형을 색칠합니다. 위쪽에서 받는 색소로 왼쪽에서 받는 도형 전체를 색칠합니다. double: - name: 2단 도형 색칠기 - description: 왼쪽에 입력되는 도형을 위에서 입력되는 색소로 색칠한다. + name: 2단 색칠기 + description: 색소를 이용해 도형을 색칠합니다. 위쪽에서 받는 색소로 왼쪽에서 받는 도형 전체를 색칠합니다. quad: - name: 4단 도형 색칠기 - description: 도형의 4가지 분단을 각각 다른 색으로 색칠할 수 있다. + name: 4단 색칠기 + description: 도형의 각 사분면에 개별적으로 색상을 칠할 수 있습니다. 전선 레이어를 통해 참 신호가 + 있는 슬롯만 칠해집니다! mirrored: - name: *painter - description: *painter_desc - + name: 색칠기 + description: 색소를 이용해 도형을 색칠합니다. 아래쪽에서 받는 색소로 왼쪽에서 받는 도형 전체를 색칠합니다. trash: default: - name: &trash 휴지통 - description: 양쪽에서 오는 모든 입력물을 버린다. - - storage: - name: 저장소 - description: 할당된 용량만큼 초과되는 도형을 저장한다. + name: 휴지통 + description: 어느 곳에서든 들어오는 아이템을 영원히 파괴합니다. wire: default: - name: Energy Wire - description: Allows you to transport energy. - advanced_processor: + name: 전선 + description: 아이템, 색상, 또는 불 값 (0 혹은 1)이 될 수 있는 신호를 전송합니다. 색이 다른 전선은 서로 연결되지 않습니다. + second: + name: 전선 + description: 아이템, 색상, 또는 불 값 (0 혹은 1)이 될 수 있는 신호를 전송합니다. 색이 다른 전선은 서로 연결되지 않습니다. + balancer: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For - default: - name: Energy Generator - description: Generates energy by consuming shapes. - 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: 컨베이어 벨트 두 줄을 한 줄로 합칩니다. + merger-inverse: + name: 압축형 병합기 + description: 컨베이어 벨트 두 줄을 한 줄로 합칩니다. + splitter: + name: 압축형 분배기 + description: 컨베이어 벨트 한 줄을 두 줄로 나눕니다. + splitter-inverse: + name: 압축형 분배기 + description: 컨베이어 벨트 한 줄을 두 줄로 나눕니다. + storage: + default: + name: 저장고 + description: 아이템을 지정된 용량까지 저장합니다. 왼쪽 출력이 가장 우선되므로 오버플로 회로로 사용할 수 있습니다. + wire_tunnel: + default: + name: 전선 교차 장치 + description: 두 전선이 서로 연결되지 않고 교차할 수 있도록 합니다. + constant_signal: + default: + name: 일정 신호 + description: 모양, 색상, 또는 불 값 (1 혹은 0)이 될 수 있는 상수 신호를 방출합니다. + lever: + default: + name: 스위치 + description: 전선 레이어에서 불 값 (1 또는 0)를 방출하도록 전환할 수 있으며, 그 후 아이템 선별같은 구성 요소를 제어하는 데 + 사용될 수 있습니다. + logic_gate: + default: + name: AND 회로 + description: 두 입력이 모두 참일 경우 불 값 "1"을 내보냅니다 (참은 도형, 색상, 불 값 "1"을 의미합니다). + not: + name: NOT 회로 + description: 입력이 거짓일 경우 불 값 "1"을 내보냅니다 (참은 도형, 색상, 불 값 "1"을 의미합니다). + xor: + name: XOR 회로 + description: 입력 중 하나만 참이고 둘 다 같지 않을 경우 불 값 "1"을 내보냅니다 (참은 도형, 색상, 불 값 "1"을 + 의미합니다). + or: + name: OR 회로 + description: 입력 중 하나 이상이 참일 경우 불 값 "1"을 내보냅니다 (참은 도형, 색상, 불 값 "1"을 의미합니다). + transistor: + default: + name: 트랜지스터 + description: 양 옆의 입력이 참일 경우 아래쪽 입력을 전달합니다 (모양, 색상, 또는 값 "1"일 경우). + mirrored: + name: 트랜지스터 + description: 양 옆의 입력이 참일 경우 아래쪽 입력을 전달합니다 (모양, 색상, 또는 값 "1"일 경우) + filter: + default: + name: 선별기 + description: 신호를 연결하여 일치하는 모든 아이템은 위로, 나머지 아이템은 오른쪽으로 내보냅니다. 불 값으로도 제어할 수 있습니다. + display: + default: + name: 디스플레이 + description: 신호를 연결하여 디스플레이에 도형이나 색상 또는 불 값을 표시합니다. + reader: + default: + name: 벨트 판독기 + description: 벨트의 평균 처리량을 측정합니다. (잠금 해제된) 전선 레이어에서 마지막으로 읽은 아이템을 출력합니다. + analyzer: + default: + name: 도형 분석기 + description: 도형의 가장 낮은 레이어의 오른쪽 상단 사분면을 분석하고 모양과 색상을 반환합니다. + comparator: + default: + name: 비교기 + description: 두 신호가 정확히 동일할 경우 불 값 "1"을 반환합니다. 도형, 색상, 불 값을 비교할 수 있습니다. + virtual_processor: + default: + name: 가상 절단기 + description: 가상으로 도형을 잘라 반으로 나눕니다. + rotater: + name: 가상 회전기 + description: 가상으로 도형을 시계 방향이나 반시계 방향으로 회전합니다. + unstacker: + name: 가상 결합해제기 + description: 가상으로 최상단에 있는 레이어를 오른쪽으로 출력하고, 나머지는 왼쪽으로 출력합니다. + stacker: + name: 가상 결합기 + description: 가상으로 오른쪽 도형을 왼쪽 도형에 쌓습니다. + painter: + name: 가상 색칠기 + description: 가상으로 하단 입력의 모양을 오른쪽 입력의 색상으로 칠합니다. + item_producer: + default: + name: 아이템 생성기 + description: 샌드박스 모드에서만 사용할 수 있는 아이템으로, 일반 레이어 위에 있는 전선 레이어에서 주어진 신호를 출력합니다. storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: 절단기 - desc: 절단기가 잠금 해제되었습니다! 절단기는 도형을 세로로 잘라 반으로 나눕니다.

사용하지 않는 도형은 휴지통에 버려주세요. 그렇지 않으면 절단기가 멈출 것입니다. - + desc: 절단기가 잠금 해제되었습니다! 절단기는 들어오는 도형이 어떤 모양을 하고 있던 수직으로 잘라 + 반으로 나눕니다!

쓰지 않는 도형은 쓰레기로 처리하세요, 그렇지 않으면 + 작동을 멈출 것입니다! 이러한 목적을 위해 휴지통도 함께 + 지급되었습니다. 휴지통에 들어간 것은 모두 파괴됩니다! reward_rotater: title: 회전기 - desc: 회전기가 잠금 해제되었습니다! 이것은 도형을 시계방향으로 90도 회전 시킵니다. - + desc: 회전기가 잠금 해제되었습니다! 회전기는 들어오는 도형을 시계 방향으로 90도 회전시켜줍니다. reward_painter: title: 색칠기 - desc: >- - 색칠기가 잠금 해제되었습니다. - 추출한 색소(도형을 추출하는 것처럼)를 색칠기에서 도형과 합쳐 색칠된 도형을 얻으세요!

추신: 색맹이라면, 설정에서 색맹 모드를 활성화 시키세요! - + desc: "색칠기가 잠금 해제되었습니다! 도형과 마찬가지로 색소를 추출하고 색칠기에 넣거 도형과 결합하여 색칠된 + 도형을 만들도록 하세요!

추신: 만약 당신이 색맹이라면, 설정에서 색맹 모드를 + 활성화하세요!" reward_mixer: title: 혼합기 - desc: 혼합기가 잠금 해제되었습니다! 이 건물로 두 색소를 혼합하세요! - + desc: 혼합기가 잠금 해제되었습니다! 서로 다른 두 색소를 혼합하여 새로운 혼합 + 색소를 얻을 수 있습니다! reward_stacker: title: 결합기 - desc: 결합기가 잠금 해제되었습니다! 두 도형이 서로 옆에 놓을 수 있는 경우, 두 도형이 결합됩니다. 그렇지 않은 경우, 오른쪽 도형이 왼쪽 도형 위에 쌓이게됩니다. - + desc: 결합기가 잠금 해제되었습니다! 이제 결합기를 통해 여러 도형을 붙이고 결합할 수 있습니다! 들어오는 두 + 도형의 모양이 서로 나란히 붙일 수 있다면, 하나의 도형으로 결합됩니다. 만약 서로 + 겹쳐진다면, 오른쪽 도형이 왼쪽 도형의 위에 쌓이게 됩니다! reward_splitter: - title: 배분기 - desc: 다양한 용도로 쓰이는 배분기가 잠금 해제되었습니다! 배분기로 도형들을 여러 개의 벨트에 합하거나 나누어서 큰 공장을 지을 수 있습니다.

- + title: 압축형 분배기 + desc: 밸런서의 새로운 형태인 분배기가 잠금 해제되었습니다! 이제 벨트 한 줄을 + 즉시 두 줄로 분배합니다! reward_tunnel: title: 터널 - desc: 터널이 잠금 해제되었습니다! 자원을 건물과 벨트 밑으로 운송 할 수 있습니다. - + desc: 터널이 잠금 해제되었습니다! 이제 벨트와 건물 아래로 공간을 만들어내 옮길 수 있습니다! reward_rotater_ccw: - title: 회전기 (반시게방향) - desc: 반시게방향 회전기가 잠금 해제되었습니다! 이것을 배치하려면 회전기를 선택하고 T를 눌러서 변형된 버전을 사용하세요! - + title: 반시계 방향 회전기 + desc: 반시계 방향 회전기가 잠금 해제되었습니다! 반시계 방향 회전기는 회전기의 다른 형태로, 이름처럼 + 들어오는 도형을 반시계 방향으로 90도만큼 회전시킵니다! 제작하려면 회전기를 선택한 후 'T' 키를 눌러 + 다른 형태로 전환하세요! reward_miner_chainable: - title: 체인 추출기 - desc: 체인 추출기가 잠금 해제되었습니다! 체인 추출기는 자원을 다른 추출기로 전달하여 효율적으로 추출할 수 있게 합니다. - + title: 연쇄 추출기 + desc: "연쇄 추출기가 잠금 해제되었습니다! 자원을 보다 더욱 효율적으로 추출할 수 있도록 앞에 + 있는 추출기로 자원을 보낼 수 있습니다!

추신: 이제 툴바에 있는 기존 추출기는 연쇄 + 추출기로 대체되었습니다!" reward_underground_belt_tier_2: title: 터널 티어 II - desc: 새로운 종류의 터널이 잠금 해제되었습니다! 새 터널은 보다 넓은 범위를 가졌으며, 터널들은 같은 종류끼리만 연결됩니다. - - reward_splitter_compact: - title: 컴팩트 연결기 - desc: >- - 컴팩트 연결기가 잠금 해제되었습니다! 벨트 2개를 1개로 만듭니다. - + desc: 터널의 새로운 형태가 잠금 해제되었습니다! 터널 티어 II는 더욱 긴 + 거리를 운송할 수 있고 기존 터널과 겹쳐지지 않고도 자원을 보낼 수 있습니다! reward_cutter_quad: - title: 절단기 (4단) - desc: 새로운 종류의 절단기가 잠금 해제되었습니다! 새 절단기는 도형을 2조각이 아니라 4조각으로 자릅니다. - + title: 4단 절단기 + desc: 새로운 종류의 절단기가 잠금 해제되었습니다! 4단 절단기는 도형을 두 조각이 아닌 네 + 조각으로 자를 수 있습니다! reward_painter_double: - title: 색칠기 (2단) - desc: 새로운 종류의 색칠기가 잠금 해제되었습니다! 새 색칠기는 색소 하나로 2개의 도형을 색칠할 수 있습니다. - - reward_painter_quad: - title: 색칠기 (4단) - desc: 4단 도형 색칠기가 잠금 해제되었습니다! 도형의 4분단을 각각 다른 색으로 색칠할 수 있습니다! - + title: 2단 색칠기 + desc: 새로운 종류의 절단기가 잠금 해제되었습니다! 일반적인 색칠기와 거의 동일하지만, 하나의 색소를 사용하여 + 동시에 두 개의 도형을 색칠할 수 있습니다! reward_storage: - title: 저장소 - desc: 저장소가 잠금 해제되었습니다! 주어진 용량만큼 자원을 저장할 수 있습니다! - + title: 저장고 + desc: 저장고가 잠금 해제되었습니다! 저장고는 최대 용량까지 도형을 저장할 수 있습니다!

왼쪽 + 출력이 우선되므로 오버플로 회로로도 활용될 수 있습니다! reward_freeplay: - title: 프리플레이 모드 - desc: 해내셨군요! 프리플레이 모드가 잠금 해제되었습니다! 이제 도형이 랜덤으로 생성됩니다! (걱정 마세요, 유료버전에는 더 많은 컨텐츠가 계획되어 있습니다!) - + title: 자유플레이 + desc: 드디어 해내셨군요! 자유플레이 모드가 잠금 해제되었습니다! 이는 즉 앞으로 도형이 + 무작위로 생성됩니다.

이제부터 허브는 처리량이 + 필요하므로 요청하는 도형을 자동으로 전달하는 공장을 구축하는 것이 좋습니다.

허브는 요청된 도형을 전선 + 레이어에서 출력하므로 이를 분석하고 기반으로 하여 공장을 자동으로 구성하기만 하면 됩니다. reward_blueprints: - title: 블루프린트 - desc: 이제부터는 공장의 일부 영역을 복사하여 붙여넣기 할 수 있습니다! CTRL을 누르면서 드래그해서 먼저 영역을 선택하세요.

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

복사는 무료가 이닙니다. 특별한 "화폐" 도형으로 돈을 지불하고 복사가 됩니다. - - # Special reward, which is shown when there is no reward actually + title: 청사진 + desc: 이제 공장의 일부를 복사하고 붙여넣는 기능을 사용할 수 있습니다! 영역을 선택 (CTRL 키를 누른 채 + 마우스로 드래그)한 뒤 'C' 키를 눌러 복사할 수 있습니다.

하지만 공짜는 + 아닙니다, 청사진 모양 도형을 허브에 저장하고 그것을 일부 사용해 붙여넣기 + 기능을 사용할 수 있습니다! (방금 당신이 만든 것입니다.) no_reward: title: 다음 레벨 - desc: >- - 이 단계는 아무런 보상이 없습니다. 하지만 다음 단계에는 있죠!

추신: 현존하는 공장을 부수지 않는 것이 좋습니다. - 추후 업그레이드를 해제하기 위해 모든 도형들이 필요합니다! - + desc: "이번 레벨의 보상은 없네요. 대신 다음 레벨에서 줄겁니다!

추신: 기존 공장을 파괴하지는 마세요. 후에 + 업그레이드 잠금 해제되면 기존의 모든 도형이 필요합니다!" no_reward_freeplay: title: 다음 레벨 - desc: >- - 축하드립니다! 유료 버전을 위한 더 많은 컨텐츠를 만들고 있습니다. - + desc: 축하드립니다! + reward_balancer: + title: 밸런서 + desc: 밸런서가 잠금 해제되었습니다! 다목적 밸런서를 통해 여러 벨트의 아이템을 서로 다른 + 벨트로 분할하거나 합침으로써 더욱 거대한 공장을 만들 수 있습니다! + reward_merger: + title: 압축형 병합기 + desc: 밸런서의 새로운 형태인 병합기가 잠금 해제되었습니다! 이제 벨트 두 줄을 + 즉시 한 줄로 병합합니다! + reward_belt_reader: + title: 벨트 판독기 + desc: 벨트 판독기가 잠금 해제되었습니다! 이제 벨트의 처리량을 확인할 수 있습니다.

그리고, + 전선이 잠금 해제될 때 까지 기다리신다면 정말 유용하게 사용할 수 있을 겁니다! + reward_rotater_180: + title: 180도 회전기 + desc: 180도 회전기가 잠금 해제되었습니다! 이제 도형을 바로 180도로 회전시킬 수 있습니다. (짜잔! + :D) + reward_display: + title: 디스플레이 + desc: "디스플레이가 잠금 해제되었습니다! 이제 신호를 전선 레이어에 연결해 시각화할 수 + 있습니다.

추신: 벨트 판독기와 저장고가 마지막으로 읽은 아이템을 출력했나요? 디스플레이로 한번 봐보세요!" + reward_constant_signal: + title: 일정 신호 + desc: 전선 레이어에서 구축할 수 있는 일정 신호가 잠금 해제되었습니다! 간단한 예시로, 아이템 + 선별에 연결하여 사용하는 데 유용합니다.

일정 신호는 도형, + 색상, 혹은 불 값 (1 혹은 0)을 출력할 수 있습니다. + reward_logic_gates: + title: 논리 회로 + desc: 논리 회로가 잠금 해제되었습니다! 굳이 흥분할 필요는 없지만, 진짜 멋진 기술입니다!

+ 논리 회로를 통해 이제 AND, OR, XOR, NOT 논리 연산을 할 수 있습니다.

보너스로, + 트랜지스터도 지급되었습니다! + reward_virtual_processing: + title: 가상 처리 + desc: 도형의 처리를 시뮬레이션할 수 있는 다양한 새로운 건물이 잠금 해제되었습니다!

이제 전선 + 레이어에서 도형에 대한 절단기, 회전기, 결합기 등을 가상으로 시뮬레이션할 수 있습니다! 이제 게임 진행에 있어 다음 세 + 가지의 방법이 존재합니다:

- 완전 자동화된 기계를 구축하고 허브에서 요구되는 + 도형을 제작합니다. (먼저 시도해볼 것을 권합니다!).

- 전선을 통해 멋진 것들 만듭니다.

+ - 평소처럼 게임을 진행합니다.

어떤 방식으로든, 재미있게 게임을 플레이해주시길 바랍니다! + reward_wires_painter_and_levers: + title: 전선과 4단 색칠기 + desc: "전선 레이어가 잠금 해제되었습니다! 전선 레이어는 + 일반 레이어 위에 존재하는 별도의 레이어로, 이를 통한 다양하고 새로운 + 메커니즘을 소개하겠습니다!

우선 4단 색칠기가 + 잠금 해제되었습니다. 전선 레이어에서 색칠하고 싶은 슬롯에 전선을 연결하세요! + 전선 레이어로 전환하려면 E 키를 누르세요.

+ 추신: 설정에서 힌트를 활성화하여 전선 튜토리얼을 활성화하세요!" + reward_filter: + title: 아이템 선별기 + desc: 아이템 선별기가 잠금 해제되었습니다! 전선 레이어의 신호와 일치하는지에 대한 여부로 아이템을 위쪽 + 출력이나 오른쪽 출력으로 보냅니다.

불 값 (1 또는 0)을 전달하여 완전히 활성화과 비활성화를 전환할 수 + 있습니다. + reward_demo_end: + title: 체험판 끝 + desc: 체험판 콘텐츠가 모두 끝이 났습니다! settings: title: 설정 categories: - game: 게임 - app: 앱 - + general: 일반 + userInterface: 사용자 인터페이스 + advanced: 고급 + performance: 성능 versionBadges: - dev: 발전 중 - staging: 단계적으로 발전 중 - prod: 제작 중 - buildDate: 날짜 - + dev: 개발 + staging: 검증 + prod: 배포 + buildDate: 제작 labels: uiScale: title: UI 크기 - description: >- - UI의 크기를 변경시키기: + description: 사용자 인터페이스의 크기를 변경합니다. 인터페이스는 당신의 해상도에 따라 확장되는데 이 설정은 그 확장의 정도를 + 제어합니다. scales: super_small: 매우 작게 small: 작게 regular: 보통 large: 크게 - huge: 거대하게 - + huge: 매우 크게 scrollWheelSensitivity: - title: 확대 민감도 - description: >- - 마우스 휠이나 트렉패드로 확대하는 데의 민감도 + title: 화면 줌 감도 + description: (마우스 휠이나 트랙 패드를 통한) 화면 줌 인/아웃 감도를 설정합니다. sensitivity: super_slow: 매우 느리게 slow: 느리게 regular: 보통 fast: 빠르게 super_fast: 매우 빠르게 - movementSpeed: title: 이동 속도 - description: >- - 키보드를 사용할 때, 화면 이동 속도를 설정합니다. + description: 키보드나 마우스를 화면 테두리로 옮겨 화면을 이동할 때 이동 속도를 설정합니다. speeds: super_slow: 매우 느리게 slow: 느리게 regular: 보통 fast: 빠르게 super_fast: 매우 빠르게 - extremely_fast: 극한의 속도 - + extremely_fast: 극도로 빠르게 language: title: 언어 - description: >- - 언어 바꾸기 - 모든 언어팩은 사용자들이 만든 것이므로 완성되지 않았을 수 있습니다.. - + description: 언어를 바꿉니다. 모든 언어팩은 사용자들이 모여 만드므로 정확하지 않을 수 있습니다! fullscreen: - title: Fullscreen - description: >- - 이 게임은 풀 스크린으로 하는 것이 가장 좋습니다. 풀 스크린 모드는 유료 버전에서만 가능합니다. - + title: 전체 화면 + description: 이 게임은 전체 화면으로 하는 것이 가장 좋습니다. 전체 화면 기능은 정식 버전에서만 가능합니다. soundsMuted: - title: 소리 끄기 - description: >- - 모든 효과음을 끕니다. - + title: 효과음 끄기 + description: 모든 효과음을 끕니다. musicMuted: title: 음악 끄기 - description: >- - 모든 배경 음악을 끕니다. - + description: 모든 배경 음악을 끕니다. theme: title: 게임 테마 - description: >- - 게임 테마를 고르세요. (밝음/어두움). + description: 게임 테마를 고르세요. (라이트/다크). themes: - dark: 어두운 테마 - light: 밝은 테마 - + dark: 다크 + light: 라이트 refreshRate: - title: 모니터 리프레쉬 속도 - description: >- - 당신의 모니터의 리프세쉬 속도가 144hz 보다 높으면 이 설정을 바꾸어서 게임이 더 빨리 리프레시 되게 하세요. 만약에 컴퓨터가 느리다면 FPS에 영양을 미칠 수 있습니다. - + title: 틱 빈도 + description: 이것은 초당 발생하는 게임 틱 수를 결정합니다. 일반적으로 틱 속도가 높을수록 정밀도는 향상되나 성능은 낮아집니다. 낮은 + 틱 빈도에서는 처리량이 정확하지 않을 수 있습니다. alwaysMultiplace: - title: 항상 여러 개 배치 - description: >- - 배치 이후에도 모든 빌딩이 선택되어 있습니다. SHIFT를 계속 누르고 있는 것과 같은 효과입니다. - + title: 다수 배치 항시 켜기 + description: 활성화할 경우 모든 건물은 배치한 후 취소할 때 까지 커서에 선택된 상태를 유지합니다. 이 기능은 SHIFT 키를 계속 + 누르는 것과 같습니다. offerHints: title: 힌트와 튜토리얼 - description: >- - 이것을 끄면 힌트와 튜토리얼이 나오지 않습니다. 또한 게임에 쉽게 들어가기 위해서 주어진 레벨에서 특정 UI 요소를 숨길 수도 있습니다. - + description: 게임 플레이하는 동안 힌트와 튜토리얼을 보여줄 지를 결정합니다. 또한 게임에 더 쉽게 빠져들 수 있도록 특정 레벨까지 + 특정한 UI 요소를 숨깁니다. enableTunnelSmartplace: - title: 스마트 터널 - description: >- - 활성화 시키면, 터널을 설치하는 것이 자동적으로 불필요한 벨트를 없앱니다. - 또한, 터널을 당겨서 남는 터널을 없앱니다. - + title: 지능적인 터널 배치 + description: 활성화할 경우 터널을 설치할 때 터널 사이에 있는 불필요한 벨트를 제거합니다. 또한 터널을 당겨서 남는 터널을 없앱니다. vignette: - title: 삽화 - description: >- - 화면의 코너를 어둡게 만들어 텍스트를 읽기 쉽게 해주는 삽화를 활성화 시킵니다. - + title: 비네트 효과 + description: 화면의 모서리를 어둡게 만들어 텍스트를 읽기 쉽게 해주는 비네트 효과를 활성화 시킵니다. autosaveInterval: - title: 자동저장 주기 - description: >- - 자동저장을 얼마나 자주 할 것인지 정합니다. 자동저장기능을 끌 수도 있습니다. + title: 자동 저장 주기 + description: 자동저장을 얼마나 자주 할 것인지 정합니다. 자동저장 기능을 끌 수도 있습니다. intervals: one_minute: 1분 two_minutes: 2분 five_minutes: 5분 ten_minutes: 10분 twenty_minutes: 20분 - disabled: 기능 끄기 + disabled: 끄기 compactBuildingInfo: - title: 간결한 건물 정보 - description: >- - 건물의 정보창을 해당 건물의 능률만 보이도록 줄입니다. - 아니면, 설명과 이미지가 보입니다. + title: 건물 정보 간소화 + description: 건물에 대한 정보 상자를 줄여 처리 비율만 나타냅니다. 아니라면 설명과 이미지가 함께 표시됩니다. disableCutDeleteWarnings: - title: 자르기/삭제 경고기능 끄기 - description: >- - 100개 이상의 건물을 자르기/삭제할 때 경고창이 나오지 않게 합니다. - + title: 자르기 및 삭제 경고 끄기 + description: 100개가 넘는 개체를 자르거나 삭제할 때 표시되는 경고창을 띄우지 않도록 합니다. enableColorBlindHelper: title: 색맹 모드 - description: 색맹이 게임을 플레이하는데 도움을 주는 다양한 도구를 활성화 시킵니다. + description: 색맹 사용자를 위해 게임을 플레이하는 데 도움을 주는 다양한 도구를 활성화합니다. rotationByBuilding: title: 건물 유형에 따른 방향 - description: >- - 각 건물 유형은 최근에 설정한 방향을 개별적으로 기억합니다. - 다른 유형의 건물 배치 간에 자주 방향을 전환할 경우, 이 방법이 더 편할 수 있습니다. - + description: 각 건물 유형마다 개별적으로 마지막으로 설정했던 방향을 기억하도록 합니다. 다른 건물 변형을 자주 전환하는 경우 이 + 방법이 더욱 편할 수 있습니다. + soundVolume: + title: 효과음 볼륨 + description: 효과음의 볼륨을 조절합니다. + musicVolume: + title: 음악 볼륨 + description: 음악 볼륨을 조절합니다. + lowQualityMapResources: + title: 저품질 지도 자원 + description: 성능 향상을 위해 지도 확대 시 자원의 렌더링을 단순화합니다. 더욱 깨끗해 보이는 편이니 꼭 해보세요! + disableTileGrid: + title: 그리드 비활성화 + description: 성능 향상을 위해 타일 그리드를 비활성화할 수 있습니다. 이 역시 게임을 더욱 깨끗하게 보여줍니다! + clearCursorOnDeleteWhilePlacing: + title: 우클릭 시 커서 지우기 + description: 기본적으로 활성화되어 있으며, 배치할 건물을 선택한 상태에서 마우스 우클릭 시 커서를 지웁니다. 비활성화할 경우, 건물을 + 커서에 선택한 채로 우클릭하면 바로 건물을 삭제할 수 있습니다. + lowQualityTextures: + title: 저품질 텍스처 (못생김) + description: 성능 향상을 위해 낮은 품질의 텍스처를 사용합니다. 이것은 게임을 아주 못생기게 만들 겁니다! + displayChunkBorders: + title: 청크 경계 표시 + description: 게임의 청크는 16x16의 타일로 나누어지며, 이 설정을 활성화하면 각 청크의 테두리가 표시됩니다. + pickMinerOnPatch: + title: 자원 패치에서 추출기 즉시 선택 + description: 기본적으로 활성화되어 있으며, 자원 패치에서 피펫 기능을 사용 시 즉시 추출기를 선택합니다. + simplifiedBelts: + title: 벨트 단순화 (못생김) + description: 성능 향상을 위해 벨트를 가리킬 때를 제외한 모든 상황에서 벨트 아이템을 렌더링하지 않습니다. 이 기능을 사용할 할 + 정도로 심각한 성능 문제가 일어나지 않는 한, 이 설정을 사용할 필요는 없습니다. + enableMousePan: + title: 화면 가장자리 패닝 + description: 커서를 화면 가장자리로 옮기면 스크롤되어 지도를 이동할 수 있습니다. 스크롤 속도는 이동 속도 설정에 따릅니다. + zoomToCursor: + title: 커서를 기준으로 줌 + description: 활성화할 경우 화면 줌 인 아웃이 마우스 커서가 있는 지점을 기준이 되며, 아닐 경우 화면 중앙이 기준이 됩니다. + mapResourcesScale: + title: 지도 자원 크기 + description: 지도를 축소할 때 나타나는 도형의 크기를 제어합니다. + rangeSliderPercentage: % keybindings: - title: 키바인딩 - hint: >- - 팁: CTRL, SHIFT, ALT를 활용하세요. 건물을 배치할 때 유용합니다. - - resetKeybindings: 키바인딩 리셋 - + title: 조작법 + hint: "팁: CTRL, SHIFT, ALT를 적절히 사용하세요! 건물을 배치할 때 유용합니다." + resetKeybindings: 초기화 categoryLabels: - general: 앱 + general: 애플리케이션 ingame: 게임 navigation: 둘러보기 - placement: 놓기 - massSelect: 다중 선택 - buildings: 건물 쇼트컷 - placementModifiers: 배치 수정기 - + placement: 배치 + massSelect: 대량 선택 + buildings: 건물 단축키 + placementModifiers: 배치 설정 mappings: confirm: 확인 back: 취소 - mapMoveUp: 위로 가기 - mapMoveRight: 오른쪽으로 가기 - mapMoveDown: 밑으로 가기 - mapMoveLeft: 왼쪽으로 가기 - centerMap: 맵 중앙으로 가기 - + mapMoveUp: 위쪽 이동 + mapMoveRight: 오른쪽 이동 + mapMoveDown: 아래쪽 이동 + mapMoveLeft: 왼쪽 이동 + centerMap: 맵 중앙으로 이동 mapZoomIn: 확대 mapZoomOut: 축소 - createMarker: 마커 놓기 - + createMarker: 마커 배치 menuOpenShop: 업그레이드 menuOpenStats: 통계 - - toggleHud: UI보기/숨기기 - toggleFPSInfo: FPS 와 디버그 보기/숨기기 - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + toggleHud: HUD 토글 + toggleFPSInfo: FPS와 디버그 정보 토글 + belt: 컨베이어 벨트 + underground_belt: 터널 + miner: 추출기 + cutter: 절단기 + rotater: 회전기 + stacker: 결합기 + mixer: 혼합기 + painter: 색칠기 + trash: 휴지통 rotateWhilePlacing: 회전 - rotateInverseModifier: >- - Modifier: 대신 반시계방향으로 회전 - cycleBuildingVariants: 변형종 사용 - confirmMassDelete: 대량 삭제 확인 - pasteLastBlueprint: 최근 청사진 붙여넣기 - cycleBuildings: 건물 사이클 - + rotateInverseModifier: "변경: 대신 반시계 방향" + cycleBuildingVariants: 형태 전환 + confirmMassDelete: 대량 삭제 + pasteLastBlueprint: 마지막 청사진 붙여넣기 + cycleBuildings: 건물 전환 massSelectStart: 누르고 드래그해서 시작 massSelectSelectMultiple: 여러 곳 선택 massSelectCopy: 영역 복사 massSelectCut: 영역 자르기 - placementDisableAutoOrientation: 자동 회전 끄기 - placeMultiple: 배치 모드에 있기 - placeInverse: 자동 벨트 회전 뒤집기 + placeMultiple: 배치 모드 유지 + placeInverse: 반대 방향으로 벨트 배치 exportScreenshot: 공장 전체를 이미지로 내보내기 mapMoveFaster: 더 빠르게 움직이기 - lockBeltDirection: 벨트 플래너 활성화 - switchDirectionLockSide: "플래너: 방향 바꾸기" + lockBeltDirection: 벨트 계획기 활성화 + switchDirectionLockSide: "계획기: 방향 바꾸기" pipette: 피펫 - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire - + menuClose: 메뉴 닫기 + switchLayers: 레이어 전환 + wire: 전선 + balancer: 밸런서 + storage: 저장고 + constant_signal: 일정 신호 + logic_gate: 논리 회로 + lever: 레버 + filter: 선별기 + wire_tunnel: 전선 교차 장치 + display: 디스플레이 + reader: 벨트 판독기 + virtual_processor: 가상 절단기 + transistor: 트랜지스터 + analyzer: 도형 분석기 + comparator: 비교기 + item_producer: 아이템 생성기 (샌드박스) + copyWireValue: "전선: 커서 아래 값 복사" about: - title: 이 게임의 정보 + title: 게임 정보 body: >- - 이 게임은 오픈소스이고, Tobias Springer가 개발했습니다.

+ 이 게임은 오픈소스이고, Tobias + Springer가 개발했습니다.

- 이 게임을 위해 이바지하고 싶다면, shapez.io on github를 확인하세요.

+ 이 게임을 위해 기여하고 싶다면, shapez.io on github를 확인하세요.

- 이 게임은 디스코드 커뮤니티의 공헌이 없었다면 불가능했을 것입니다. - 우리 디스코드 커뮤니티에 꼭 참여해주세요! 디스코드 서버!

+ 이 게임은 Discord 커뮤니티의 공헌이 없었다면 불가능했을 것입니다. 우리 Discord 커뮤니티에 꼭 참여해주세요! Discord 서버!

- 사운드 트랙 제작자는 Peppsen입니다. - 킹갓제너럴 Peppsen!

- - 마지막으로, 나의 절친 Niklas에게 - 크나큰 감사를 표합니다 - 우리가 함께 해낸 Factorio가 아니었다면, 이 게임은 존재하지 않았을 겁니다! + 사운드 트랙 제작자는 Peppsen입니다. - 킹갓제너럴 Peppsen!

+ 마지막으로, 나의 절친 Niklas에게 크나큰 감사를 표합니다 - 우리가 함께 해낸 Factorio가 아니었다면, 이 게임은 존재하지 않았을 겁니다! changelog: - title: 업데이트 기록 - + title: 업데이트 목록 demo: features: - restoringGames: 게임 자장 파일 리스토어 하기 - importingGames: 게임 저장 파일 불러오기 - oneGameLimit: 게임 저장 파일 최대 1개 - customizeKeybindings: 키바인딩 설정하기 + restoringGames: 게임 세이브 파일 복원 하기 + importingGames: 게임 세이브 파일 가져오기 + oneGameLimit: 게임 세이브 파일 최대 1개 + customizeKeybindings: 조작법 설정하기 exportingBase: 공장 전체를 이미지로 내보내기 - - settingNotAvailable: 데모 버전에서 사용 불가 + settingNotAvailable: 체험판 버전에서 사용 불가 +tips: + - 허브는 단지 필요로 하는 도형은 물론, 모든 형태의 도형 입력을 허용합니다! + - 공장을 짓기 전에 확장 가능성을 고려하세요. 분명 좋은 대가를 받게 될겁니다! + - 공장을 허브에 너무 가까이 짓지 마세요. 그렇지 않으면 크나큰 혼란을 겪을 수 있습니다! + - 결합기가 작동되지 않는다면, 두 도형의 입력을 서로 바꿔보세요. + - 벨트 계획 중 R 키를 눌러 방향을 전환할 수 있습니다. + - CTRL 키를 누른 채 벨트를 배치하면 자동으로 벨트가 연결되지 않게 됩니다. + - 모든 업그레이드의 티어가 동일하다면 모든 공장의 처리 비율도 동일합니다. + - 높은 효율에는 병렬보다 직렬입니다. + - 나중에 더 많은 변형 건물을 잠금 해제할 수 있습니다! + - T 키를 눌러 건물의 다른 형태로 전환할 수 있습니다. + - 대칭이 핵심입니다! + - 서로 다른 티어의 터널은 같은 줄에서 서로 겹쳐지지 않습니다. + - 공장은 가능한 작게, 오밀조밀하게 지으세요. 분명 좋은 대가를 받게 될겁니다! + - 색칠기에는 T키로 선택할 수 있는 반전 형태가 있습니다. + - 각 건물 간의 처리 비율이 동일하다면 그 효율은 극대화됩니다. + - 최대 레벨에서, 한 줄의 벨트를 채우기 위해 다섯 개의 추출기가 필요합니다. + - 터널을 잊지 마세요! + - 완벽한 효율성을 위해 굳이 아이템을 균등하게 배분할 필요는 없습니다. + - SHIFT키를 누르면 벨트 계획기가 활성화되어 긴 길이의 벨트 한 줄을 쉽게 배치할 수 있습니다. + - 절단기는 들어오는 도형과 배치된 절단기의 방향에 관계 없이, 언제나 수직으로 자릅니다. + - 흰색은 세 가지의 색소를 혼합해야 합니다. + - 저장고의 양쪽 출력 중 왼쪽 출력이 가장 우선됩니다. + - 가능한 반복적으로 배치할 수 있는 일종의 연쇄 구조를 만들도록 하세요! 그만한 가치가 충분합니다! + - CTRL키를 누른 상태로 건물을 배치하여 여러 건물을 빠르게 배치할 수 있습니다. + - ALT키를 누른 상태로 벨트를 배치하면 벨트의 방향이 반전됩니다. + - 효율성이 핵심입니다! + - 허브에서 멀리 떨어질수록, 도형 패치의 형태가 더욱 복잡해집니다. + - 기계는 속도가 한정되어 있습니다. 최대 효율을 위해 자원을 분할하세요. + - 밸런서를 통해 효율성을 극대화시키세요. + - 구성이 중요합니다. 컨베이어 벨트가 서로 너무 교차되지 않도록 하세요. + - 미래를 계획하세요. 그렇지 않으면 크나큰 혼란을 겪을 수 있습니다! + - 굳이 오래된 공장을 철거하지는 마세요! 업그레이드를 하려면 이전의 도형도 필요합니다! + - 도움을 받기 전에, 혼자서 직접 레벨 20까지 클리어를 시도해보세요! + - 복잡하게 대신 단순하게, 그러면 멀리 나아갈 수 있을 겁니다. + - 나중에 지었던 공장을 재사용해야 할 때가 있을 겁니다. 언제나 공장을 재사용할 수 있도록 계획하세요. + - 간혹 굳이 절단하고 결합하지 않고도, 지도 곳곳에서 필요한 형태의 도형을 찾을 수도 있습니다. + - 온전한 모양의 풍차 모양 도형은 절대 자연적으로 생성되지 않습니다. + - 색소를 최대한 덜 사용하기 위해, 절단하기 전에 먼저 색칠기로 색칠하세요. + - 극한의 확장성을 가진 모듈 공장을 사용한다면 이 넓은 땅은 인간의 관심사에 있는 공간에 불과합니다. + - 별도의 청사진 공장을 만드세요. 언제나 확장성이 중요합니다. + - 혼합기를 잘 살펴보면, 그 질문에 대한 답을 얻을 수 있습니다. + - CTRL + 클릭을 사용하여 영역을 선택합니다. + - 공장을 허브에 가까이 지으면 나중에 거대한 프로젝트에 방해가 될 수 있습니다. + - 업그레이드 목록에 나타나는 도형 옆의 핀 아이콘을 누르면 화면에 고정됩니다. + - 세 가지의 기본 색상을 모두 섞어서 흰색을 만드세요! + - 당신에겐 무한한 땅이 있습니다. 굳이 공간을 적게 쓸 필요는 없으니, 맘껏 확장하세요! + - Factorio도 플레이 해보세요! 제가 가장 좋아하는 게임입니다. + - 4단 절단기는 오른쪽 상단부터 시계 방향으로 차례로 절단합니다. + - 메인 메뉴에서 세이브 파일을 다운로드 할 수 있습니다. + - 이 게임에는 유용한 조작법이 많습니다! 설정 페이지에서 확인해보세요. + - 이 게임에는 다양한 설정이 있습니다. 꼭 확인해 보세요! + - 허브의 마커에는 방향을 나타내는 작은 나침반이 있습니다! + - 벨트를 제거하고 싶다면 해당 영역을 잘라낸 다음, 같은 위치에 붙여 넣으세요. + - F4 키를 누르면 FPS와 틱 비율을 표시합니다. + - F4 키를 두번 누르면 마우스와 카메라의 타일을 표시합니다. + - 왼쪽에 고정된 도형을 클릭하여 고정을 해제할 수 있습니다. diff --git a/translations/base-lt.yaml b/translations/base-lt.yaml index 134105ff..910cb9f2 100644 --- a/translations/base-lt.yaml +++ b/translations/base-lt.yaml @@ -1,111 +1,63 @@ -# -# 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 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 combination of increasingly complex shapes within an infinite map. + discordLinkShort: Official Discord + intro: >- + Shapez.io is a relaxed game in which you have to build factories for the + automated production of geometric shapes. - # 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] + As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map. - 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. + And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! - 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]! + While you only process shapes at the beginning, you have to color them later - for this you have to extract and mix colors! - 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. + Buying the game on Steam gives you access to the full version, but you can also play a demo on shapez.io first and decide later! + title_advantages: Standalone Advantages + advantages: + - 12 New Level for a total of 26 levels + - 18 New Buildings for a fully automated factory! + - 20 Upgrade Tiers for many hours of fun! + - Wires Update for an entirely new dimension! + - Dark Mode! + - Unlimited Savegames + - Unlimited Markers + - Support me! ❤️ + title_future: Planned Content + planned: + - Blueprint Library (Standalone Exclusive) + - Steam Achievements + - Puzzle Mode + - Minimap + - Mods + - Sandbox mode + - ... and a lot more! + title_open_source: This game is open source! + title_links: Links + links: + discord: Official Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Help translate + text_open_source: >- + Anybody can contribute, I'm actively involved in the community and + attempt to review all suggestions and take feedback into consideration + where possible. - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! - global: loading: Loading error: Error - - # 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. + decimalSeparator: . suffix: thousands: k millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: inf - time: - # Used for formatting past time dates oneSecondAgo: one second ago xSecondsAgo: seconds ago oneMinuteAgo: one minute ago @@ -114,14 +66,10 @@ global: xHoursAgo: hours ago oneDayAgo: one day ago xDaysAgo: days ago - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s hoursAndMinutesShort: h m - xMinutes: minutes - keys: tab: TAB control: CTRL @@ -129,13 +77,9 @@ global: escape: ESC shift: SHIFT space: SPACE - 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! - + intro: Get the standalone to unlock all features! mainMenu: play: Play changelog: Changelog @@ -143,20 +87,15 @@ mainMenu: openSourceHint: This game is open source! discordLink: Official Discord Server helpTranslate: Help translate! - - # 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. - + 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 - - continue: Continue newGame: New Game madeBy: Made by subreddit: Reddit - + savegameUnnamed: Unnamed dialogs: buttons: ok: OK @@ -170,113 +109,103 @@ dialogs: viewUpdate: View Update showUpgrades: Show Upgrades showKeybindings: Show Keybindings - importSavegameError: title: Import Error - text: >- - Failed to import your savegame: - + text: "Failed to import your savegame:" importSavegameSuccess: title: Savegame Imported - text: >- - Your savegame has been successfully imported. - + text: Your savegame has been successfully imported. gameLoadFailure: title: Game is broken - text: >- - Failed to load your savegame: - + text: "Failed to load your savegame:" confirmSavegameDelete: title: Confirm deletion - text: >- - Are you sure you want to delete the game? - + text: Are you sure you want to delete the following game?

+ '' at level

This can not be + undone! savegameDeletionError: title: Failed to delete - text: >- - Failed to delete the savegame: - + text: "Failed to delete the savegame:" restartRequired: title: Restart required - text: >- - You need to restart the game to apply the settings. - + 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. - resetKeybindingsConfirmation: title: Reset keybindings desc: This will reset all keybindings to their default values. Please confirm. - keybindingsResetOk: title: Keybindings reset desc: The keybindings have been reset to their respective defaults! - 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 to get the standalone 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! updateSummary: title: New update! - desc: >- - Here are the changes since you last played: - + desc: "Here are the changes since you last played:" upgradesIntroduction: title: Unlock Upgrades - 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. - + 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 - desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? - + desc: You are deleting a lot of buildings ( to be exact)! Are you sure + you want to do this? blueprintsNotUnlocked: title: Not unlocked yet - desc: >- - Complete level 12 to unlock Blueprints! - + desc: Complete level 12 to unlock Blueprints! keybindingsIntroduction: title: Useful 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.
- + 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.
" 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) + 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: You can only create two custom markers in the demo. Get the standalone for unlimited markers! + 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 + 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! - + 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? - + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: Rename Savegame + desc: You can rename your savegame here. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Move selectBuildings: Select area @@ -297,18 +226,9 @@ ingame: clearSelection: Clear Selection pipette: Pipette switchLayers: Switch layers - - # 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. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - + hotkeyLabel: "Hotkey: " infoTexts: speed: Speed range: Range @@ -316,36 +236,21 @@ ingame: oneItemPerSecond: 1 item / second itemsPerSecond: items / s itemsPerSecondDouble: (x2) - 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 - - # Notifications on the lower right notifications: newUpgrade: A new upgrade is available! gameSaved: Your game has been saved. - - # The "Upgrades" window + freeplayLevelComplete: Level has been completed! shop: title: Upgrades buttonUnlock: Upgrade - - # Gets replaced to e.g. "Tier IX" tier: Tier - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXIMUM LEVEL (Speed x) - - # The "Statistics" window statistics: title: Statistics dataSources: @@ -354,55 +259,70 @@ ingame: description: Displaying amount of stored shapes in your central building. produced: title: Produced - description: Displaying all shapes your whole factory produces, including intermediate products. + description: Displaying all shapes your whole factory produces, including + intermediate products. delivered: title: Delivered 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 - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Playtime - buildingsPlaced: Buildings beltsPlaced: Belts - - buttons: - continue: Continue - settings: Settings - menu: Return to menu - - # Bottom left tutorial hints tutorialHints: title: Need help? showHint: Show hint hideHint: Close - - # When placing a blueprint blueprintPlacer: 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. + 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. - - # Interactive tutorial interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! - 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. - + 1_1_extractor: Place an extractor on top of a circle + shape to extract it! + 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." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." colors: red: Red green: Green @@ -417,8 +337,42 @@ ingame: title: Layers empty: Empty copyKey: Copy Key - -# All shop upgrades + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limited to + watermark: + title: Demo version + desc: Click here to see the Steam version advantages! + get_on_steam: Get on steam + standaloneAdvantages: + title: Get the full version! + no_thanks: No, thanks! + points: + levels: + title: 12 New Levels + desc: For a total of 26 levels! + buildings: + title: 18 New Buildings + desc: Fully automate your factory! + savegames: + title: ∞ Savegames + desc: As many as your heart desires! + upgrades: + title: 20 Upgrade Tiers + desc: This demo version has only 5! + markers: + title: ∞ Markers + desc: Never get lost in your factory! + wires: + title: Wires + desc: An entirely new dimension! + darkmode: + title: Dark Mode + desc: Stop hurting your eyes! + support: + title: Support me + desc: I develop it in my spare time! shopUpgrades: belt: name: Belts, Distributor & Tunnels @@ -432,281 +386,424 @@ shopUpgrades: painting: name: Mixing & Painting description: Speed x → x - -# Buildings and their name / description buildings: hub: deliver: Deliver toUnlock: to unlock levelShortcut: LVL - + endOfDemo: End of Demo belt: default: - name: &belt Conveyor Belt + name: Conveyor Belt description: Transports items, hold and drag to place multiple. - - miner: # Internal name for the Extractor + miner: default: - name: &miner Extractor + name: 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 + underground_belt: default: - name: &underground_belt Tunnel + name: 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! + name: 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 parts or it will stall! - + description: Cuts shapes into four parts. If you use only one part, be + sure to destroy the other parts or it will stall! rotater: default: - name: &rotater Rotate + name: Rotate description: Rotates shapes clockwise by 90 degrees. ccw: name: Rotate (CCW) description: Rotates shapes counter clockwise by 90 degrees. - + rotate180: + name: Rotate (180) + description: Rotates shapes by 180 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. - + name: 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 + name: 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 top input. + name: Painter + description: Colors the whole shape on the left input with the color from the + top input. double: name: Painter (Double) - description: Colors the shapes on the left inputs with the color from the top input. + 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. + description: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! mirrored: - name: *painter - description: *painter_desc - + name: Painter + description: Colors the whole shape on the left input with the color from the + top input. trash: default: - name: &trash Trash + name: 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. wire: default: name: Energy Wire description: Allows you to transport energy. - advanced_processor: + second: + name: Wire + description: Transfers signals, which can be items, colors or booleans (1 / 0). + Different colored wires do not connect. + balancer: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For - default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Merger (compact) + description: Merges two conveyor belts into one. + merger-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + storage: + default: + name: Storage + description: Stores excess items, up to a given capacity. Prioritizes the left + output and can be used as an overflow gate. + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: Switch + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means + shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. + (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means + shape, color or boolean "1") + transistor: + default: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + mirrored: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: Belt Reader + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: Virtual Cutter + description: Virtually cuts the shape into two halves. + rotater: + name: Virtual Rotater + description: Virtually rotates the shape, both clockwise and counter-clockwise. + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the + remaining ones to the left. + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the shape on + the right input. + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the + wires layer on the regular layer. 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, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! reward_rotater: title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. - + desc: The rotater has been unlocked! It rotates shapes + clockwise by 90 degrees. 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! - + 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!" reward_mixer: title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! - + desc: The mixer has been unlocked - Combine two colors using + additive blending with this building! 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! - + 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! 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!

- + desc: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! reward_tunnel: title: Tunnel - desc: The tunnel has been unlocked - You can now tunnel items through belts and buildings with it! - + desc: The tunnel has been unlocked - You can now tunnel items + through belts and buildings with it! 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 to + rotate counter clockwise! To build it, select the rotater and + press 'T' to cycle its variants! 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! - + desc: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" 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! - - 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! - + 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! 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! - + desc: You have unlocked a variant of the cutter - It allows you + to cut shapes in four parts instead of just two! 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! - - 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 works as + the regular painter but processes two shapes at + once consuming just one color instead of two! 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 the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! 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!) - + desc: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. 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). - - # Special reward, which is shown when there is no reward actually + 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). 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! - + 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: >- - Congratulations! By the way, more content is planned for the standalone! - + desc: Congratulations! By the way, more content is planned for the standalone! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: End of Demo + desc: You have reached the end of the demo version! settings: title: Settings categories: - game: Game - app: Application - + general: General + userInterface: User Interface + advanced: Advanced + performance: Performance versionBadges: dev: Development staging: Staging prod: Production buildDate: Built - labels: 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. + 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. scales: super_small: Super small small: Small regular: Regular large: Large huge: Huge - scrollWheelSensitivity: title: Zoom sensitivity - description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + 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 - language: title: Language - description: >- - Change the language. All translations are user contributed and might be incomplete! - + description: Change the language. All translations are user contributed and + might be incomplete! fullscreen: title: Fullscreen - description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. - + description: It is recommended to play the game in fullscreen to get the best + experience. Only available in the standalone. soundsMuted: title: Mute Sounds - description: >- - If enabled, mutes all sound effects. - + description: If enabled, mutes all sound effects. musicMuted: title: Mute Music - description: >- - If enabled, mutes all music. - + description: If enabled, mutes all music. theme: title: Game theme - description: >- - Choose the game theme (light / dark). + description: Choose the game theme (light / dark). themes: dark: Dark light: Light - refreshRate: title: Simulation Target - 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. - + 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: Multiplace - description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. - + description: If enabled, all buildings will stay selected after placement until + you cancel it. This is equivalent to holding SHIFT permanently. 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. - + 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. movementSpeed: title: Movement speed description: Changes how fast the view moves when using the keyboard. @@ -719,20 +816,17 @@ settings: 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. + description: When enabled, placing tunnels will automatically remove unnecessary + belts. This also enables 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. - + description: Enables the vignette which darkens the screen corners and makes + text easier to read. autosaveInterval: title: Autosave Interval - description: >- - Controls how often the game saves automatically. You can also disable it - entirely here. + description: Controls how often the game saves automatically. You can also + disable it entirely here. intervals: one_minute: 1 Minute two_minutes: 2 Minutes @@ -742,32 +836,77 @@ settings: disabled: Disabled compactBuildingInfo: title: Compact Building Infos - description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a - description and image is shown. + description: 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. - + 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. + 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. - + 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. + soundVolume: + title: Sound Volume + description: Set the volume for sound effects + musicVolume: + title: Music Volume + description: Set the volume for music + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: Keybindings - hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - + hint: "Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different + placement options." resetKeybindings: Reset Keybindings - categoryLabels: general: Application ingame: Game @@ -776,7 +915,6 @@ keybindings: massSelect: Mass Select buildings: Building Shortcuts placementModifiers: Placement Modifiers - mappings: confirm: Confirm back: Back @@ -785,38 +923,30 @@ keybindings: mapMoveDown: Move Down mapMoveLeft: Move Left centerMap: Center Map - mapZoomIn: Zoom in mapZoomOut: Zoom out createMarker: Create Marker - menuOpenShop: Upgrades menuOpenStats: Statistics - toggleHud: Toggle HUD toggleFPSInfo: Toggle FPS and Debug Info - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + belt: Conveyor Belt + underground_belt: Tunnel + miner: Extractor + cutter: Cutter + rotater: Rotate + stacker: Stacker + mixer: Color Mixer + painter: Painter + trash: Trash rotateWhilePlacing: Rotate - rotateInverseModifier: >- - Modifier: Rotate CCW instead + rotateInverseModifier: "Modifier: Rotate CCW instead" cycleBuildingVariants: Cycle Variants confirmMassDelete: Confirm Mass Delete cycleBuildings: Cycle Buildings - massSelectStart: Hold and drag to start massSelectSelectMultiple: Select multiple areas massSelectCopy: Copy area - placementDisableAutoOrientation: Disable automatic orientation placeMultiple: Stay in placement mode placeInverse: Invert automatic belt orientation @@ -829,33 +959,38 @@ keybindings: pipette: Pipette menuClose: Close Menu switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator wire: Energy Wire - + balancer: Balancer + storage: Storage + constant_signal: Constant Signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" 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.

- - Finally, huge thanks to my best friend Niklas - Without our - factorio sessions this game would never have existed. + 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. changelog: title: Changelog - demo: features: restoringGames: Restoring savegames @@ -863,5 +998,65 @@ demo: oneGameLimit: Limited to one savegame customizeKeybindings: Customizing Keybindings exportingBase: Exporting whole Base as Image - settingNotAvailable: Not available in the demo. +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-nl.yaml b/translations/base-nl.yaml index a082dc67..e43d6450 100644 --- a/translations/base-nl.yaml +++ b/translations/base-nl.yaml @@ -1,112 +1,65 @@ -# -# 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 is een spel dat draait om het bouwen van fabrieken voor het produceren en automatiseren van steeds complexere vormen in een oneindig groot speelveld. + 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. + discordLinkShort: Officiële Discord server + intro: >- + Shapez.io is een spel waarin je fabrieken moet bouwen voor de + automatische productie van geometrische vormen. - # 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] + Naarmate het spel vordert, worden de vormen complexer, en moet je uitbreiden in het oneindige speelveld. - 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. + En als dat nog niet genoeg is moet je ook nog eens steeds meer produceren om aan de vraag te kunnen voldoen. Het enige dat helpt is uitbreiden! - 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! - - 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. + Ondanks het feit dat je in het begin alleen vormen maakt, komt er het punt waarop je ze moet kleuren. Deze kleuren moet je vinden en mengen! - 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! - - 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 Voordelen[/b] - - [list] - [*] 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]Geplande Updates[/b] - - Ik update het spel regelmatig en probeer dit zeker eenmaal per week te doen! - - [list] - [*] 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]Dit spel is open source![/b] - - 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]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 met vertalen[/url] - [/list] - - discordLink: Officiële Discord - Chat met mij! + Door het spel op Steam te kopen kun je de volledige versie spelen. Je kunt echter ook een demo versie spelen op shapez.io en later beslissen + om over te schakelen zonder voortgang te verliezen. + title_advantages: Standalone Voordelen + advantages: + - 12 Nieuwe Levels met een totaal van 26 levels + - 18 Nieuwe Gebouwen voor een volledig geautomatiseerde fabriek! + - 20 Upgrade Levels voor vele speeluren! + - Draden Update voor een volledig nieuwe dimensie! + - Dark Mode Donkere modus! + - Oneindig veel werelden. + - Oneindig veel Markers + - Help mij! ❤️ + title_future: Geplande Content + planned: + - Blueprint Bibliotheek (Alleen volledige versie) + - Steam Prestaties + - Puzzel Modus + - Minimap + - Mods + - Sandbox modus + - ... en nog veel meer! + title_open_source: Dit spel is open source! + title_links: Links + links: + discord: Officiële Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Hulp met vertalen + text_open_source: >- + Iedereen mag meewerken. Ik ben actief betrokken in de community en + probeer alle suggesties en feedback te beoordelen als dat nodig is. + Zorg dat je ook mijn trello board bekijkt voor de volledige roadmap! global: loading: Laden - error: Error - - # 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" + error: Fout + thousandsDivider: . 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: inf - + infinite: ∞ time: - # Used for formatting past time dates - oneSecondAgo: één seconde geleden + oneSecondAgo: een seconde geleden xSecondsAgo: seconden geleden oneMinuteAgo: een minuut geleden xMinutesAgo: minuten geleden @@ -114,14 +67,10 @@ global: xHoursAgo: uren geleden oneDayAgo: een dag geleden xDaysAgo: dagen geleden - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s hoursAndMinutesShort: u m - xMinutes: minuten - keys: tab: TAB control: CTRL @@ -129,34 +78,25 @@ global: escape: ESC shift: SHIFT space: SPATIE - demoBanners: - # This is the "advertisement" shown in the main menu and other various places title: Demoversie - intro: >- - Koop de standalone om alle functies te ontgrendelen! - + intro: Koop de standalone om alle functies te ontgrendelen! mainMenu: play: Spelen changelog: Changelog importSavegame: Importeren openSourceHint: Dit spel is open source! - discordLink: Officiële discord-server (Engelstalig) - helpTranslate: Help met vertalen! - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - Sorry, maar dit spel draait langzaam in je huidige browser! Koop de standalone versie of download chrome voor de volledige ervaring. - + discordLink: Officiële Discord-server (Engelstalig) + helpTranslate: Help ons met vertalen! + browserWarning: Sorry, maar dit spel draait langzaam in je huidige browser! Koop + de standalone versie of download chrome voor de volledige ervaring. savegameLevel: Level savegameLevelUnknown: Onbekend Level - - - continue: Verder + continue: Ga verder newGame: Nieuw Spel madeBy: Gemaakt door subreddit: Reddit - + savegameUnnamed: Unnamed dialogs: buttons: ok: OK @@ -170,111 +110,109 @@ dialogs: viewUpdate: Zie Update showUpgrades: Zie Upgrades showKeybindings: Zie Sneltoetsen - importSavegameError: - title: Importeer error - text: >- - Het importeren van je savegame is mislukt: - + title: Importeerfout + text: "Het importeren van je savegame is mislukt:" importSavegameSuccess: title: Savegame geïmporteerd - text: >- - Je savegame is succesvol geïmporteerd. - + text: Je savegame is succesvol geïmporteerd. gameLoadFailure: title: Het spel is kapot - text: >- - Het laden van je savegame is mislukt: - + text: "Het laden van je savegame is mislukt:" confirmSavegameDelete: - title: Bevestig verwijderen - text: >- - Weet je zeker dat je het spel wil verwijderen? - + title: Bevestig het verwijderen + text: Ben je zeker dat je het volgende spel wil verwijderen?

+ '' op niveau

Dit kan niet ongedaan worden + gemaakt! savegameDeletionError: title: Verwijderen mislukt - text: >- - Het verwijderen van de savegame is mislukt: - + text: "Het verwijderen van de savegame is mislukt:" restartRequired: title: Opnieuw opstarten vereist - text: >- - Je moet het spel opnieuw opstarten om de instellingen toe te passen. - + text: Je moet het spel opnieuw opstarten om de instellingen toe te passen. editKeybinding: title: Verander sneltoetsen - desc: Druk op de toets of muisknop die je aan deze functie toe wil wijzen, of druk op ESC om te annuleren. - + desc: Druk op de toets of muisknop die je aan deze functie toe wil wijzen, of + druk op ESC om te annuleren. resetKeybindingsConfirmation: title: Reset sneltoetsen - desc: Dit reset al je sneltoetsen naar de standaardinstellingen. Wil je dit bevestigen? - + desc: Dit reset al je sneltoetsen naar de standaardinstellingen. Wil je dit + bevestigen? keybindingsResetOk: title: Sneltoetsen gereset desc: De sneltoetsen zijn gereset naar hun originele instellingen! - featureRestriction: title: Demoversie - desc: Je probeerde een functie te gebruiken () die niet beschikbaar is in de demo. Overweeg om de standalone te kopen voor de volledige ervaring! - + desc: Je probeerde een functie te gebruiken () die niet beschikbaar is + in de demo. Overweeg om de standalone te kopen voor de volledige + ervaring! oneSavegameLimit: title: Gelimiteerd aantal savegames - desc: Je kunt maar één savegame tegelijk hebben in de demoversie. Verwijder de bestaande savegame of koop de standalone! - + desc: Je kunt maar één savegame tegelijk hebben in de demoversie. Verwijder de + bestaande savegame of koop de standalone! updateSummary: title: Nieuwe update! - desc: >- - Dit zijn de veranderingen sinds je voor het laatst gespeeld hebt: - + desc: "Dit zijn de veranderingen sinds je voor het laatst gespeeld hebt:" upgradesIntroduction: title: Ontgrendel upgrades - desc: >- - Alle vormen die je produceert kunnen gebruikt worden om upgrades te ontgrendelen - vernietig je oude fabrieken niet! + 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. - massDeleteConfirm: title: Bevestig verwijderen - desc: >- - Je bent veel gebouwen aan het verwijderen ( om precies te zijn)! Weet je zeker dat je dit wil doen? - + desc: Je bent veel gebouwen aan het verwijderen ( om precies te zijn)! + Weet je zeker dat je dit wil doen? blueprintsNotUnlocked: title: Nog niet ontgrendeld - desc: >- - Blauwdrukken zijn nog niet ontgrendeld! Voltooi meer levels om ze te ontgrendelen. - + desc: Blauwdrukken zijn nog niet ontgrendeld! Voltooi meer levels om ze te + ontgrendelen. keybindingsIntroduction: title: Nuttige sneltoetsen - desc: >- - Dit spel heeft veel sneltoetsen die het makkelijker maken om grote fabrieken te bouwen. - Hier zijn er een aantal, maar zorg dat je kijkt naar de sneltoetsen!

- CTRL + slepen: selecteer een gebied om te kopiëren / verwijderen.
- SHIFT: Houd ingedrukt om meerdere van het zelfde gebouw te plaatsen.
- ALT: Houd ingedrukt om de richting van lopende banden om te draaien wanneer je ze plaatst.
- + desc: "Dit spel heeft veel sneltoetsen die het makkelijker maken om grote + fabrieken te bouwen. Hier zijn er een aantal, maar zorg dat je + kijkt naar de sneltoetsen!

CTRL + slepen: selecteer een gebied om te + kopiëren / verwijderen.
SHIFT: + Houd ingedrukt om meerdere van het zelfde gebouw te plaatsen.
+ ALT: Houd ingedrukt om de richting + van lopende banden om te draaien wanneer je ze plaatst.
" createMarker: title: Nieuwe markering - desc: Geef het een betekenisvolle naam. Je kunt ook een icoontje van een vorm toevoegen (die je hier kunt maken) - titleEdit: Edit Marker - + desc: Geef het een nuttige naam, Je kan ook een snel + toets van een vorm gebruiken (die je here kan genereren). + titleEdit: Bewerk markering markerDemoLimit: - desc: Je kunt maar twee markeringen plaatsen in de demo. Koop de standalone voor een ongelimiteerde hoeveelheid markeringen! + desc: Je kunt maar twee markeringen plaatsen in de demo. Koop de standalone voor + een ongelimiteerde hoeveelheid markeringen! massCutConfirm: title: Bevestig knippen - desc: >- - Je bent veel gebouwen aan het knippen ( om precies te zijn)! Weet je zeker dat je dit wil doen? - + desc: Je bent veel gebouwen aan het knippen ( om precies te zijn)! Weet + je zeker dat je dit wil doen? exportScreenshotWarning: title: Exporteer screenshot - desc: >- - 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! - + desc: 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: Bevestig knippen - desc: Je kunt het je niet veroorloven om de selectie te plakken! Weet je zeker dat je het wil knippen? - + desc: Je kunt het je niet veroorloven om de selectie te plakken! Weet je zeker + dat je het wil knippen? + editSignal: + title: Stel het signaal in. + descItems: "Kies een ingesteld item:" + descShortKey: ... of voer de hotkey in van een vorm (Die je + hier kunt vinden). + renameSavegame: + title: Hernoem opgeslagen spel + desc: Geef je opgeslagen spel een nieuwe naam. + tutorialVideoAvailable: + title: Tutorial Beschikbaar + desc: Er is een tutorial video beschikbaar voor dit level! Zou je het willen bekijken? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: Er is een tutorial beschikbaar voor dit level, maar het is alleen + beschikbaar in het Engels. Zou je het toch graag kijken? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Beweeg speelveld selectBuildings: Selecteer gebied @@ -287,7 +225,7 @@ ingame: placeBuilding: Plaats gebouw createMarker: Plaats markering delete: Vernietig - pasteLastBlueprint: Plak laatst gekopiëerde blauwdruk + pasteLastBlueprint: Plak laatst gekopieerde blauwdruk lockBeltDirection: Gebruik lopende band planner plannerSwitchSide: Draai de richting van de planner cutSelection: Knip @@ -295,55 +233,31 @@ ingame: clearSelection: Annuleer selectie pipette: Pipet switchLayers: Wissel lagen - - # 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: Druk op om tussen varianten te wisselen. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - + hotkeyLabel: "Hotkey: " infoTexts: speed: Snelheid range: Bereik storage: Opslag - oneItemPerSecond: 1 voorwerp / s - itemsPerSecond: voorwerpen / s + oneItemPerSecond: 1 voorwerp/s + itemsPerSecond: voorwerpen/s itemsPerSecondDouble: (x2) - tiles: tegels - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Level completed: Voltooid - unlockText: Ontgrendeld ! + unlockText: ontgrendeld! buttonNextLevel: Volgende Level - - # Notifications on the lower right notifications: newUpgrade: Er is een nieuwe upgrade beschikbaar! gameSaved: Je spel is opgeslagen. - - # The "Upgrades" window + freeplayLevelComplete: Level is voltooid! shop: title: Upgrades buttonUnlock: Upgrade - - # Gets replaced to e.g. "Tier IX" tier: Niveau - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXIMAAL NIVEAU (Snelheid x) - - # The "Statistics" window statistics: title: Statistieken dataSources: @@ -352,55 +266,71 @@ ingame: 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. + description: Geeft alle vormen weer die op dit moment geproduceerd worden, + inclusief tussenproducten. delivered: title: Geleverd description: Geeft alle vormen weer die in de HUB worden bezorgd. noShapesProduced: Er zijn nog geen vormen geproduceerd. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: /s + minute: /m + hour: /h settingsMenu: playtime: Speeltijd - buildingsPlaced: Gebouwen beltsPlaced: Lopende banden - - buttons: - continue: Verder spelen - settings: Opties - menu: Terug naar het Menu - - # Bottom left tutorial hints tutorialHints: title: Hulp nodig? showHint: Zie hint hideHint: Sluit - - # When placing a blueprint blueprintPlacer: cost: Prijs - - # Map markers waypoints: waypoints: Markeringen hub: HUB - description: Klik met de linkermuisknop op een markering om hier naartoe te gaan, klik met de rechtermuisknop om de markering te verwijderen.

Druk op om een markering te maken in het huidige zicht, of rechtermuisknop om een markering te maken bij het geselecteerde gebied. + description: Klik met de linkermuisknop op een markering om hier naartoe te + gaan, klik met de rechtermuisknop om de markering te + verwijderen.

Druk op om een markering te maken + in het huidige zicht, of rechtermuisknop om een + markering te maken bij het geselecteerde gebied. creationSuccessNotification: Markering is gemaakt. - - # Interactive tutorial interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Plaats een ontginner op een cirkelvorm om deze te onttrekken! - 1_2_conveyor: >- - Verbind de ontginner met een lopende band aan je hub!

Tip: Klik en sleep de lopende band met je muis! - - 1_3_expand: >- - Dit is GEEN nietsdoen-spel! bouw meer ontginners en lopende banden om het doel sneller te behalen.

Tip: Houd SHIFT ingedrukt om meerdere ontginners te plaatsen en gebruik R om ze te draaien. - + 1_1_extractor: Plaats een ontginner op een + cirkelvorm om deze te onttrekken! + 1_2_conveyor: "Verbind de ontginner met een lopende band aan je + hub!

Tip: Klik en sleep de lopende band + met je muis!" + 1_3_expand: "Dit is GEEN nietsdoen-spel! Bouw meer ontginners + en lopende banden om het doel sneller te behalen.

Tip: + Houd SHIFT ingedrukt om meerdere ontginners te + plaatsen en gebruik R om ze te draaien." + 2_1_place_cutter: "Plaats nu een Knipper om de cirkels in twee te knippen + halves!

PS: De knipper knipt altijd van boven naar + onder ongeacht zijn oriëntatie." + 2_2_place_trash: De knipper kan vormen verstoppen en bijhouden!

Gebruik een + vuilbak om van het (!) niet + nodige afval vanaf te geraken. + 2_3_more_cutters: "Goed gedaan! Plaats nu 2 extra knippers om dit traag + process te versnellen!

PS: Gebruik de 0-9 + sneltoetsen om gebouwen sneller te selecteren." + 3_1_rectangles: "Laten we nu rechthoeken ontginnen! Bouw 4 + ontginners en verbind ze met de lever.

PS: + Houd SHIFT Ingedrukt terwijl je lopende banden plaats + om ze te plannen!" + 21_1_place_quad_painter: Plaats de quad painter en krijg een paar + cirkels in witte en + rode kleur! + 21_2_switch_to_wires: Schakel naar de draden laag door te duwen op + E!

verbind daarna alle + inputs van de verver met kabels! + 21_3_place_button: Mooi! Plaats nu een schakelaar en verbind het + met draden! + 21_4_press_button: "Druk op de schakelaar om het een Juist signaal door + te geven en de verver te activeren.

PS: Je + moet niet alle inputs verbinden! Probeer er eens 2." colors: red: Rood green: Groen @@ -414,9 +344,43 @@ ingame: shapeViewer: title: Lagen empty: Leeg - copyKey: Kopiëer sleutel - -# All shop upgrades + copyKey: Kopieer sleutel + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: "Gelimiteerd tot: " + watermark: + title: Demo versie + desc: Klik hier om het spel op Steam te bekijken! + get_on_steam: Krijg het op Steam + standaloneAdvantages: + title: Koop de volledige versie! + no_thanks: Nee, bedankt! + points: + levels: + title: 12 Nieuwe Levels + desc: Voor een totaal van 26 levels! + buildings: + title: 18 Nieuwe Gebouwen + desc: Automatiseer je fabrieken! + savegames: + title: ∞ Savegames + desc: Zo veel je maar wilt! + upgrades: + title: 20 Upgrade Levels + desc: Deze demo heeft er enkel 5! + markers: + title: ∞ Markeringen + desc: Verdwaal nooit meer in je fabriek! + wires: + title: Kabels + desc: Een volledig nieuwe dimensie! + darkmode: + title: Dark Mode + desc: Minder vervelend voor je ogen! + support: + title: Help mij + desc: Ik maak dit spel in mijn vrije tijd! shopUpgrades: belt: name: Banden, Verdeler & Tunnels @@ -430,285 +394,435 @@ shopUpgrades: painting: name: Mengen en verven description: Snelheid x → x - -# Buildings and their name / description buildings: belt: default: - name: &belt Lopende Band + name: Lopende Band description: Transporteert voorwerpen, klik en sleep om meerdere te plaatsen. - - miner: # Internal name for the Extractor + miner: default: - name: &miner Ontginner + name: Ontginner description: Plaats op een vorm of kleur om deze te onttrekken. - chainable: name: Ontginner (Ketting) - description: Plaats op een vorm of kleur om deze te onttrekken. Kan achter elkaar worden geplaatst. - - underground_belt: # Internal name for the Tunnel + description: Plaats op een vorm of kleur om deze te onttrekken. Kan achter + elkaar worden geplaatst. + underground_belt: default: - name: &underground_belt Tunnel + name: Tunnel description: Laat voorwerpen onder gebouwen en lopende banden door lopen. - tier2: name: Tunnel Niveau II description: Laat voorwerpen onder gebouwen en lopende banden door lopen. - - splitter: # Internal name for the Balancer - default: - name: &splitter Verdeler - description: Multifunctioneel - Verdeelt alle input gelijk over alle output. - - compact: - name: Invoeger (compact) - description: Voegt twee lopende banden samen tot één. - - compact-inverse: - name: Invoeger (compact) - description: Voegt twee lopende banden samen tot één. - cutter: default: - name: &cutter Knipper - description: Knipt vormen van boven naar onder en geeft beiden helften als output. Als je maar één helft gebruikt, zorg dat je de andere helft vernietigt, anders loopt de machine vast! + name: Knipper + description: Knipt vormen van boven naar onder en geeft beiden helften als + output. Als je maar één helft gebruikt, zorg dat je de + andere helft vernietigt, anders loopt de machine vast! quad: name: Knipper (Quad) - description: Knipt vormen in vier delen. Als je maar één deel gebruikt, zorg dat je de andere delen vernietigt, anders loopt de machine vast! - + description: Knipt vormen in vier delen. Als je maar één deel gebruikt, + zorg dat je de andere delen vernietigt, anders loopt de machine + vast! rotater: default: - name: &rotater Roteerder + name: Roteerder description: Draait vormen 90 graden met de klok mee. ccw: - name: Roteerder (andersom) + name: Roteerder (omgekeerd) description: Draait vormen 90 graden tegen de klok in. - + rotate180: + name: Roteerder (180°) + description: Draait vormen 180 graden. stacker: default: - name: &stacker Stapelaar - description: Stapelt twee vormen. Als ze niet samengevoegd kunnen worden, wordt het rechtervoorwerp boven op het linker geplaatst. - + name: Stapelaar + description: Stapelt twee vormen. Als ze niet samengevoegd kunnen worden, wordt + het rechtervoorwerp boven op het linker geplaatst. mixer: default: - name: &mixer Kleurenmenger + name: Kleurenmenger description: Mengt twee kleuren met behulp van additieve kleurmenging. - painter: default: - name: &painter Verver - description: &painter_desc Verft de volledige vorm in de linker input met de kleur van de rechter input. + name: Verver + description: 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 input 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. + description: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! mirrored: - name: *painter - description: *painter_desc - + name: Verver + description: Verft de volledige vorm in de linker input met de kleur van de + rechter input. trash: default: - name: &trash Vuilnisbak + name: Vuilnisbak description: Accepteert input van alle kanten en vernietigt het. Voor altijd. - - storage: - name: Opslag - description: Slaat het overschot aan voorwerpen op, tot een zekere hoeveelheid. Kan worden gebruikt als buffer. - hub: - deliver: Lever + deliver: Lever in toUnlock: om te ontgrendelen levelShortcut: LVL + endOfDemo: End of Demo wire: default: name: Energiekabel description: Voor transport van energie. - advanced_processor: + second: + name: Kabel + description: Vervoerd signalen, zoals items, kleuren of booleans (1 of 0). + Verschillende kleuren kabels kunnen niet verbonden worden. + balancer: default: - name: Kleur-omkeerder - description: Keert de kleur om van een voorwerp. - energy_generator: - deliver: Lever - toGenerateEnergy: Voor - default: - name: Energiegenerator - description: Wekt energie op door vormen te consumeren. - wire_crossings: - default: - name: Kabelsplijter - description: Splijt één kabel in twee. + name: Balanceerder + description: Multifunctioneel - Verdeel alle invoeren over alle uitvoeren. merger: - name: Kabelvoeger - description: Voegt twee kabels samen tot één. - + name: Samenvoeger (compact) + description: Voeg 2 lopende banden samen. + merger-inverse: + name: Samenvoeger + description: Voeg 2 lopende banden samen. + splitter: + name: Splitser (compact) + description: Splits een lopende band in tweeën. + splitter-inverse: + name: Splitser + description: Splits een lopende band in tweeën. + storage: + default: + name: Opslag + description: Slaat teveel aan items of kleuren op. De linker uitvoer heeft de + voorkeur. + wire_tunnel: + default: + name: Kabel kruising + description: Kruis 2 kabels zonder ze te koppelen + constant_signal: + default: + name: Constant Signaal + description: Zend een constant signaal, dit kan een vorm, kleur of boolean (1 / + 0) zijn. + lever: + default: + name: Schakelaar + description: Zend een 1 of een 0 uit afhankelijk van de stand. + logic_gate: + default: + name: AND poort + description: Zend een 1 uit als beide invoeren hetzelfde zijn. (Kan een vorm, + kleur of boolean (1/0) zijn) + not: + name: NOT poort + description: Zend een 1 uit als de invoer een 0 is. + xor: + name: XOR poort + description: Zend een 1 uit als de invoeren niet hetzelfde zijn. (Kan een vorm, + kleur of boolean (1/0) zijn) + or: + name: OR poort + description: Zend een 1 uit als de invoeren wel of niet hetzelfde zijn, maar + niet uit zijn. (Kan een vorm, kleur of boolean (1/0) zijn) + transistor: + default: + name: Transistor + description: Geeft het signaal van onder door als de zijkant 1 is. + mirrored: + name: Transistor + description: Geeft het signaal van onder door als de zijkant 1 is. + filter: + default: + name: Filter + description: Stuurt alle items van de ingestelde soort naar boven en de rest + naar rechts. + display: + default: + name: Scherm + description: Verbind een signaal met het scherm om de soort weer te geven. Kan + een vorm, kleur of boolean (1/0) zijn. + reader: + default: + name: Lopende band lezer + description: Meet de gemiddelde doorvoer op de band. Geeft het laatste gelezen + item door aan de kabel. + analyzer: + default: + name: Vorm Analyse + description: Analiseerd de onderste laag rechts boven en geeft de kleur en vorm + door aan de kabel. + comparator: + default: + name: Vergelijker + description: Zend 1 uit als beiden invoeren gelijk zijn, kunnen vormen, kleuren + of booleans (1/0) zijn + virtual_processor: + default: + name: Virtuele Snijder + description: Snijdt de vorm virtueel in twee helften. + rotater: + name: Virtuele Draaier + description: Draait de vorm virtueel met de klok mee en tegen de klok in. + unstacker: + name: Virtuele Ontstapelaar + description: Geeft de bovenste laag door aan de rechter uitvoer en de rest aan + de linker uitvoer. + stacker: + name: Virtuele Stapelaar + description: Stapelt de rechter vorm virtueel op de linkervorm. + painter: + name: Virtuele Schilder + description: Schildert de vorm virtueel vanaf de onderste invoer met de vorm aan + de rechter ingang. + item_producer: + default: + name: Item Producent + description: Alleen beschikbaar in sandbox-modus, geeft het gegeven signaal van + de kabel laag op de reguliere laag. storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Vormen Knippen - desc: Je hebt de knipper ontgrendeld - Deze knipt vormen half van boven naar onder ongeacht de oriëntatie!

Zorg dat je ongebruikte vormen weggooit, anders loopt het vast - Dit is waarom ik je een vuilnisbak heb gegeven, die alles wat er in komt vernietigt! - + desc: Je hebt juist de knipper ontgrendeld, die vormen in de helft + kan knippen van boven naar onder ongeacht zijn rotatie + !

Wees zeker dat je het afval weggooit, want + anders zal het vastlopen - Voor deze reden + heb ik je de vuilbak gegeven, die alles + vernietigd wat je erin laat stromen! reward_rotater: title: Roteren - desc: De roteerder is ontgrendeld - Het draait vormen 90 graden met de klok mee. - + desc: De roteerder is ontgrendeld - Het draait vormen 90 graden + met de klok mee. reward_painter: title: Verven - desc: >- - De verver is ontgrendeld - Onttrek wat kleur (op dezelfde manier hoe je vormen onttrekt) en combineer het met een vorm in de verver om ze te kleuren!

PS: Als je kleurenblind bent, is er een kleurenblindmodus in de instellingen! - + desc: "De verver is ontgrendeld - Onttrek wat kleur (op + dezelfde manier hoe je vormen onttrekt) en combineer het met een + vorm in de verver om ze te kleuren!

PS: Als je kleurenblind + bent, is er een kleurenblindmodus in de + instellingen!" reward_mixer: title: Kleuren mengen - desc: De menger is ontgrendeld - Gebruik dit gebouw om twee kleuren te mengen met behulp van additieve kleurmenging! - + desc: De menger is ontgrendeld - Gebruik dit gebouw om twee + kleuren te mengen met behulp van additieve + kleurmenging! reward_stacker: title: Stapelaar - desc: Je kunt nu vormen combineren met de stapelaar! De inputs worden gecombineerd en als ze naast elkaar passen worden ze samengevoegd. Als ze niet samengevoegd kunnen worden dan wordt het rechtervoorwerp boven op het linker geplaatst! - + desc: Je kunt nu vormen combineren met de stapelaar! De inputs + worden gecombineerd en als ze naast elkaar passen worden ze + samengevoegd. Als ze niet samengevoegd kunnen + worden dan wordt het rechtervoorwerp boven op het + linker geplaatst! reward_splitter: - title: Splitter/samenvoeger - desc: De multifunctionele verdeler is ontgrendeld - Het kan worden gebruikt om grotere fabrieken te bouwen door voorwerpen samen te voegen of te verdelen over meerdere lopende banden!

- + title: Splitser/samenvoeger + desc: Je hebt de splitser ontgrendeld, een variant van de + samenvoeger - Het accepteert 1 input en verdeelt het + in 2! reward_tunnel: title: Tunnel - desc: De tunnel is ontgrendeld - Je kunt nu voorwerpen onder gebouwen en lopende banden door laten lopen. - + desc: De tunnel is ontgrendeld - Je kunt nu voorwerpen onder + gebouwen en lopende banden door laten lopen. reward_rotater_ccw: title: Roteren (andersom) - desc: Je hebt een variant van de roteerder ontgrendeld - Het roteert voorwerpen tegen de klok in! Om het te bouwen selecteer je de roteerder en druk je op 'T' om tussen varianten te wisselen! - + desc: Je hebt een variant van de roteerder ontgrendeld - Het + roteert voorwerpen tegen de klok in! Om het te bouwen selecteer je + de roteerder en druk je op 'T' om tussen varianten te + wisselen! reward_miner_chainable: title: Ketting-ontginner - desc: Je hebt de Ketting-ontginner ontgrendeld! Deze kan grondstoffen doorsturen naar andere ontginners, waardoor je efficiënter grondstoffen kan onttrekken! - + desc: "Je hebt de Ketting-ontginner ontgrendeld! Het kan + zijn materialen ontginnen via andere ontginners zodat je + meer materialen tegelijkertijd kan ontginnen!

PS: De oude + ontginner is vervangen in je toolbar!" reward_underground_belt_tier_2: title: Tunnel Niveau II - desc: Je hebt een variant van de tunnel ontgrendeld - Deze heeft een grotere reikwijdte- - Je hebt een compacte variant van de verdeler ontgrendeld - Dit voegt twee lopende banden samen tot één. - + desc: Je hebt een nieuwe variant van de tunnel ontgrendeld. - Het heeft een + groter bereik, en je kan nu ook die tunnels mixen + over en onder elkaar! reward_cutter_quad: title: Quad Knippen - desc: Je hebt een variant van de knipper ontgrendeld - Dit knipt vormen in vier stukken in plaats van twee! - + desc: Je hebt een variant van de knipper ontgrendeld - Dit + knipt vormen in vier stukken in plaats van twee! reward_painter_double: title: Dubbel verven - desc: Je hebt een variant van de verver ontgrendeld - Het werkt als de gewone verver, maar verft twee vormen tegelijk met één kleur in plaats van twee! - - reward_painter_quad: - title: Quad verven - desc: Je hebt een variant van de verver ontgrendeld - Het verft elk kwadrant van de vorm een andere kleur! - + desc: Je hebt een variant van de verver ontgrendeld - Het werkt + als de gewone verver, maar verft twee vormen + tegelijk met één kleur in plaats van twee! reward_storage: title: Opslagbuffer - desc: Je hebt een variant van de vuilnisbak ontgrendeld - Het slaat voorwerpen op tot een zekere hoeveelheid! - + desc: Je hebt een variant van de opslag ontgrendeld - Het laat je toe om + vormen op te slagen tot een bepaalde capaciteit!

Het verkiest de linkse + output, dus je kan het altijd gebruiken als een overloop poort! reward_freeplay: title: Vrij spel - desc: Het is gelukt! je hebt het vrije spel ontgrendeld! Dit betekent dat gevraagde vormen vanaf nu willekeurig gegenereerd worden! (Geen zorgen, het spel wordt in de toekomst nog verder uitgebreid in de standalone!) - + desc: Je hebt het gedaan! Je hebt de free-play modus ontgrendeld! Dit betekend + dat vormen nu willekeurig gegenereerd worden!

+ Omdat de hub vanaf nu een bepaald aantal vormen per seconden nodig heeft, + Raad ik echt aan een machine te maken die automatisch + de juiste vormen genereert!

De HUB geeft de vorm die je nodig hebt + op de tweede laag met draden, dus alles wat je moet doen is dat analyseren + en je fabriek dat automatisch laten maken op basis van dat. reward_blueprints: title: Blauwdrukken - desc: Je kunt nu delen van je fabriek kopiëren en plakken! Selecteer een gebied (Houd CTRL ingedrukt en sleep dan met je muis) en druk op 'C' om het geselecteerde gebied te kopiëren.

Plakken is niet gratis, je hebt er blauwdruk-vormen voor nodig! (De vorm die je net ingeleverd hebt). - - # Special reward, which is shown when there is no reward actually + desc: Je kunt nu delen van je fabriek kopiëren en plakken! + Selecteer een gebied (Houd CTRL ingedrukt en sleep dan met je muis) + en druk op 'C' om het geselecteerde gebied te + kopiëren.

Plakken is niet gratis, je hebt er + blauwdruk-vormen voor nodig! (De vorm die je net + ingeleverd hebt). no_reward: title: Volgende level - desc: >- - Je hebt niks nieuws ontgrendeld met dit level, maar bij de volgende zal er weer iets nieuws zijn!

PS: Maak je fabrieken niet kapot - Je hebt al deze vormen later nog nodig om upgrades te ontgrendelen! - + desc: "Je hebt niks nieuws ontgrendeld met dit level, maar bij de volgende zal + er weer iets nieuws zijn!

PS: Maak je fabrieken niet kapot + - Je hebt al deze vormen later nog nodig om + upgrades te ontgrendelen!" no_reward_freeplay: title: Volgende level - desc: >- - Gefeliciteerd! Even tussendoor, het spel wordt in de toekomst nog verder uitgebereid in de standalone! - + desc: Gefeliciteerd! Even tussendoor, het spel wordt in de toekomst nog verder + uitgebereid in de standalone! + reward_balancer: + title: Verdeler + desc: De multifunctionele verdeler is nu ontgrendeld - Het kan + gebruikt worden om grotere te knippen en plakken vormen op meerdere + lopende banden te zetten + reward_merger: + title: Compacte samenvoeger + desc: Je hebt een variant op de samenvoeger van de + verdeler vrijgespeeld - Dit gebouw maakt van 2 + lopende banden 1! + reward_belt_reader: + title: Lopende band lezer + desc: Je hebt de lopende band lezer vrijgespeeld! Dit gebouw + geeft de doorvoer op een lopende band weer.

Wacht maar tot je + kabels vrijspeeld, dan wordt het pas echt interessant! + reward_rotater_180: + title: Draaier (180 graden) + desc: Je hebt de 180 graden draaier vrijgespeeld! - Hiermee kun + je een item op de band 180 graden draaien! + reward_display: + title: Scherm + desc: "Je hebt het scherm ontgrendeld - Verbind een signaal met de + laag van draden om het te visualiseren!

PS: Heb je gezien dat de lopende band + lezer en opslag hun laatste vorm weergeven? Probeer het te tonen op + een scherm!" + reward_constant_signal: + title: Constante Signaal + desc: Je hebt het constante signaal vrijgespeeld op de kabel + dimensie! Dit gebouw is handig in samenwerking met item + filters.

Het constante signaal kan een + vorm, kleur of + boolean (1/0) zijn. + reward_logic_gates: + title: Logische poorten + desc: Je hebt de logische poorten vrijgespeeld! Misschien word + je hier nog niet zo vrolijk van, maar eigenlijk zijn ze heel erg + handig!

Met logische poorten kun je AND, OR en XOR operaties + uitvoeren.

Als bonus krijg je ook nog een + transistor van mij! + reward_virtual_processing: + title: VIrtuele verwerking + desc: Ik heb juist een hele hoop nieuwe gebouwen toegevoegd die je toetstaan om + het process van vormen te stimuleren!

Je kan + nu de knipper, draaier, stapelaar en meer op de dradenlaag stimuleren! + Met dit heb je nu 3 opties om verder te gaan met het spel:

- + Bouw een automatische fabriek om eender welke mogelijke + vorm te maken gebraagd door de HUB (Ik raad aan dit te proberen!).

- Bouw + iets cool met draden.

- Ga verder met normaal + spelen.

Wat je ook kiest, onthoud dat je plezier hoort te hebben! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "Je hebt juist de draden laag ontgrendeld: Het is een aparte + laag boven op de huidige laag en introduceert heel veel nieuwe + manieren om te spelen!

Voor het begin heb ik voor jou de Quad + Painter ontgrendeld - Verbind de gleuf waarin je wilt verven op + de draden laag!

Om over te schakelen naar de draden laag, Duw op + E.

PS: Zet hints aan in + de instellingen om de draden tutorial te activeren!" + reward_filter: + title: Item Filter + desc: Je hebt de Item Filter vrijgespeeld! Items worden naar + rechts of naar boven gestuurd, afhankelijk van de invoer.

Er + kan ook een boolean (1/0) worden ingevoerd om de filter in en uit + te schakelen. + reward_demo_end: + title: Einde van de Demo + desc: Je hebt het einde van de demoversie bereikt! settings: title: Opties categories: - game: Spel - app: Applicatie - + general: Algemeen + userInterface: Opmaak + advanced: Geavanceerd + performance: Prestatie versionBadges: dev: Ontwikkeling - staging: Staging + staging: Positie prod: Productie buildDate: gebouwd - labels: uiScale: title: Interface-schaal - description: >- - Veranderd de grootte van de gebruikersinterface. De interface schaalt nog steeds gebaseerd op de resolutie van je apparaat, maar deze optie heeft invloed op de hoeveelheid schaling. + description: Veranderd de grootte van de gebruikersinterface. De interface + schaalt nog steeds gebaseerd op de resolutie van je apparaat, + maar deze optie heeft invloed op de hoeveelheid schaling. scales: super_small: Zeer klein small: Klein regular: Middel large: Groot huge: Jumbo - scrollWheelSensitivity: title: Zoom-gevoeligheid - description: >- - Veranderd hoe gevoelig het zoomen is (muiswiel of trackpad). + description: Veranderd hoe gevoelig het zoomen is (muiswiel of trackpad). sensitivity: super_slow: Super langzaam slow: Langzaam regular: Middel fast: Snel super_fast: Super snel - language: title: Taal - description: >- - Verander de taal. Alle vertalingen zijn bijdragen van gebruikers en zijn mogelijk niet compleet! - + description: Verander de taal. Alle vertalingen zijn bijdragen van gebruikers en + zijn mogelijk niet compleet! fullscreen: title: Volledig scherm - description: >- - Het wordt aangeraden om het spel op volledig scherm te spelen voor de beste ervaring. Dit is alleen beschikbaar in de standalone. - + description: Het wordt aangeraden om het spel op volledig scherm te spelen voor + de beste ervaring. Dit is alleen beschikbaar in de standalone. soundsMuted: title: Demp geluiden - description: >- - Wanneer dit aan staat worden alle geluidseffecten uitgeschakeld. - + description: Wanneer dit aan staat worden alle geluidseffecten uitgeschakeld. musicMuted: title: Demp muziek - description: >- - Wanneer dit aan staat wordt alle muziek uitgeschakeld. - + description: Wanneer dit aan staat wordt alle muziek uitgeschakeld. theme: title: Donkere modus - description: >- - Kies de gewenste weergave (licht / donker). - + description: Kies de gewenste weergave (licht/donker). themes: dark: Donker light: Licht - refreshRate: - title: Simulation Target - description: >- - Wanneer je een 144 hz monitor hebt, verander de refresh rate hier zodat het spel naar behoren weer blijft geven. Dit verlaagt mogelijk de FPS als je computer te traag is. - + title: Simulatie doel + description: Wanneer je een 144 hz monitor hebt, verander de refresh rate hier + zodat het spel naar behoren weer blijft geven. Dit verlaagt + mogelijk de FPS als je computer te traag is. alwaysMultiplace: title: Plaats meerdere - description: >- - Wanneer dit aan staat zullen gebouwen geselecteerd blijven na plaatsing, tot je dit cancelt. Dit staat gelijk aan permanent SHIFT inhouden. - + description: Wanneer dit aan staat zullen gebouwen geselecteerd blijven na + plaatsing, tot je dit cancelt. Dit staat gelijk aan permanent + SHIFT inhouden. offerHints: title: Hints & Tutorials - description: >- - Wanneer dit uit staat zullen er geen hints en tutorials meer aangeboden worden. Als deze optie aan staat, zullen ook bepaalde elementen uit de UI verborgen worden tot het punt waarop ze gebruikt worden om de instap in het spel makkelijker te maken. - + description: Wanneer dit uit staat zullen er geen hints en tutorials meer + aangeboden worden. Als deze optie aan staat, zullen ook bepaalde + elementen uit de UI verborgen worden tot het punt waarop ze + gebruikt worden om de instap in het spel makkelijker te maken. movementSpeed: title: Bewegingssnelheid - description: Veranderd hoe snel het beeld beweegt wanneer je het toetsenbord gebruikt. + description: Veranderd hoe snel het beeld beweegt wanneer je het toetsenbord + gebruikt. speeds: super_slow: Super langzaam slow: Langzaam @@ -718,20 +832,17 @@ settings: extremely_fast: Extreem snel enableTunnelSmartplace: title: Slimme Tunnels - description: >- - Wanneer dit aan staat zullen tunnels automatisch onnodige lopende banden verwijderen. - Ook kun je dan tunnels slepen en onnodige tunnels worden ook verwijderd. + description: Wanneer dit aan staat zullen tunnels automatisch onnodige lopende + banden verwijderen. Ook kun je dan tunnels slepen en onnodige + tunnels worden ook verwijderd. vignette: title: Vignet - description: >- - Schakelt de vignet in, wat de hoeken van het scherm donkerder maakt zodat de tekst makkelijker te lezen is. - + description: Schakelt de vignet in, wat de hoeken van het scherm donkerder maakt + zodat de tekst makkelijker te lezen is. autosaveInterval: title: Autosave Interval - description: >- - Bepaalt hoe vaak het spel automatisch opslaat. Je kan het hier ook volledig - mee uitschakelen. - + description: Bepaalt hoe vaak het spel automatisch opslaat. Je kan het hier ook + volledig mee uitschakelen. intervals: one_minute: 1 Minuut two_minutes: 2 Minuten @@ -741,31 +852,78 @@ settings: disabled: Uitgeschakeld compactBuildingInfo: title: Compacte gebouwinformatie - description: >- - Informatie weergeven bij gebouwen wordt beperkt tot alleen hun 'ratios'. Anders - zie je een beschrijving en een afbeelding. + description: Informatie weergeven bij gebouwen wordt beperkt tot alleen hun + 'ratios'. Anders zie je een beschrijving en een afbeelding. disableCutDeleteWarnings: title: Schakel knip/verwijder waarschuwingen uit - description: >- - Schakelt de waarschuwing uit die wordt weergegeven wanneer je meer dan 100 dingen probeert te - knippen/verwijderen. + description: Schakelt de waarschuwing uit die wordt weergegeven wanneer je meer + dan 100 dingen probeert te knippen/verwijderen. enableColorBlindHelper: title: Kleurenblindmodus - description: Schakelt verschillende hulpmiddelen in zodat je het spel alsnog kunt spelen wanneer je kleurenblind bent. + description: Schakelt verschillende hulpmiddelen in zodat je het spel alsnog + kunt spelen wanneer je kleurenblind bent. rotationByBuilding: title: Rotatie per type gebouw - description: >- - Elk type gebouw onthoud apart de rotatie waarin je het voor het laatst geplaatst hebt. - Dit kan handig zijn wanneer je vaak tussen verschillende - soorten gebouwen wisselt. - + description: Elk type gebouw onthoudt apart de rotatie waarin je het voor het + laatst geplaatst hebt. Dit kan handig zijn wanneer je vaak + tussen verschillende soorten gebouwen wisselt. + soundVolume: + title: Geluidsvolume + description: Stel het volume voor geluidseffecten in. + musicVolume: + title: Muziekvolume + description: Stel het volume voor muziek in. + lowQualityMapResources: + title: Lage kwaliteit van resources + description: Versimpeldde resources op de wereld wanneer ingezoomd om de + performance te verbeteren. Het lijkt ook opgeruimder, dus + probeer het zelf een keertje uit! + disableTileGrid: + title: Zet Grid uit + description: Door de grid uit te zetten krijgt het spel een betere performance. + Het zorgt er ook voor dat het spel er opgeruimder uit ziet! + clearCursorOnDeleteWhilePlacing: + title: Verwijder cursor met rechtermuisknop + description: Standaard aan, Stopt met het plaatsen van gebouwen door te klikken + op de rechtermuisknop. Als deze instelling uit staat kunnen + gebouwen verwijderd worden tijdens het plaatsen door te klikken + op de rechtermuisknop. + lowQualityTextures: + title: Lage kwaliteit + description: Gebruikt een lage kwaliteit voor meer performance. Het spel ziet er + wel niet meer mooi uit! + displayChunkBorders: + title: Toon gebied omlijning + description: Het spel is verdeeld in gebieden van 16x16 tegels. Als deze + instelling is ingeschakeld, zijn de lijnen hiervan zichtbaar. + pickMinerOnPatch: + title: Selecteer ontginner boven resource vakje + description: Standaard aan. Selecteerd automatisch de ontginner wanneer de muis + met de pipet boven het vakje van een resource staat. + simplifiedBelts: + title: Versimpelde lopende banden + description: Toont geen items op de band tenzij je over de lopende band beweegt + met je muis. De functie wordt niet aangeraden tenzij het qua + performance echt niet anders kan! + enableMousePan: + title: Schakel bewegen met muis in + description: Schakel deze functie in om met je muis het veld te kunnen bewegen. + Plaats de cursor boven, rechts, links of onder om daar naartoe + te bewegen. + zoomToCursor: + title: Zoom naar de Muis + description: "Wanneer geactiveert: de zoom zal gebeuren in de richting van je + muispositie, anders in het midden van het scherm." + mapResourcesScale: + title: Kaartbronnen schaal + description: Controleert de grote van de vormen op het map overzicht (wanneer je + uitzoomt). + rangeSliderPercentage: % keybindings: title: Sneltoetsen - hint: >- - Tip: Maak gebruik van CTRL, SHIFT en ALT! Hiermee kun je dingen anders en gemakkelijker plaatsen. - + hint: "Tip: Maak gebruik van CTRL, SHIFT en ALT! Hiermee kun je dingen anders en + gemakkelijker plaatsen." resetKeybindings: Reset sneltoetsen - categoryLabels: general: Applicatie ingame: Spel @@ -774,7 +932,6 @@ keybindings: massSelect: Massaselectie buildings: Gebouwen placementModifiers: Plaatsingsaanpassingen - mappings: confirm: Bevestig back: Terug @@ -783,38 +940,30 @@ keybindings: mapMoveDown: Beweeg omlaag mapMoveLeft: Beweeg naar links centerMap: Ga naar het midden van het speelveld - mapZoomIn: Zoom in mapZoomOut: Zoom uit createMarker: Plaats een markering - menuOpenShop: Upgrades menuOpenStats: Statistieken - - toggleHud: Toggle HUD - toggleFPSInfo: Toggle FPS en Debug Info - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + toggleHud: Schakel HUD + toggleFPSInfo: Schakel FPS en Debug Info + belt: Lopende Band + underground_belt: Tunnel + miner: Ontginner + cutter: Knipper + rotater: Roteerder + stacker: Stapelaar + mixer: Kleurenmenger + painter: Verver + trash: Vuilnisbak rotateWhilePlacing: Roteren - rotateInverseModifier: >- - Aanpassing: Roteer tegen de klok in + rotateInverseModifier: "Aanpassing: Roteer tegen de klok in" cycleBuildingVariants: Wissel tussen varianten confirmMassDelete: Bevestig massaal verwijderen cycleBuildings: Wissel tussen gebouwen - massSelectStart: Klik en sleep voor selecteren massSelectSelectMultiple: Selecteer meerdere gebieden massSelectCopy: Kopieer selectie - placementDisableAutoOrientation: Schakel automatisch draaien uit placeMultiple: Blijf in plaatsmodus placeInverse: Omkeren richting lopende band @@ -827,39 +976,120 @@ keybindings: pipette: Pipet menuClose: Sluit Menu switchLayers: Lagen omwisselen - advanced_processor: Kleur-omvormer - energy_generator: Energiegenerator wire: Energiekabel - + balancer: Balancer + storage: Opslag + constant_signal: Constant Signaal + logic_gate: Logische poort + lever: Schakelaar (regulier) + filter: Filter + wire_tunnel: Kabel kruising + display: Scherm + reader: Lopende band lezer + virtual_processor: Virtuele Snijder + transistor: Transistor + analyzer: Vorm Analyse + comparator: Vergelijk + item_producer: Item Producent (Sandbox) + copyWireValue: "Kabels: Kopieer waarde onder cursor" about: title: Over dit spel body: >- - Dit spel is open source en ontwikkeld door Tobias Springer (dit ben ik).

+ Dit spel is open source en ontwikkeld door Tobias Springer + (dit ben ik).

- Als je ook bij wil dragen, ga dan naar shapez.io op github.

+ Als je ook bij wil dragen, ga dan naar shapez.io op github.

- 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)!

+ 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)!

- De muziek is gemaakt door Peppsen - Hij is geweldig.

- - Tot slot wil ik mijn beste vriend Niklas bedanken - Zonder onze - factorio-sessies zou dit spel nooit bestaan hebben. + De muziek is gemaakt door Peppsen - Hij is geweldig.

+ Tot slot wil ik mijn beste vriend Niklas bedanken - Zonder onze factorio-sessies zou dit spel nooit bestaan hebben. changelog: title: Changelog - demo: features: restoringGames: Savegames terughalen importingGames: Savegames importeren oneGameLimit: Gelimiteerd tot één savegame - customizeKeybindings: Custom sneltoetsen + customizeKeybindings: Aangepaste sneltoetsen exportingBase: Exporteer volledige basis als afbeelding - settingNotAvailable: Niet beschikbaar in de demo. +tips: + - De hub accepteert elke vorm van invoer, niet alleen de huidige vorm! + - Zorg ervoor dat uw fabrieken modulair zijn - het loont! + - Bouw niet te dicht bij de hub, anders wordt het een enorme chaos! + - Als het stapelen niet werkt, probeer dan de ingangen om te wisselen. + - U kunt de richting van de lopende band planner wijzigen door op R + te drukken. + - Door CTRL ingedrukt te houden, kunnen lopende banden worden + gesleept zonder automatische oriëntatie. + - Verhoudingen blijven hetzelfde, zolang alle upgrades zich op hetzelfde + niveau bevinden. + - Opeenvolgende uitvoering is efficiënter dan parallele uitvoering. + - Je ontgrendelt later in het spel meer varianten van gebouwen! + - U kunt T gebruiken om tussen verschillende varianten te schakelen. + - Symmetrie is de sleutel! + - Je kunt verschillende tunnels weven. + - Probeer compacte fabrieken te bouwen - het loont! + - De schilder heeft een gespiegelde variant die u kunt selecteren met + T + - Met de juiste bouwverhoudingen wordt de efficiëntie gemaximaliseerd. + - Op het maximale niveau vullen 5 ontginners een enkele band. + - Vergeet tunnels niet! + - U hoeft de items niet gelijkmatig te verdelen voor volledige efficiëntie. + - Als u SHIFT ingedrukt houdt tijdens het bouwen van lopende banden, + wordt de planner geactiveerd, zodat je gemakkelijk lange rijen kunt + plaatsen. + - Snijders snijden altijd verticaal, ongeacht hun oriëntatie. + - Meng alle drie de kleuren om wit te krijgen. + - De opslagbuffer geeft prioriteit aan de eerste uitvoer. + - Investeer tijd om herhaalbare ontwerpen te maken - het is het waard! + - Door SHIFT ingedrukt te houden, kunnen meerdere gebouwen worden + geplaatst. + - U kunt ALT ingedrukt houden om de richting van de geplaatste banden + om te keren. + - Efficiëntie is de sleutel! + - Vormontginningen die verder van de hub verwijderd zijn, zijn complexer. + - Machines hebben een beperkte snelheid, verdeel ze voor maximale + efficiëntie. + - Gebruik verdelers om uw efficiëntie te maximaliseren. + - Organisatie is belangrijk. Probeer de transportbanden niet te veel over te + steken. + - Plan van tevoren, anders wordt het een enorme chaos! + - Verwijder uw oude fabrieken niet! Je hebt ze nodig om upgrades te + ontgrendelen. + - Probeer in je eentje level 20 te verslaan voordat je hulp zoekt! + - Maak de dingen niet ingewikkeld, probeer eenvoudig te blijven en u zult + ver komen. + - Mogelijk moet u later in het spel fabrieken hergebruiken. Plan uw + fabrieken zodat ze herbruikbaar zijn. + - Soms kunt u een gewenste vorm op de kaart vinden zonder deze met + stapelaars te maken. + - Volle windmolens / vuurwielen kunnen nooit op natuurlijke wijze spawnen. + - Kleur uw vormen voordat u ze snijdt voor maximale efficiëntie. + - Bij modules is ruimte slechts een beleving; een zorg voor sterfelijke + mannen. + - Maak een aparte blueprint fabriek. Ze zijn belangrijk voor modules. + - Bekijk de kleurenmixer eens wat beter, en uw vragen worden beantwoord. + - Gebruik CTRL + klik om een gebied te selecteren. + - Te dicht bij de hub bouwen kan latere projecten in de weg staan. + - Het speldpictogram naast elke vorm in de upgradelijst zet deze vast op het + scherm. + - Meng alle primaire kleuren door elkaar om wit te maken! + - Je hebt een oneindige kaart, verkramp je fabriek niet, breid uit! + - Probeer ook Factorio! Het is mijn favoriete spel. + - De quad-snijder snijdt met de klok mee vanaf de rechterbovenhoek! + - Je kunt je savegames downloaden in het hoofdmenu! + - Deze game heeft veel handige sneltoetsen! Bekijk zeker de + instellingenpagina. + - Deze game heeft veel instellingen, bekijk ze zeker! + - De markering naar uw hub heeft een klein kompas om de richting aan te + geven! + - Om de banden leeg te maken, knipt u het gebied af en plakt u het op + dezelfde locatie. + - Druk op F4 om uw FPS en Tick Rate weer te geven. + - Druk twee keer op F4 om de tegel van je muis en camera weer te geven. + - U kunt aan de linkerkant op een vastgezette vorm klikken om deze los te + maken. diff --git a/translations/base-no.yaml b/translations/base-no.yaml index dccb84b3..1e8bf7b0 100644 --- a/translations/base-no.yaml +++ b/translations/base-no.yaml @@ -1,111 +1,64 @@ -# -# 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 er et spill som handler om å bygge fabrikker for å automatisere produksjon og kombinasjon av former med økende kompleksitet på et uendelig ekspanderende 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. + discordLinkShort: Offissiell Discord + intro: >- + Shapez.io er et avslappende spill der du skal bygge fabrikker + for automatisert produksjon av geometriske former. - # 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] + Etterhvert som du når høyere nivåer blir formene mer og mer komplekse, og du må spre deg ut over det uendelige kartet. - 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 + Og som om det ikke var nok må du også produsere eksponensielt for å tilfredsstille etterspørselen - det eneste som hjelper er skalering! - 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]! + Mens du kun produserer former i starten må du fargelegge de senere - for å gjøre dette må du hente ut og blande farger! - 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. - - 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! - - 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]Frittstående fordeler[/b] - - [list] - [*] 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]Fremtidige Oppdateringer[/b] - - Jeg oppdaterer spillet veldig ofte og prøver å presse inn en oppdatering i det minste hver uke! - - [list] - [*] Forskjellige baner og utfordringer (f.eks. baner 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]Dette spillet er åpen kildekode![/b] - - 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]Lenker[/b] - - [list] - [*] [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]Kildekode (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Hjelp til å oversette[/url] - [/list] - - discordLink: Offisiell Discord - Chat med meg! + Ved å kjøpe spillet på Steam får du tilgang til fullversjonen, men du kan også spille en demo på shapez.io først og bestemme deg senere! + title_advantages: Fordeler med fullversjonen + advantages: + - 12 Nye nivåer til totalt 26 nivåer + - 18 Nye byggninger For en helautomatisert fabrikk! + - 20 Oppgraderingsnivåer for mange timer med moro! + - Kabeloppdateringen For en helt ny dimensjon! + - Mørkt tema! + - Uendelige lagringsplasser + - Uendelige markører + - Støtt meg! ❤️ + title_future: Planlagt innhold + planned: + - Blåkopibibliotek (Eksklusivt til fullversjonen) + - Steam-medaljer + - Puslemodus + - Minikart + - Mods + - Sandkassemodus + - ... og masse mer! + title_open_source: Dette spillet har åpen kildekode! + title_links: Lenker + links: + discord: Offisiell Discord + roadmap: Veikart + subreddit: Subreddit + source_code: Kildekode (GitHub) + translate: Hjelp til med å oversette + text_open_source: >- + Alle kan bidra, jeg er aktivt involvert i sammfunnet og prøver å se + gjennom alle forslagene og tar tilbakemeldinger i betraktning der det + er mulig. + Sjekk også mitt Trello-brett for hele veikartet! global: loading: Laster error: Feil - - # 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. + decimalSeparator: . suffix: thousands: k millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: inf - time: - # Used for formatting past time dates oneSecondAgo: ett sekund siden xSecondsAgo: sekunder siden oneMinuteAgo: ett minutt siden @@ -114,14 +67,10 @@ global: xHoursAgo: timer siden oneDayAgo: en dag siden xDaysAgo: dager siden - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s hoursAndMinutesShort: t m - xMinutes: minutter - keys: tab: TAB control: CTRL @@ -129,34 +78,26 @@ global: escape: ESC shift: SHIFT space: MELLOMROM - demoBanners: - # This is the "advertisement" shown in the main menu and other various places title: Demo Versjon - intro: >- - Skaff deg frittstående versjon for å åpne alle funksjoner! - + intro: Skaff deg frittstående versjon for å åpne alle funksjoner! mainMenu: play: Spill 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. - + browserWarning: 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 subreddit: Reddit - + savegameUnnamed: Unnamed dialogs: buttons: ok: OK @@ -170,110 +111,107 @@ dialogs: viewUpdate: Vis Oppdatering showUpgrades: Vis Oppgraderinger showKeybindings: Se Hurtigtaster - importSavegameError: - title: Importerings feil - text: >- - Kunne ikke importere lagringsfilen: - + title: Importeringsfeil + text: "Kunne ikke importere lagringsfilen:" importSavegameSuccess: title: Lagringsfil importert - text: >- - Din Lagringsfil ble vellykket importert. - + text: Din Lagringsfil ble importert. gameLoadFailure: title: Lagringsfilen er ødelagt - text: >- - Kunne ikke laste inn lagringsfilen: - + text: "Kunne ikke laste inn lagringsfilen:" confirmSavegameDelete: title: Bekreft sletting - text: >- - Er du sikker på at du ønsker å slette lagringsfilen? - + text: Are you sure you want to delete the following game?

+ '' at level

This can not be + undone! savegameDeletionError: title: Kunne ikke slette - text: >- - Kunne ikke slette lagringsfilen: - + text: "Kunne ikke slette lagringsfilen:" restartRequired: title: Omstart nødvendig - text: >- - Du må starte spillet på nytt for å ta i bruk instillingene. - + text: Du må starte spillet på nytt for å ta i bruk instillingene. editKeybinding: title: Endre Hurtigtast - desc: Trykk på knappen eller museknappen du vil tildele, eller escape for å avbryte. - + 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!! - desc: >- - Her er endringene siden sist du spilte: - + desc: "Her er endringene siden sist du spilte:" upgradesIntroduction: title: Åpne Oppgradering - desc: >- - Alle objektene du produserer kan bli brukt til å åpne oppgraderinger - Ikke ødelegg dine gamle fabrikker! + desc: Alle objektene du produserer kan bli brukt til å åpne oppgraderinger - + Ikke ødelegg dine gamle fabrikker! Oppgraderingsfanen er plassert øverst til høyre på skjermen. - massDeleteConfirm: title: Bekreft sletting - desc: >- - Du skal til å slette mange bygninger ( for å være nøyaktig)! Er du sikker på at du ønsker å gjøre dette? - + desc: 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 - desc: >- - Du klipper ut mange bygninger ( for å være nøyaktig)! Er du sikker på at du ønsker å gjøre dette? - + title: Bekreft Utlipping + desc: Du klipper ut mange bygninger ( for å være nøyaktig)! Er du sikker + på at du ønsker å gjøre dette? blueprintsNotUnlocked: title: Ikke åpnet enda - desc: >- - Fullfør nivå 12 for å åpne blåkopier! - + desc: Fullfør nivå 12 for å åpne blåkopier! keybindingsIntroduction: title: Nyttige hurtigtaster - desc: >- - 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.
- + desc: "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 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: Give it a meaningful name, you can also include a short + key of a shape (Which you can generate here) + 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)! + 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? + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: Rename Savegame + desc: You can rename your savegame here. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Beveg selectBuildings: Velg område @@ -293,19 +231,10 @@ ingame: copySelection: Kopier clearSelection: Fjern Valgte pipette: Pipette - switchLayers: Switch layers - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + switchLayers: Bytt lag 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: Trykk for å veksle mellom variantene. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - + hotkeyLabel: "Hotkey: " infoTexts: speed: Hastighet range: Lengde @@ -313,36 +242,21 @@ ingame: oneItemPerSecond: 1 objekt / sekund itemsPerSecond: objekter / s itemsPerSecondDouble: (x2) - tiles: ruter - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Nivå completed: Fullført unlockText: Åpnet ! buttonNextLevel: Neste Nivå - - # Notifications on the lower right notifications: newUpgrade: En ny oppgradering er tilgjengelig! gameSaved: Spillet ditt er lagret. - - # The "Upgrades" window + freeplayLevelComplete: Level has been completed! shop: title: Oppgraderinger buttonUnlock: Oppgrader - - # Gets replaced to e.g. "Tier IX" tier: Nivå - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAKS NIVÅ (Hastighet x) - - # The "Statistics" window statistics: title: Statistikk dataSources: @@ -351,55 +265,70 @@ ingame: description: Viser hva som er lagret i hovedbygningen. produced: title: Produsert - description: Viser alle objektene hele fabrikken produserer, inkluderer avanserte objekter. + description: Viser alle objektene hele fabrikken produserer, inkluderer + avanserte objekter. delivered: title: Levert description: Viser objekter som er levert til hovedbygningen. noShapesProduced: Ingen objekter har blitt produsert så langt. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Spilletid - buildingsPlaced: Bygninger - beltsPlaced: Belter - - buttons: - continue: Fortsett - settings: Innstillinger - menu: Tilbake til hovedmeny - - # Bottom left tutorial hints + beltsPlaced: Samlebånd tutorialHints: title: Trenger du hjelp? showHint: Vis hint hideHint: Lukk - - # When placing a blueprint blueprintPlacer: cost: Kostnad - - # Map markers waypoints: waypoints: Markør hub: Hovedbygning - description: Venstreklikk en markør for å gå dit, høyreklikk for å slette markøren.

Trykk for å lage en markør fra nåværende sted, eller høyreklikk for å lage en markør på valgt område. + description: Venstreklikk en markør for å gå dit, høyreklikk for å slette + markøren.

Trykk for å lage en markør fra + nåværende sted, eller høyreklikk for å lage en + markør på valgt område. creationSuccessNotification: Markren ble laget. - - # Interactive tutorial interactiveTutorial: title: Opplæring hints: - 1_1_extractor: Plasser en utdrager på toppen av en sirkel form for å samle den! - 1_2_conveyor: >- - Koble utdrageren med et transportbånd til hovedbygningen!

Tips: Trykk og dra beltet med musa! - - 1_3_expand: >- - Dette er IKKE et idle-spill! Bygg flere utdragere og belter for å nå målet raskere.

Tips: Hold SHIFT for å plassere flere utdragere, og bruk R for å rotere dem. - + 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!" + 1_3_expand: "Dette er IKKE et idle-spill! Bygg flere utdragere + og belter for å nå målet raskere.

Tips: Hold + SHIFT for å plassere flere utdragere, og bruk + R for å rotere dem." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." colors: red: Rød green: Grønn @@ -409,16 +338,50 @@ ingame: cyan: Cyan white: Hvit uncolored: Ingen farge - black: Black + black: Svart shapeViewer: title: Lag empty: Tom copyKey: Copy Key - -# All shop upgrades + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limited to + watermark: + title: Demo version + desc: Click here to see the Steam version advantages! + get_on_steam: Get on steam + standaloneAdvantages: + title: Get the full version! + no_thanks: No, thanks! + points: + levels: + title: 12 New Levels + desc: For a total of 26 levels! + buildings: + title: 18 New Buildings + desc: Fully automate your factory! + savegames: + title: ∞ Savegames + desc: As many as your heart desires! + upgrades: + title: 20 Upgrade Tiers + desc: This demo version has only 5! + markers: + title: ∞ Markers + desc: Never get lost in your factory! + wires: + title: Wires + desc: An entirely new dimension! + darkmode: + title: Dark Mode + desc: Stop hurting your eyes! + support: + title: Support me + desc: I develop it in my spare time! shopUpgrades: belt: - name: Belter, Distributører & Tuneller + name: Belter, Distributører & Tunneler description: Hastighet x → x miner: name: Utdrager @@ -429,309 +392,457 @@ shopUpgrades: painting: name: Miksing & Maling description: Hastighet x → x - -# Buildings and their name / description buildings: hub: deliver: Lever toUnlock: for å låse opp levelShortcut: nivå - + endOfDemo: End of Demo belt: default: - name: &belt Transportbånd + name: Samlebånd description: Transporterer objekter, hold og dra for å plassere flere. - - miner: # Internal name for the Extractor + miner: default: - name: &miner Utdrager + name: Utdrager description: Plasser over en form eller farge for å trekke ut. - chainable: name: Utdrager (Kjede) - description: Plasser over en form eller farge for å trekke ut. Kan kobles i kjede. - - underground_belt: # Internal name for the Tunnel + description: Plasser over en form eller farge for å trekke ut. Kan kobles i + kjede. + underground_belt: default: - name: &underground_belt Tunell - description: Lar deg bruke tuneller for å transportere objekter under bygninger og belter. - + name: Tunnel + description: Lar deg bruke tuneller for å transportere objekter under bygninger + og belter. tier2: name: Tunell Nivå II - description: Lar deg bruke tuneller for å transportere objekter under bygninger og belter. - - splitter: # Internal name for the Balancer - default: - name: &splitter Utjevner - description: Multifunksjonell - Sprer alt jevnt utover. - - compact: - name: Sammenslå (kompakt) - description: Slår sammen to belter til ett. - - compact-inverse: - name: Sammenslå (kompakt) - description: Slår sammen to belter til ett. - + description: Lar deg bruke tuneller for å transportere objekter under bygninger + og belter. 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! + name: 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 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. + name: Roter + 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. + rotate180: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: - name: &stacker Stabler - description: Stabler begge objekter. Hvis de ikke kan bli stablet sidelengs, vil høyre stables over den andre. - + name: Stabler + description: Stabler begge formene. Hvis de ikke kan bli stablet sidelengs, vil + høyre stables over den andre. mixer: default: - name: &mixer Fargemikser + name: Fargemikser description: Mikser to farger sammen ved å blande de. - painter: default: - name: &painter Maler - description: &painter_desc Maler hele objektet på venstre inngang med fargen fra øverste inngang. + name: Maler + description: 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: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! mirrored: - name: *painter - description: *painter_desc - + name: Maler + description: Maler hele formen på venstre inngang med fargen fra øverste + inngang. trash: default: - name: &trash Søppelkasse - description: Tar imot objekter 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. + name: Søppelkasse + description: Tar imot former og farger fra alle sider og ødelegger de. For + alltid. wire: default: - name: Energy Wire - description: Allows you to transport energy. - advanced_processor: + name: Energikabel + description: Lar deg transportere energi. + second: + name: Wire + description: Transfers signals, which can be items, colors or booleans (1 / 0). + Different colored wires do not connect. + balancer: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For - default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Merger (compact) + description: Merges two conveyor belts into one. + merger-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + storage: + default: + name: Storage + description: Stores excess items, up to a given capacity. Prioritizes the left + output and can be used as an overflow gate. + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: Switch + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means + shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. + (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means + shape, color or boolean "1") + transistor: + default: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + mirrored: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: Belt Reader + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: Virtual Cutter + description: Virtually cuts the shape into two halves. + rotater: + name: Virtual Rotater + description: Virtually rotates the shape, both clockwise and counter-clockwise. + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the + remaining ones to the left. + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the shape on + the right input. + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the + wires layer on the regular layer. 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: You just unlocked the cutter, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! reward_rotater: title: Rotering - desc: Rotereren har blitt tilgjengelig! Den roterer objekter med klokken 90 grader. - + desc: Rotereren har blitt tilgjengelig! Den roterer objekter + med klokken 90 grader. 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! - + 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 instillingene!" reward_mixer: title: Fargemikser - desc: Fargemikseren har blitt tilgjengelig - Kombiner to farger og bland de sammen med denne bygningen! - + desc: Fargemikseren har blitt tilgjengelig - Kombiner to farger + og bland de sammen med denne bygningen! reward_stacker: title: Sammenslåer - desc: Du kan nå slå sammen forskjellige former med sammenslåeren! Begge inngangene blir slått sammen, og hvis det er mulig blir de plassert ved siden av hverandre, de vil bil til en. Hvis ikke, blir høyre inngang plassert over venstre inngang! - + desc: Du kan nå slå sammen forskjellige former med + sammenslåeren! Begge inngangene blir slått sammen, + og hvis det er mulig blir de plassert ved siden av hverandre, de vil + bil til en. Hvis ikke, blir høyre inngang + plassert over venstre inngang! 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: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! 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 - 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! - + 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: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" 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å! - - reward_splitter_compact: - title: Kompakt Utjevning - desc: >- - Du har åpnet en variant av utjevneren - Den godtar to innganger og slår de sammen til en! - + 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_cutter_quad: title: 4-Veis Kutting - desc: Du har åpnet en variant av kutteren - Den lar deg dele objekter inn i fire deler istedenfor bare to! - + desc: Du har åpnet en variant av kutteren - Den lar deg dele + objekter inn i fire deler istedenfor bare to! 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! - - reward_painter_quad: - title: Firegangers Maling - desc: Du har åpnet en variant av maleren - Den lar deg male hver del av objektet individuelt! - + 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_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: You have unlocked the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! 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: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. 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). - - # Special reward, which is shown when there is no reward actually + 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). 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! - + desc: "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! - + desc: Gratulerer!! Forresten, mer innhold er planlagt for den frittstående + versjonen! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: End of Demo + desc: You have reached the end of the demo version! settings: title: Instillinger categories: - game: Spill - app: Applikasjon - + general: Generelt + userInterface: Brukergrensesnitt + advanced: Avansert + performance: Performance versionBadges: dev: Utvikling - staging: Icenesettelse + staging: Iscenesettelse prod: Produksjon buildDate: Bygget - labels: uiScale: - title: Grensesnitt skala - description: >- - Endrer størrelsen på brukergrensesnitt. Grensesnittet vil fortsatt skaleres basert på din enhets oppløsning, men denne instillingen styrer mengden den skalerer. + 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: super_small: Veldig liten small: Liten regular: Vanlig large: Stor huge: Gigantisk - scrollWheelSensitivity: - title: Forstørrelses sensitivitet - description: >- - Endrer hvor sensitiv forstørringen er (Enten musehjulet eller trackpad). + title: Forstørrelsessensitivitet + description: Endrer hvor sensitiv forstørringen er (Enten musehjulet eller + museplate). sensitivity: super_slow: Veldig Sakte slow: Sakte regular: Vanlig fast: Raskt super_fast: Veldig Raskt - movementSpeed: title: Bevegelses hastighet - description: >- - Endrer hvor raskt bildet beveger seg når man bruker tastaturet. + 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 super_fast: Veldig Raskt extremely_fast: Ekstremt Raskt - language: title: Språk - description: >- - Endre språket. Alle oversettelser er bidrag ifra andre brukere og kan være ufullstendig! - + description: Endre språket. Alle oversettelser er bidrag ifra andre brukere og + kan være ufullstendig! fullscreen: title: Fullskjerm - description: >- - Det er anbefalt å spille spillet i fullskjerm for best mulig opplevelse. Kun tilgjengelig i frittstående versjon. - + description: Det er anbefalt å spille spillet i fullskjerm for best mulig + opplevelse. Kun tilgjengelig i frittstående versjon. soundsMuted: title: Skru av lyder - description: >- - Hvis aktivert, skrur av alle lydeffekter. - + description: Skrur av alle lydeffekter. musicMuted: title: Skru av Musikk - description: >- - Hvis aktivert, skrur av all musikk. - + description: Skrur av all musikk. theme: title: Spilltema - description: >- - Velg spilltema (lys / mørk). + description: Velg spilltema (lyst / mørk). themes: dark: Mørk - light: Lys - + light: Lyst refreshRate: - title: Simulerings Må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. - + 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. - + description: Hvis aktivert vil alle bygg forbli valgt etter plassering inntil du + avbryter det. Dette tilsvarer å holde SHIFT nede permanent. offerHints: title: Hint & Opplæring - description: >- - Om du ønsker hint og opplæring mens du spiller. Skjuler også enkelte elementer i brukergrensesnittet inntil spesifike nivå for å enklere komme i gang med spillet. - + description: Om du ønsker hint og opplæring mens du spiller. Skjuler også + enkelte elementer i brukergrensesnittet inntil spesifike nivå + for å enklere komme i gang med spillet. 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. + description: 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: >- - Aktiverer vignett som gjør hjørnene på skjermen mørkere og teksten lettere - å lese. - + description: Aktiverer vignett som gjør hjørnene på skjermen mørkere og teksten + lettere å lese. autosaveInterval: title: Autolagringsintervall - description: >- - Jsuter hvor ofte spillet lagres automatisk. Du kan også - deaktivere det fullstendig. + description: Jsuter hvor ofte spillet lagres automatisk. Du kan også deaktivere + det fullstendig. intervals: one_minute: 1 Minutt two_minutes: 2 Minutter @@ -741,41 +852,85 @@ settings: disabled: Deaktivert compactBuildingInfo: title: Kompakt Bygningsinformasjon - description: >- - Forkorter informasjonsboksen for bygninger ved å bare vise dems forhold. Ellers - vises en beskrivelse og bilde er vist. + description: Forkorter informasjonsboksen for bygninger ved å bare vise deres + forhold. Ellers vises en beskrivelse og et bilde. disableCutDeleteWarnings: - title: Deaktiverer Kutt/Slette Advarsler - description: >- - Deaktiverer advarselsdialogen som kommer frem når du kutter/sletter mer enn 100 - bygninger. - + title: Deaktiverer Utklipps- og Sletteadvarsler + description: Deaktiverer advarselsmeldingen som kommer frem når du klipper ut + eller sletter mer enn 100 bygninger. enableColorBlindHelper: - title: Fargeblind Modus - description: Aktiverer forskjellige verktøy som lar deg spille spillet om du er fargeblind. + 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. - Dette kan være mer komfortabelt hvis du ofte veksler mellom plassering + description: Hver bygningstype husker rotasjonen du sist brukte på dee. Dette + kan være mer komfortabelt hvis du ofte veksler mellom plassering av forskjellige bygninger. - + soundVolume: + title: Sound Volume + description: Set the volume for sound effects + musicVolume: + title: Music Volume + description: Set the volume for music + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: Hurtigtaster - hint: >- - Tips: Husk å bruke CTRL, SHIFT and ALT! De gir deg flere plasseringsmuligheter. - + hint: "Tips: Husk å bruke CTRL, SHIFT and ALT! De gir deg flere + plasseringsmuligheter." resetKeybindings: Nullstill Hurtigtaster - categoryLabels: general: Applikasjon ingame: Spill navigation: Navigering placement: Plassering massSelect: Velg Masse - buildings: Bygnings Snarvei - placementModifiers: Plasserings Alternativer - + buildings: Bygningssnarvei + placementModifiers: Plasseringsalternativer mappings: confirm: Bekreft back: Tilbake @@ -785,75 +940,139 @@ keybindings: mapMoveLeft: Flytt Venstre mapMoveFaster: Beveg Raskere centerMap: Midstill Brettet - mapZoomIn: Zoom inn mapZoomOut: Zoom ut createMarker: Lag Markør - menuOpenShop: Oppgraderinger 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 - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + belt: Samlebånd + underground_belt: Tunnel + miner: Utdrager + cutter: Kutter + rotater: Roter + stacker: Stabler + mixer: Fargemikser + painter: Maler + trash: Søppelkasse rotateWhilePlacing: Roter - rotateInverseModifier: >- - Alternativ: Roter mot klokken isteden + rotateInverseModifier: "Alternativ: Roter mot klokken isteden" cycleBuildingVariants: Endre Varianter confirmMassDelete: Bekreft Massesletting pasteLastBlueprint: Lim inn forrige blåkopi cycleBuildings: Endre Bygninger - 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 + wire: Energikabel + balancer: Balancer + storage: Storage + constant_signal: Constant Signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" about: title: Om dette spillet body: >- - Dette spillet er åpen kildekode og utviklet av Tobias Springer (dette er meg).

+ Dette spillet er åpen kildekode og utviklet av Tobias Springer + (dette er meg).

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 - demo: features: restoringGames: Gjenopprette lagringsfiler 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. +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-pl.yaml b/translations/base-pl.yaml index a28d244c..80b49d99 100644 --- a/translations/base-pl.yaml +++ b/translations/base-pl.yaml @@ -1,113 +1,65 @@ -# -# 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 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. + 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. + discordLinkShort: Oficjalny serwer Discord + intro: >- + Shapez.io jest spokojną grą, której celem jest budowanie automatycznych + fabryk produkujących różne kształty geometryczne. - # 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] + W miarę zwiększania się poziomów, kształty będą stawać się coraz bardziej skomplikowane, a Twoja fabryka będzie musiała się rozpszetrzenić na mapie o nieskończonej wielkości. - 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ę. + A jeżeli to było mało, będziesz również musiał produkować coraz więcej kształtów, by zaspokoić wymagania - jedynym rozwiązaniem jest skalowanie fabryki! - 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]! + Początkowo przekształcanie kształtów będzie proste, ale później będziesz również musiał je malować - wymaga to wydobywania i łączenia barwników! - 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. - - 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! - - Zakup gry daje dostęp do samodzielnej wersji, która ma dodatkowe funkcje, a także dostęp do nowo opracowanych funkcji. - - [b]Samodzielne zalety[/b] - - [list] - [*] 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]Przyszłe aktualizacje[/b] - - Aktualizuję grę bardzo często i staram się przesyłać aktualizacje przynajmniej co tydzień! - - [list] - [*] 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]Ta gra jest open source![/b] - - 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]Linki[/b] - - [list] - [*] [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]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: Oficjalna Discord - Porozmawiaj ze mną! + Kupienie gry w serwisie Steam przyznaje Ci dostęp do pełnej wersji, ale możesz również skorzystać z wersji demonstracyjnej na strone shapez.io i rozważyć zakup później! + title_advantages: Korzyści wersji pełnej + advantages: + - 12 Nowych poziomów (razem 26 poziomów)s + - 18 Nowych budynków umożliwiających zbudowanie całkowicie + automatycznej fabryki! + - 20 Poziomów ulepszeń zapewniających wiele godzin zabawy! + - Aktualizacja z przewodami dodająca całkowicie nowy wymiar! + - Tryb Ciemny! + - Nielimitowane zapisy gry + - Nielimitowane znaczniki + - Wspomóż mnie! ❤️ + title_future: Planowane funkcje + planned: + - Biblioteka schematów (Tylko dla Wersji pełnej) + - Osiągniecia + - Tryb zagadek + - Minimapa + - Modyfikacje + - Tryb piaskownicy + - ... i wiele więcej! + title_open_source: Ta gra jest open-source! + title_links: Linki + links: + discord: Oficjalny serwer Discord + roadmap: Plany gry + subreddit: Reddit + source_code: Kod źródłowy (GitHub) + translate: Pomóż w tłumaczeniu + text_open_source: >- + Każdy może pomóc w tworzeniu gry, jestem aktywny wśród społeczności i + próbuję odbierać wszystkie sugestie i brać je pod uwagę, gdzie tylko + jest to możliwe. + Sprawdź moją tablicę Trello, by zobaczyć moje dalsze plany! global: loading: Ładowanie error: Wystąpił błąd - - # 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 + decimalSeparator: . suffix: thousands: tys millions: mln billions: mld trillions: bln - - # Shown for infinitely big numbers infinite: ∞ - time: - # Used for formatting past time dates oneSecondAgo: sekundę temu xSecondsAgo: sekund temu oneMinuteAgo: minutę temu @@ -116,15 +68,10 @@ global: xHoursAgo: godzin temu oneDayAgo: dzień temu xDaysAgo: dni temu - - # Short formats for times, e.g. '5h 23m' - # 2nd translator's note: Changed 'm' to 'min' to distinguish from meters & to be consistent secondsShort: s minutesAndSecondsShort: min s hoursAndMinutesShort: godz min - xMinutes: minut - keys: tab: TAB control: CTRL @@ -132,13 +79,9 @@ global: escape: ESC shift: SHIFT space: SPACJA - demoBanners: - # This is the "advertisement" shown in the main menu and other various places - title: Wersja demo - intro: >- - Kup pełną wersję gry, by odblokować więcej funkcji! - + title: Wersja demonstracyjna + intro: Kup pełną wersję gry, by odblokować więcej funkcji! mainMenu: play: Rozpocznij continue: Kontynuuj @@ -148,18 +91,13 @@ mainMenu: openSourceHint: Gra z otwartym kodem źródłowym! discordLink: Oficjalny serwer Discord! helpTranslate: Pomóż w tłumaczeniu! - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - Przepraszam, ale ta gra może działać wolno w Twojej przeglądarce! Kup pełną wersję gry lub pobierz przeglądarkę chrome. - + browserWarning: Przepraszam, ale ta gra może działać wolno w Twojej + przeglądarce! Kup pełną wersję gry lub pobierz przeglądarkę chrome. savegameLevel: Poziom savegameLevelUnknown: Nieznany poziom - - madeBy: Gra wykonana przez subreddit: Reddit - + savegameUnnamed: Zapis bez nazwy dialogs: buttons: ok: OK @@ -173,113 +111,110 @@ dialogs: viewUpdate: Zobacz aktualizację showUpgrades: Pokaż ulepszenia showKeybindings: Pokaż Klawiszologię - importSavegameError: title: Błąd importowania - text: >- - Nie udało się zaimportować twojego zapisu gry: - + text: "Nie udało się zaimportować twojego zapisu gry:" importSavegameSuccess: title: Import zapisu - text: >- - Twoja gra została zaimportowana pomyślnie. - + text: Twoja gra została zaimportowana pomyślnie. gameLoadFailure: title: Błąd wczytywania - text: >- - Nie udało się wczytać twojego zapisu gry: - + text: "Nie udało się wczytać twojego zapisu gry:" confirmSavegameDelete: title: Potwierdź usuwanie - text: >- - Jesteś pewien, że chcesz usunąć zapis? - + text: Czy jesteś pewny, że chcesz usunąć poniższy zapis gry?

+ '' (poziom )

Ta akcja nie może + być cofnięta! savegameDeletionError: title: Błąd usuwania - text: >- - Nie udało się usunąć zapisu: - + text: "Nie udało się usunąć zapisu:" restartRequired: title: Wymagany restart - text: >- - Gra wymaga ponownego uruchomienia w celu zastosowania nowych ustawień. - + text: Gra wymaga ponownego uruchomienia w celu zastosowania nowych ustawień. editKeybinding: title: Zmień klawiszologię - desc: Naciśnij klawisz bądź przycisk myszy, który chcesz przypisać lub wciśnij Escape, aby anulować. - + desc: Naciśnij klawisz bądź przycisk myszy, który chcesz przypisać lub wciśnij + Escape, aby anulować. resetKeybindingsConfirmation: title: Zresetuj klawiszologię - desc: Ta akcja zresetuje wszystkie ustawienia klawiszologii do domyślnych wartości. Proszę potwierdzić. - + desc: Ta akcja zresetuje wszystkie ustawienia klawiszologii do domyślnych + wartości. Proszę potwierdzić. keybindingsResetOk: title: Reset Klawiszologii desc: Klawiszologia została przywrócona do ustawień domyślnych! - featureRestriction: - title: Wersja Demo - desc: Próbujesz skorzystać z "", który nie jest dostępny w wersji demo. Rozważ zakup gry dla pełni doświadczeń! - + title: Wersja Demonstracyjna + desc: Próbujesz skorzystać z "", który nie jest dostępny w wersji demo. + Rozważ zakup pełnej wersji gry dla pełni doświadczeń! oneSavegameLimit: title: Limit Zapisów Gry - desc: W wersji demo możesz posiadać wyłącznie jeden zapis gry. Proszę usuń obecny lub zakup pełną wersję gry! - + desc: W wersji demo możesz posiadać wyłącznie jeden zapis gry. Proszę usuń + obecny lub zakup pełną wersję gry! updateSummary: title: Nowa aktualizacja! - desc: >- - Lista zmian od Twojej ostatniej rozgrywki: - + desc: "Lista zmian od Twojej ostatniej rozgrywki:" upgradesIntroduction: title: Ulepszenia - desc: >- - Wszystkie kształty, które produkujesz, mogą zostać użyte do ulepszeń - Nie niszcz starych fabryk! - Zakładka "Ulepszenia" dostępna jest w prawym górnym rogu. - + desc: Wszystkie kształty, które produkujesz, mogą zostać użyte do ulepszeń - + Nie niszcz starych fabryk! Zakładka "Ulepszenia" + dostępna jest w prawym górnym rogu. massDeleteConfirm: title: Potwierdź Usuwanie - desc: >- - Usuwasz sporą ilość maszyn ( gwoli ścisłości)! Czy na pewno chcesz kontynuować? - + desc: Usuwasz sporą ilość maszyn ( gwoli ścisłości)! Czy na pewno chcesz + kontynuować? blueprintsNotUnlocked: title: Jeszcze Nie Odblokowane - desc: >- - Schematy nie zostały jeszcze odblokowane! Awansuj poziomami, by odblokować. - + desc: Schematy nie zostały jeszcze odblokowane! Awansuj poziomami, by + odblokować. keybindingsIntroduction: title: Przydatna Klawiszologia - desc: >- - Gra posiada sporą gamę kombinacji klawiszy upraszczających budowę dużych fabryk. - Oto kilka z nich, lecz nie zmienia to faktu iż warto sprawdzić dostępne kombinacje!

- CTRL + Przeciąganie: Zaznacz obszar do kopiowania/usuwania.
- SHIFT: Przytrzymaj, by wstawić więcej niż jeden budynek.
- ALT: Odwróć orientację stawianych taśmociągów.
- + desc: "Gra posiada sporą gamę kombinacji klawiszy upraszczających budowę dużych + fabryk. Oto kilka z nich, lecz nie zmienia to faktu iż warto + sprawdzić dostępne kombinacje!

CTRL + Przeciąganie: Zaznacz obszar do + kopiowania/usuwania.
SHIFT: + Przytrzymaj, by wstawić więcej niż jeden budynek.
ALT: Odwróć orientację stawianych + taśmociągów.
" createMarker: title: Nowy Znacznik - desc: Podaj nazwę znacznika. Możesz w niej zawrzeć kod kształtu, który możesz wygenerować tutaj. + desc: Nadaj mu nazwę. Możesz w niej zawrzeć kod kształtu (Który + możesz wygenerować tutaj) 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! - + desc: Możesz stworzyć tylko dwa własne znaczniki w wersji demo. Zakup pełną + wersję gry dla nielimitowanych znaczników! massCutConfirm: title: Potwierdź wycinanie - desc: >- - Wycinasz sporą ilość maszyn ( gwoli ścisłości)! Czy na pewno chcesz kontynuować? - + desc: Wycinasz sporą ilość maszyn ( gwoli ścisłości)! Czy na pewno chcesz + kontynuować? exportScreenshotWarning: title: Tworzenie zrzutu fabryki - desc: >- - Zamierzasz wyeksportować swoją fabrykę jako zrzut ekranu. W przypadku dużej - fabryki ta akcja może być bardzo wolna, a nawet może spowodować zawieszenie się lub awarię gry! - Czy na pewno chcesz kontynuować? - + desc: Zamierzasz wyeksportować swoją fabrykę jako zrzut ekranu. W przypadku + dużej fabryki ta akcja może być bardzo wolna, a nawet może + spowodować zawieszenie się lub awarię gry! Czy na pewno chcesz + kontynuować? massCutInsufficientConfirm: - title: Potwierdź cięcie - desc: Nie możesz sobie pozwolić na wklejenie tego obszaru! Czy na pewno chcesz to wyciąć? - + title: Potwierdź wycinanie + desc: Nie posiadasz wystarczająco kształtów schematów na wklejenie tego obszaru! + Czy na pewno chcesz go wyciąć? + editSignal: + title: Ustaw Sygnał + descItems: "Ustaw wcześniej zdefiniowany przedmiot:" + descShortKey: ... albo wpisz kod kształtu (Który możesz + wygenerować tutaj) + renameSavegame: + title: Zmień nazwę zapisu gry + desc: Tutaj możesz zmienić nazwę zapisu gry. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Ruch selectBuildings: Zaznacz @@ -299,9 +234,7 @@ ingame: copySelection: Skopiuj clearSelection: Wyczyść zaznaczenie pipette: Wybierz obiekt z mapy - switchLayers: Switch layers - - # Names of the colors, used for the color blind mode + switchLayers: Przełącz warstwy colors: red: Czerwony green: Zielony @@ -311,19 +244,10 @@ ingame: cyan: Cyjanowy white: Biały uncolored: Brak koloru - black: Black - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + black: Czarny 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: Naciśnij , by zmieniać warianty. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Skrót: - + hotkeyLabel: "Skrót: " infoTexts: speed: Szybkość range: Zasięg @@ -331,38 +255,21 @@ ingame: oneItemPerSecond: 1 obiekt / s itemsPerSecond: obiektów / s itemsPerSecondDouble: (x2) - tiles: kafelków - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Poziom completed: Ukończono unlockText: Odblokowano ! buttonNextLevel: Następny Poziom - - # Notifications on the lower right notifications: newUpgrade: Nowe ulepszenie dostępne! gameSaved: Postęp gry został zapisany. - - # The "Upgrades" window + freeplayLevelComplete: Poziom został ukończony! shop: title: Ulepszenia buttonUnlock: Ulepsz - - # Gets replaced to e.g. "Tier IX" - # Translator note: translated into "rank" - # 2nd translator's note: I think translating this to "level" is better (and that's how Google Translate translates it :)) tier: Poziom - - # The roman numeral for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: POZIOM MAKSYMALNY (Szybkość x) - - # The "Statistics" window statistics: title: Statystyki dataSources: @@ -371,61 +278,111 @@ ingame: description: Wyświetla ilość przechowywanych kształtów w głównym budynku. produced: title: Produkowane - description: Wyświetla wszystkie kształty produkowane przez Twoją fabrykę, w tym półprodukty. + description: Wyświetla wszystkie kształty produkowane przez Twoją fabrykę, w tym + półprodukty. delivered: title: Dostarczone description: Wyświetla kształty dostarczone do budynku głównego. noShapesProduced: Brak wyprodukowanych kształtów. - - # Displays the shapes per minute, e.g. '523 / m' - # Translator note: user "min" to distinguish from "meters" - shapesPerMinute: / min - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / sek. + minute: / min. + hour: / godz. settingsMenu: playtime: Czas Gry - buildingsPlaced: Budynki beltsPlaced: Taśmociągi - - buttons: - continue: Kontynuuj - settings: Ustawienia - menu: Powrót do menu - - # Bottom left tutorial hints tutorialHints: title: Potrzebujesz pomocy? showHint: Pokaż Wskazówkę hideHint: Zamknij - - # When placing a blueprint blueprintPlacer: cost: Koszt - - # Map markers waypoints: waypoints: Znaczniki hub: Budynek Główny - description: Kliknij znacznik lewym przyciskiem myszy, by się do niego przenieść lub prawym, by go usunąć.

Naciśnij , by stworzyć marker na środku widoku lub prawy przycisk myszy, by stworzyć na wskazanej lokacji. - creationSuccessNotification: Utworzono znacznik. - - # Shape viewer + description: Kliknij znacznik lewym przyciskiem myszy, by się do niego przenieść + lub prawym, by go usunąć.

Naciśnij , by stworzyć + marker na środku widoku lub prawy przycisk myszy, + by stworzyć na wskazanej lokacji. + creationSuccessNotification: Pomyślnie utworzono znacznik. shapeViewer: - title: Poziomy + title: Warstwy empty: Puste - copyKey: Copy Key - - # Interactive tutorial + copyKey: Skopiuj kod interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Postaw ekstraktor na źródle kształtu koła, aby go wydobyć! - 1_2_conveyor: >- - Połącz ekstraktor taśmociągiem do głównego budynku!

Porada: Kliknij i przeciągnij taśmociąg myszką! - 1_3_expand: >- - To NIE JEST gra "do poczekania"! Buduj więcej taśmociągów i ekstraktorów, by wydobywać szybciej.

Porada: Przytrzymaj SHIFT, by postawić wiele ekstraktorów. Naciśnij R, by je obracać. -# All shop upgrades + 1_1_extractor: Postaw ekstraktor na źródle kształtu + koła, aby go wydobyć! + 1_2_conveyor: "Połącz ekstraktor taśmociągiem do głównego + budynku!

Porada: Kliknij i przeciągnij + taśmociąg myszką!" + 1_3_expand: 'To NIE JEST gra "do poczekania"! Buduj więcej + taśmociągów i ekstraktorów, by wydobywać + szybciej.

Porada: Przytrzymaj SHIFT, by + postawić wiele ekstraktorów. Naciśnij R, by je + obracać.' + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." + connectedMiners: + one_miner: 1 ekstraktor + n_miners: ekstraktorów + limited_items: Ograniczone do + watermark: + title: Wersja demo + desc: Kliknij tutaj, aby zobaczyć co potrafi wersja Steam! + get_on_steam: Kup na Steam + standaloneAdvantages: + title: Kup pełną wersję! + no_thanks: Nie, dziękuję! + points: + levels: + title: 12 Nowych Poziomów + desc: Aby otrzymać 26 poziomów! + buildings: + title: 18 Nowych Budynków + desc: W pełni zautomatyzuj produkcję! + savegames: + title: ∞ Zapisów Gry + desc: Twórz tyle, ile potrzebujesz! + upgrades: + title: 20 Poziomów Ulepszeń + desc: To demo posiada tylko 5! + markers: + title: ∞ Znaczników + desc: Nigdy nie zgub się w swojej fabryce! + wires: + title: Przewody + desc: Całkowicie nowy wymiar! + darkmode: + title: Tryb Ciemny + desc: Przestań psuć swój wzrok! + support: + title: Wspomóż mnie + desc: Tworzę tą grę w swoim wolnym czasie! shopUpgrades: belt: name: Taśmociągi, Dystrybutory & Tunele @@ -439,256 +396,412 @@ shopUpgrades: painting: name: Miksowanie & Malowanie description: Szybkość x → x - -# Buildings and their name / description buildings: hub: deliver: Dostarcz toUnlock: by odblokować levelShortcut: Poz. - + endOfDemo: Koniec wersji demonstracyjnej belt: default: - name: &belt Taśmociąg + name: Taśmociąg description: Transportuje obiekty, przytrzymaj i przeciągnij, by postawić kilka. - - miner: # Internal name for the Extractor + miner: default: - name: &miner Ekstraktor + name: Ekstraktor description: Postaw na źródle kształtów, by je wydobyć. - chainable: name: Ekstraktor (Łańcuchowy) - description: Postaw na źródle kształtów, by je wydobyć. Mogą być połączone szeregowo. - - underground_belt: # Internal name for the Tunnel + description: Postaw na źródle kształtów, by je wydobyć. Mogą być połączone + szeregowo. + underground_belt: default: - name: &underground_belt Tunel + name: Tunel description: Pozwala na transport podziemnym tunelem. - tier2: name: Tunel Poziomu II - description: Pozwala na transport podziemnym tunelem. Nie łączy się z Tunelami Poziomu I. - - splitter: # Internal name for the Balancer - default: - name: &splitter Rozdzielacz - description: Wielofunkcyjny - Równo dystrybuuje obiekty wejściowe do wyjść. - - compact: - name: Łącznik (Kompaktowy) - description: Łączy dwa osobne taśmociągi w jeden. - - compact-inverse: - name: Łącznik (Kompaktowy) - description: Łączy dwa osobne taśmociągi w jeden. - + description: Pozwala na transport podziemnym tunelem. Nie łączy się z Tunelami + Poziomu I. cutter: default: - name: &cutter Przecinak - description: Tnie kształty i oddaje wycięte połówki. Jeśli korzystasz tylko z jednej połówki, upewnij się, że niszczysz drugą, by nie zatkać budynku! + name: Przecinak + description: Tnie kształty i oddaje wycięte połówki. Jeśli korzystasz + tylko z jednej połówki, upewnij się, że niszczysz drugą, by nie + zatkać budynku! quad: name: Przecinak (Poczwórny) - description: Tnie kształty na cztery ćwiartki. Jeśli nie korzystasz z wszystkich ćwiartek, upewnij się, że niszczysz pozostałe, by nie zatkać budynku! - + description: Tnie kształty na cztery ćwiartki. Jeśli nie korzystasz z + wszystkich ćwiartek, upewnij się, że niszczysz pozostałe, by nie + zatkać budynku! rotater: - # 2nd translator's note: CW & CCW could be changed to right & left to make the description shorter. - # Another 2nd translator's note: If you start naming the buildings as "tools to do something", keep naming them like that. Don't suddenly start naming them as "processes" they do default: - name: &rotater Obracacz + name: Obracacz description: Obraca kształt zgodnie z ruchem wskazówek zegara o 90 stopni. ccw: name: Obracacz (Przeciwny kierunek) description: Obraca kształt przeciwnie do ruchu wskazówek zegara o 90 stopni. - + rotate180: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: - name: &stacker Sklejacz - description: Skleja obiekty. Jeśli obiekty nie mogą być sklejone, obiekt z prawej jest nakładany na ten z lewej. - + name: Sklejacz + description: Skleja obiekty. Jeśli obiekty nie mogą być sklejone, obiekt z + prawej jest nakładany na ten z lewej. mixer: default: - name: &mixer Mieszadło Kolorów + name: Mieszadło Kolorów description: Miesza kolory dodając kolory do siebie. - painter: - # 2nd translator's note: All those buildings had different descriptions in english. Don't change them all to the same description. default: - name: &painter Malarz - description: &painter_desc Koloruje kształt za pomocą koloru dostarczonego od boku. + name: Malarz + description: Koloruje kształt za pomocą koloru dostarczonego od boku. double: name: Malarz (Podwójny) - description: Koloruje kształt za pomocą koloru dostarczonego od boku. Koloruje 2 kształty używając 1 barwnika. + description: Koloruje kształt za pomocą koloru dostarczonego od boku. Koloruje 2 + kształty używając 1 barwnika. quad: name: Malarz (Poczwórny) - description: Koloruje każdą ćwiartkę kształtu na inny kolor, używając dostarczonych kolorów. + description: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! mirrored: - name: *painter - description: *painter_desc - + name: Malarz + description: Koloruje kształt za pomocą koloru dostarczonego od boku. trash: default: - name: &trash Śmietnik + name: Śmietnik description: Przyjmuje obiekty z każdej ze stron i je usuwa. Na zawsze. - - storage: - name: Magazyn - 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. - advanced_processor: + name: Przewód energetyczny + description: Pozwala na transportowanie energii. + second: + name: Przewód logiczny + description: Przekazuje sygnały, które mogą być w postaci przedmiotów, kolorów + lub wartości typu Prawda/Fałsz. Przewody o różnych kolorach nie + łączą sie ze sobą. + balancer: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For - default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Dystrybutor + description: Wielofunkcyjny - Równo rozdziela wszystkie kształty wejściowe do + wyjść. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Łącznik (kompaktowy) + description: Łączy dwa taśmociągi w jeden. + merger-inverse: + name: Łącznik (kompaktowy) + description: Łączy dwa taśmociągi w jeden. + splitter: + name: Rozdzielacz (kompaktowy) + description: Rozdziela jeden taśmociąg na dwa. + splitter-inverse: + name: Rozdzielacz (kompaktowy) + description: Rozdziela jeden taśmociąg na dwa. + storage: + default: + name: Magazyn + description: Przechowuje dodatkowe przedmioty, do pewnej ilości. Może zostać + użyty jako brama przepełnieniowa. Prawe wyjście posiada większy + piorytet. + wire_tunnel: + default: + name: Skrzyżowanie przewodów + description: Pozwala na skrzyżowanie dwóch przewodów bez ich łączenia. + constant_signal: + default: + name: Stały sygnał + description: Emituje stały sygnał, który może być w postaci przedmiotu, koloru + lub wartości typu Prawda/Fałsz. + lever: + default: + name: Przełącznik + description: "Może zostać przełączony, by emitować sygnał typu prawda/fałsz, co + pozwala na przykład: na przełączanie filtra przedmiotów." + logic_gate: + default: + name: Bramka AND + description: Emituje sygnał "Prawda", jeżeli oba wejścia są wartością typu + Prawda. (Prawda oznacza dowolny kształt lub kolor, a także + sygnał "Prawda") + not: + name: Bramka NOT + description: Emituje sygnał "Prawda", jeżeli wejście NIE jest wartością typu + Prawda. (Prawda oznacza dowolny kształt lub kolor, a także + sygnał "Prawda") + xor: + name: Bramka XOR + description: Emituje sygnał "Prawda", jeżeli tylko jedno wejście jest wartością + typu Prawda. (Prawda oznacza dowolny kształt lub kolor, a także + sygnał "Prawda") + or: + name: Bramka OR + description: Emituje sygnał "Prawda", jeżeli dowolne wejście jest wartością typu + Prawda. (Prawda oznacza dowolny kształt lub kolor, a także + sygnał "Prawda") + transistor: + default: + name: Tranzystor + description: Przekazuje dolne wejście, jeżeli wejście boczne jest wartością typu + Prawda. (Prawda oznacza dowolny kształt lub kolor, a także + sygnał "Prawda") + mirrored: + name: Tranzystor + description: Przekazuje dolne wejście, jeżeli wejście boczne jest wartością typu + Prawda. (Prawda oznacza dowolny kształt lub kolor, a także + sygnał "Prawda") + filter: + default: + name: Filtr + description: Podłącz sygnał, by przekierować wszystkie pasujące przedmioty na + górę, a resztę na prawo. Może być również sterowany za pomocą + sygnałów Prawda/Fałsz. + display: + default: + name: Wyświetlacz + description: Podłącz sygnał, by pokazać go na wyświetlaczu - Może on być + kształtem, kolorem lub wartością Prawda/Fałsz. + reader: + default: + name: Czytnik taśmociągów + description: Pozwala na odczytywanie średniej przepustowości taśmociągu. Emituje + ostatnio odczytany przedmiot na warstwie przewodów (gdy ją + odblokujesz). + analyzer: + default: + name: Analizator kształtów + description: Analizuje prawą górną ćwiartkę najniższej warstwy i zwraca jej + kształt i kolor. + comparator: + default: + name: Porównywacz + description: Zwraca sygnał "Prawda", jeżeli oba sygnały są dokładnie takie same. + Działa na kształtach, kolorach i wartościach Prawda/Fałsz. + virtual_processor: + default: + name: Wirtualny Przecinak + description: Wirtualnie przecina kształt na 2 połówki + rotater: + name: Wirtualny Obracacz + description: Wirtualnie obraca kształt, potrafi to robić w oba kierunki. + unstacker: + name: Wirtualny Odklejacz + description: Wirtualnie oddziela najwyższą warstwę na prawe wyjście i resztę na + lewe. + stacker: + name: Wirtualny Sklejacz + description: Wirtualnie skleja prawy kształt na lewy. + painter: + name: Wirtualny Malarz + description: Wirtualnie maluje kształt z dolnego wejścia barwnikiem z prawego + wejścia. + item_producer: + default: + name: Producent kształtów + description: Dostępne tylko w trybie piaskownicy. Produkuje przedmioty z sygnału + danego na warstwie przewodów na główną warstwę. storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Przecinanie Kształtów - desc: >- - Odblokowano nową maszynę: Przecinak - tnie kształt na pół pionowo - od góry do dołu, niezależnie od orientacji!

Upewnij się, że zniszczysz niechciane kawałki, ponieważ może się zatkać - Na potrzeby tego otrzymujesz też kosz - niszczy wszystko co do niego przekierujesz! - + desc: Właśnie odblokowałeś przecinaka, który przecina kstałty + na pół od góry na dół bez znaczenia na ich + orientację!

Upewnij się, że usuwasz śmieci - w + przeciwnym przypadku maszyna zapcha się i przestanie + działać! Do tego celu dałem ci śmietnik, + który usuwa wszystko, co do niego włożysz! reward_rotater: title: Obracanie - desc: >- - Odblokowano nową maszynę: Obracacz! Obraca wejście o 90 stopni zgodnie ze wskazówkami zegara. - - #2nd translator's note: "Color objects" should be translated as "dye" + desc: "Odblokowano nową maszynę: Obracacz! Obraca wejście o 90 + stopni zgodnie ze wskazówkami zegara." reward_painter: title: Malowanie - desc: >- - Odblokowano nową maszynę: Maszyna Malująca - wydobądź kilka pigmentów (identycznie jak kształty) i połącz je z kształtami aby je pomalować!

PS: Jeśli nie widzisz kolorów, w ustawieniach znajduje się color blind mode! - + desc: "Odblokowano nową maszynę: Maszyna Malująca - wydobądź + kilka barwników (identycznie jak kształty) i połącz je z kształtami + aby je pomalować!

PS: Jeśli nie widzisz kolorów, w + ustawieniach znajduje się tryb dla daltonistów!" reward_mixer: title: Mieszanie - desc: >- - Odblokowano nową maszynę: Mieszadło Kolorów - Złącz dwa kolory z pomocą modelu addytywnego dzięki tej maszynie! - + desc: "Odblokowano nową maszynę: Mieszadło Kolorów - Złącz dwa + kolory z pomocą modelu addytywnego dzięki tej + maszynie!" reward_stacker: title: Sklejanie - desc: >- - Odblokowano nową maszynę: Sklejacz - łączy dwa kształty w jeden! Jeżeli obiekty mogą zostać sklejone, są łączone w jeden kształt. Jeśli nie mogą zostać sklejone, kształt po prawej jest kładziony na ten z lewej! - + desc: "Odblokowano nową maszynę: Sklejacz - łączy dwa kształty + w jeden! Jeżeli obiekty mogą zostać sklejone, są łączone w + jeden kształt. Jeśli nie mogą zostać sklejone, + kształt po prawej jest kładziony na ten z lewej!" reward_splitter: title: Rozdzielacz/Łącznik - desc: Wielofunkcyjne urządzenie balansujące zostało odblokowane - Może zostać wykorzystane do tworzenia większych fabryk poprzez rozdzielanie i łączenie taśmociągów!

- + desc: Właśnie odblokowałeś rozdzielacz - typ + dystrybutor, który akceptuje jedno wejście i + rozdziela je na dwa! reward_tunnel: title: Tunel - desc: Tunel został odblokowany - Możesz teraz prowadzić podziemne taśmociągi! - + desc: Tunel został odblokowany - Możesz teraz prowadzić + podziemne taśmociągi! reward_rotater_ccw: title: Obracanie odwrotne - desc: Odblokowano nowy wariant Obracacza - Pozwala odwracać przeciwnie do wskazówek zegara! Aby zbudować, zaznacz Obracacz i naciśnij 'T', by zmieniać warianty! - + desc: Odblokowano nowy wariant Obracacza - Pozwala odwracać + przeciwnie do wskazówek zegara! Aby zbudować, zaznacz Obracacz i + naciśnij 'T', by zmieniać warianty! reward_miner_chainable: title: Wydobycie Łańcuchowe - desc: Odblokowano nowy wariant ekstraktora! Może przekierować obiekty do ekstraktorów przed nim, zwiększając efektywność wydobycia! - + desc: "Właśnie odblokowałeś łańcuchowy ekstraktor! Może on + przekazywać swoje surowce do innych ekstraktorów, + byś mógł bardziej efektywnie wydobywać surowce!

PS: Stary + ekstraktor na pasku narzędzi został teraz zastąpiony nowym!" reward_underground_belt_tier_2: title: Tunel Poziomu II - desc: Odblokowano nowy wariant tunelu - Posiada większy zasięg i nie koliduje z trasami tych krótszych tuneli! - - reward_splitter_compact: - title: Łącznik Kompaktowy - desc: >- - Odblokowano nowy wariant rozdzielacza - Przyjmuje - przedmioty z dwóch taśmociągów i przenosi je na jeden! - + desc: Odblokowano nowy wariant tunelu - Posiada większy + zasięg i nie koliduje z trasami tych krótszych + tuneli! reward_cutter_quad: title: Przecinak Poczwórny - desc: Odblokowano nowy wariant Przecinaka - Pozwala ciąć kształty na cztery ćwiartki! - + desc: Odblokowano nowy wariant Przecinaka - Pozwala ciąć + kształty na cztery ćwiartki! reward_painter_double: title: Podwójne Malowanie - desc: Odblokowano nowy wariant Malarza - Działa jak zwykły malarz, z tą różnicą, że maluje dwa kształty na raz, pobierając wyłącznie jeden barwnik! - - reward_painter_quad: - title: Poczwórne malowanie - desc: Odblokowano nowy wariant Malarza - Pozwala malować każdą ćwiartkę kształtu na inny kolor! - + desc: Odblokowano nowy wariant Malarza - Działa jak zwykły + malarz, z tą różnicą, że maluje dwa kształty na + raz, pobierając wyłącznie jeden barwnik! reward_storage: title: Magazyn - desc: Odblokowano nowy wariant Kosza - Pozwala przechować pewną ilość obiektów! - + desc: Właśnie odblokowałeś magazyn - Pozwala na przecowywanie + przedmiotów, do pewnej ilości!

Prawe wyjście posiada większy + piorytet, więc może być on użyty jako brama + przepełnieniowa! reward_freeplay: title: Tryb swobodny - desc: Gratulacje! Odblokowano tryb swobodny! Oznacza to, iż kształty są teraz generowane losowo! (Nie przejmuj się, więcej zawartości jest w planach dla wersji pełnej!) - + desc: Udało ci się! Odblokowałeś tryb swobodny! To oznacza, że + kształty są teraz losowo generowane!

Od + teraz budynek główny będzie wymagał odpowiedniej + przepustowości kształtów, zatem sugeruję budowę + maszyny, która będzie atuomatycznie dostarczała wymagany + kształt!

Budynek główny emituje wymagany kształt na warstwie + przewodów, więc wystarczy analizować ten sygnał i konfigurować + fabrykę bazując na nim. reward_blueprints: title: Schematy - desc: >- - Możesz teraz kopiować i wklejać części swojej fabryki! - Zaznacz obszar (Przytrzymaj CTRL, a następnie przeciągnij myszą) i naciśnij 'C', - by go skopiować.

Wklejanie nie jest darmowe - musisz - produkować kształty schematów (te, które właśnie dostarczyłeś), - by móc wklejać! - - # Special reward, which is shown when there is no reward actually + desc: Możesz teraz kopiować i wklejać części swojej fabryki! + Zaznacz obszar (Przytrzymaj CTRL, a następnie przeciągnij myszą) i + naciśnij 'C', by go skopiować.

Wklejanie nie jest + darmowe - musisz produkować kształty + schematów (te, które właśnie dostarczyłeś), by móc wklejać! no_reward: title: Następny Poziom - desc: >- - Ten poziom nie daje nagrody, lecz kolejny już tak!

PS: Lepiej nie niszczyć istniejących fabryk - Potrzebujesz wszystkich kształtów w późniejszych etapach, by odblokować ulepszenia! - + desc: "Ten poziom nie daje nagrody, lecz kolejny już tak!

PS: Lepiej + nie niszczyć istniejących fabryk - Potrzebujesz + wszystkich kształtów w późniejszych etapach, by + odblokować ulepszenia!" no_reward_freeplay: title: Następny Poziom - desc: >- - Gratulacje! Przy okazji, więcej zawartości jest w planach dla wersji pełnej! - + desc: Gratulacje! Przy okazji, więcej zawartości jest w planach dla wersji + pełnej! + reward_balancer: + title: Dystrybutor + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Kompaktowy łącznik + desc: Właśnie odblokowałeś łącznik - typ + dystrybutora, który akceptuje dwa wejścia i łączy + je na jeden taśmociąg! + reward_belt_reader: + title: Czytnik taśmociągów + desc: Właśnie odblokowałeś czytnik taśmociągów! Pozwala ci na + mierzenie przepustowości taśmociągu.

Czekaj tylko, aż + odblokujesz przewody logiczne - dopiero wtedy staje się bardzo + użyteczny! + reward_rotater_180: + title: Obracacz (180°) + desc: Właśnie odblokowałeś kolejny wariant obraczacza! - + Pozwala ci na obrócenie kształtu o 180 stopni! + reward_display: + title: Wyświetlacz + desc: "Właśnie odblokowałeś Wyświetlacz - Podłącz sygnał na + warstwie przewodów, by go zwizualizować!

PS: Czy zauważyłeś, + że czytnik taśmociągów i magazyn emitują ostatni przedmiot jako + sygnał? Spróbuj wyświetlić go na wyświetlaczu!" + reward_constant_signal: + title: Stały sygnał + desc: "Właśnie odblokowałeś budynek emitujący stały sygnał na + warstwie przewodów! Jest on przydatny na przykład: do ustawiania + filtrów

Sygnał może być + kształtem, kolorem lub wartością + Prawda/Fałsz." + reward_logic_gates: + title: Bramki logiczne + desc: Właśnie odblokowałeś bramki logiczne! Nie musisz być z + tego powodu podekscytowany, ale one są bardzo fajne!

Z tymi + bramkami możesz teraz wykonywać operacje AND, OR, XOR i NOT.

+ Dodatkowo dałem ci tranzystor! + reward_virtual_processing: + title: Wirtualne przetwarzanie + desc: Właśnie dałem ci mnóstwo budynków, które pozwolą ci symulować + przetwarzanie kształtów!

Możesz teraz symulować + przecinaka, obracacza, sklejacza i wiele więcej na warstwie + przewodów! Teraz masz trzy opcje na kontynuację gry:

- + Zbuduj zautomatyzowaną maszynę, która stworzy każdy + kstałt ządany przez budynek główny (Polecam tą opcję!).

- + Zbuduj coś ciekawego za pomocą przewodów.

- Kontynuuj zwykłą + rozgrywkę.

Cokolwiek wybierzesz, pamiętaj by się dobrze + bawić! + reward_wires_painter_and_levers: + title: Przewody i poczwórny malarz + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Filtr przedmiotów + desc: Właśnie odblokowałeś Filtr Przedmiotów! Będzie on + przekirowywał przedmioty do górnego lub prawego wyjścia, zależnie od + tego, czy pasują one do sygnału z warstwy przewodów.

Możesz + również przekazać sygnał typu Prawda/Fałsz, by całkowicie go włączyć + lub wyłączyć. + reward_demo_end: + title: Koniec wersji demo + desc: Dotarłeś do końca wersji demo! settings: title: Ustawienia categories: - game: Gra - app: Aplikacja - + general: Ogólne + userInterface: Interfejs + advanced: Zaawansowane + performance: Wydajność versionBadges: dev: Wersja Rozwojowa staging: Wersja eksperymentalna prod: Wersja Produkcyjna buildDate: Skompilowano - labels: uiScale: title: Skala Interfejsu - description: >- - Zmienia rozmiar interfejsu. Skala będzie dopasowana względem rozdzielczości Twojego ekranu. + description: Zmienia rozmiar interfejsu. Skala będzie dopasowana względem + rozdzielczości Twojego ekranu. scales: super_small: Bardzo Mała small: Mała regular: Zwykła large: Duża huge: Ogromna - scrollWheelSensitivity: title: Czułość Przybliżania - description: >- - Zmienia czułość przybliżania/oddalania. + description: Zmienia czułość przybliżania/oddalania. sensitivity: super_slow: Bardzo mała slow: Mała regular: Zwykła fast: Duża super_fast: Bardzo Duża - movementSpeed: title: Prędkość poruszania - description: >- - Zmienia, jak szybko widok porusza się, używając skrótów klawiszowych. + description: Zmienia, jak szybko widok porusza się, używając skrótów + klawiszowych. speeds: super_slow: Bardzo wolna slow: Wolna @@ -696,65 +809,52 @@ settings: fast: Szybka super_fast: Bardzo szybka extremely_fast: Ekstremalnie szybka - language: title: Język - description: >- - Zmień Język. Wszystkie tłumaczenia są tworzone przez społeczność i mogą nie być w pełni ukończone! - + description: Zmień Język. Wszystkie tłumaczenia są tworzone przez społeczność i + mogą nie być w pełni ukończone! fullscreen: title: Pełny Ekran - description: >- - Zachęcamy do gry w pełnym ekranie dla lepszej rozgrywki. Dostępne tylko w pełnej wersji gry. - + description: Zachęcamy do gry w pełnym ekranie dla lepszej rozgrywki. Dostępne + tylko w pełnej wersji gry. soundsMuted: title: Wycisz Dźwięki - description: >- - Jeżeli włączone, wycisza wszystkie efekty dźwiękowe. - + description: Jeżeli włączone, wycisza wszystkie efekty dźwiękowe. musicMuted: title: Wycisz Muzykę - description: >- - Jeżeli włączone, wycisza muzykę. - + description: Jeżeli włączone, wycisza muzykę. theme: title: Motyw Graficzny Gry - description: >- - Wybierz motyw (jasny / ciemny). + description: Wybierz motyw (jasny / ciemny). themes: dark: Ciemny light: Jasny - refreshRate: title: Częstość Odświeżania - description: >- - Jeśli posiadasz monitor z częstotliwością odświeżania 144hz, zmień tę opcje na poprawną częstotliwość odświeżania ekranu. Może to wpłynąć na FPS jeśli masz za wolny komputer. - + description: Jeśli posiadasz monitor z częstotliwością odświeżania 144hz, zmień + tę opcje na poprawną częstotliwość odświeżania ekranu. Może to + wpłynąć na FPS jeśli masz za wolny komputer. alwaysMultiplace: title: Wielokrotne budowanie - description: >- - Jeżeli włączone, nie anuluje budowy po postawieniu maszyny. Odpowiednik ciągłego trzymania klawisza SHIFT. - + description: Jeżeli włączone, nie anuluje budowy po postawieniu maszyny. + Odpowiednik ciągłego trzymania klawisza SHIFT. offerHints: title: Porady i Tutoriale - description: >- - Oferuje porady i tutoriale podczas gry. Dodatkowo chowa pewne elementy interfejsu, by ułatwić poznanie gry. - + description: Oferuje porady i tutoriale podczas gry. Dodatkowo chowa pewne + elementy interfejsu, by ułatwić poznanie gry. enableTunnelSmartplace: title: Inteligentne taśmociągi i tunele - description: >- - Gdy włączone, umieszczenie tunelu automatycznie usuwa zbędny taśmociąg. - Pozwala również budować tunele przez przeciąganie, gdyż niepotrzebne tunele zostają usunięte. + description: Gdy włączone, umieszczenie tunelu automatycznie usuwa zbędny + taśmociąg. Pozwala również budować tunele przez przeciąganie, + gdyż niepotrzebne tunele zostają usunięte. vignette: title: Winieta - description: >- - Włącza winietę - przyciemnia rogi ekranu, poprawiając czytelność tekstu. - + description: Włącza winietę - przyciemnia rogi ekranu, poprawiając czytelność + tekstu. autosaveInterval: title: Częstość auto-zapisu - description: >- - Zmienia, jak często gra automatycznie zapisuje fabrykę. - Można tą funkcję również całkowicie wyłączyć. + description: Zmienia, jak często gra automatycznie zapisuje fabrykę. Można tą + funkcję również całkowicie wyłączyć. intervals: one_minute: Co minutę two_minutes: Co 2 minuty @@ -762,35 +862,79 @@ settings: ten_minutes: Co 10 minut twenty_minutes: Co 20 minut disabled: Wyłączone - compactBuildingInfo: title: Wyłącz opis budynków - description: >- - Ukrywa opis i zdjęcie budynków w obszarze informacyjnym, pokazując jedynie - ich tytuł i specyfikacje techniczne. - + description: Ukrywa opis i zdjęcie budynków w obszarze informacyjnym, pokazując + jedynie ich tytuł i specyfikacje techniczne. disableCutDeleteWarnings: title: Wyłącz ostrzeżenia usuwania/wycinania - description: >- - Wyłącza ostrzeżenia wyświetlające się przy usuwaniu lub wycinaniu więcej niż - 100 budynków. - + description: Wyłącza ostrzeżenia wyświetlające się przy usuwaniu lub wycinaniu + więcej niż 100 budynków. enableColorBlindHelper: - title: Tryb ślepy na kolory - description: Włącza różne narzędzia, które pozwalają ci grać, jeśli jesteś daltonistą. + title: Tryb dla daltonistów + description: Włącza różne narzędzia, które pozwalają ci grać, jeśli jesteś + daltonistą. rotationByBuilding: title: Obrót według typu budynku - description: >- - 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. - + description: 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. + soundVolume: + title: Głośność dźwięków + description: Ustaw głośnośc efektów dźwiękowych + musicVolume: + title: Głośnosć muzyki + description: Ustaw głośność muzyki + lowQualityMapResources: + title: Zasoby mapy o niskiej jakości + description: Upraszcza renderowanie zasobów na mapie, gdy kamera jest + przybliżona, by zwiększyć wydajność. Wygląda to nawet ładnie, + więc wypróbuj tą funkcję! + disableTileGrid: + title: Wyłącz siatkę + description: Wyłączenie siatki może pomóc z wydajnością. Oprócz tego, poprawia + wygląd gry! + clearCursorOnDeleteWhilePlacing: + title: Wyczyść kursor przy kliknięciu PPM + description: Domyślnie włączone, resetuje wybrany budynek do budowy, gdy klikasz + prawym przyciskiem myszy. Jeżeli to wyłączysz, możesz usuwać + budynki podczas budowania używając tego samego przycisku. + lowQualityTextures: + title: Tekstury niskiej jakości (Brzydkie) + description: Używa niskej jakości tekstur, by zwiększyć wydajność. Spowoduje to, + że gra będzie wyglądać bardzo brzydko! + displayChunkBorders: + title: Wyświetl granice chunków + description: Gra jest podzielona na chunki o wielkości 16x15 kratek. Włączenie + tego ustawienia powoduje wyświetlenie granicy każdego chunku. + pickMinerOnPatch: + title: Wybierz ekstraktor zamiast źródła + description: Domyślnie włączone, wybiera ekstraktor, jeżeli spróbujesz wybrać + źródło surowców za pomocą pipety + simplifiedBelts: + title: Uproszczone taśmociągi (Brzydkie) + description: Nie renderuje przedmiotów na taśmociągach, jeżeli nie są zaznaczone + kursorem, by zwiększyć wydajność. Nie zalecam używać tego + ustawienia, chyba że absolutnie potrzebujesz wydajności. + enableMousePan: + title: Włącz przesuwanie myszą + description: Pozwala na poruszanie kamerą poprzez przez przesuwanie kursora do + granicy ekranu. Szybkość jest zależna od ustawienia Prędkość + poruszania. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: Klawiszologia - hint: >- - Wskazówka: Upewnij się, że wykorzystujesz CTRL, SHIFT i ALT! Pozwalają na różne metody kładzenia elementów. + hint: "Wskazówka: Upewnij się, że wykorzystujesz CTRL, SHIFT i ALT! Pozwalają na + różne metody kładzenia elementów." resetKeybindings: Zresetuj Klawiszologię - categoryLabels: general: Aplikacja ingame: Gra @@ -799,7 +943,6 @@ keybindings: massSelect: Zbiorowe Zaznaczenie buildings: Skróty Budynków placementModifiers: Modyfikatory Stawiania - mappings: confirm: Potwierdź back: Wstecz @@ -809,66 +952,74 @@ keybindings: mapMoveLeft: Ruch w lewo mapMoveFaster: Przyspiesz ruch centerMap: Wyśrodkuj Mapę - mapZoomIn: Przybliżenie mapZoomOut: Oddalenie createMarker: Stwórz Znacznik - menuOpenShop: Ulepszenia menuOpenStats: Statystyki - toggleHud: Przełącz widoczność interfejsu toggleFPSInfo: Pokaż Licznik FPS i informacje do debugowania - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + belt: Taśmociąg + underground_belt: Tunel + miner: Ekstraktor + cutter: Przecinak + rotater: Obracacz + stacker: Sklejacz + mixer: Mieszadło Kolorów + painter: Malarz + trash: Śmietnik rotateWhilePlacing: Obróć - rotateInverseModifier: >- - Modyfikator: Obróć Odwrotnie + rotateInverseModifier: "Modyfikator: Obróć Odwrotnie" cycleBuildingVariants: Zmień Wariant confirmMassDelete: Potwierdź usuwanie cycleBuildings: Zmień Budynek - massSelectStart: Przytrzymaj i przeciągnij, by zaznaczyć massSelectSelectMultiple: Zaznacz kilka obszarów massSelectCopy: Skopiuj obszar - 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 lockBeltDirection: Tryb planowania taśmociągu - switchDirectionLockSide: >- - Planowanie taśmociągu: Zmień stronę + switchDirectionLockSide: "Planowanie taśmociągu: Zmień stronę" pipette: Wybieranie obiektów z mapy menuClose: Zamknij Menu - switchLayers: zamknij menu - advanced_processor: Kolor Falownika - energy_generator: Generator Energii - wire: Drut Energetyczny - + switchLayers: Przełącz warstwy + wire: Przewód Energetyczny + balancer: Dystrybutor + storage: Magazyn + constant_signal: Stały Sygnał + logic_gate: Bramka logiczna + lever: Przełącznik + filter: Filtr + wire_tunnel: Skrzyżowanie przewodów + display: Wyświetlacz + reader: Czytnik taśmociągów + virtual_processor: Wirtualny Przetwarzacz + transistor: Tranzystor + analyzer: Analizator Kształtów + comparator: Porównywacz + item_producer: Producent Przedmiotów (Tryb Piaskownicy) + copyWireValue: "Przewody: Skopiuj wartość pod kursorem" about: title: O Grze - body: >- - Ta gra jest open-source. Rozwijana jest przez Tobiasa Springera (to ja).

- Jeżeli chcesz pomóc w rozwoju gry, sprawdź repozytorium shapez.io na Githubie.

- Ta gra nie byłaby możliwa bez wspaniałej społeczności Discord skupionej na moich grach - Naprawdę powinieneś dołączyć do mojego serwera Discord!

- Ścieżka dźwiękowa tej gry została stworzona przez Peppsena - Jest niesamowity.

- Na koniec, wielkie dzięki mojemu najlepszemu przyjacielowi: Niklas - Bez naszego wspólnego grania w Factorio ta gra nigdy by nie powstała. - + body: 'Ta gra jest open-source. Rozwijana jest przez Tobiasa Springera + (to ja).

Jeżeli chcesz pomóc w rozwoju gry, sprawdź repozytorium shapez.io na + Githubie.

Ta gra nie byłaby możliwa bez wspaniałej + społeczności Discord skupionej na moich grach - Naprawdę powinieneś + dołączyć do mojego serwera + Discord!

Ścieżka dźwiękowa tej gry została stworzona przez + Peppsena - Jest niesamowity.

Na koniec, + wielkie dzięki mojemu najlepszemu przyjacielowi: Niklas - Bez + naszego wspólnego grania w Factorio ta gra nigdy by nie powstała.' changelog: title: Dziennik zmian - demo: features: restoringGames: Przywracanie zapisów gry @@ -876,5 +1027,77 @@ demo: oneGameLimit: Limit jednego zapisu gry customizeKeybindings: Personalizowanie Klawiszologii exportingBase: Eksportowanie całej fabryki jako zrzut ekranu - settingNotAvailable: Niedostępne w wersji demo. +tips: + - Budynek główny akceptuje wejście każdego rodzaju - nie tylko aktualny + kształt! + - Upewnij się, że twoje fabryki są modularne - opłaci się to! + - Nie buduj zbyt blisko budynku głównego, albo będziesz miał wielki chaos! + - Jeżeli łączenie kształtów nie działa, spróbuj zamienić wejścia. + - Możesz zmienić kierunek planera taśmociągów poprzez naciśnięcie R. + - Przytrymanie CTRL pozwala na przeciąganie taśmociągów bez + automatycznego zmieniania kierunków. + - Stosunku pozostają takie same, dopóki wszystkie ulepszenia są na tym samym + poziomie. + - Seryjne wykonanie jest badziej wydajne niż równoległe. + - Odblokujesz więcej wariantów budynków później w rozgrywce! + - Możesz użyć T, by zmienić warianty budynków. + - Symetria to klucz do sukcesu! + - Możesz przeplatać różne poziomy tuneli. + - Spróbuj budować kompaktowe fabryki - opłaci się to! + - Malarz ma wersję odbitą lustrzanie, którą możesz wybrać klawiszem T. + - Posiadanie budynków w odpowiednich stosunkach zmaksymalizuje wydajność. + - Na najwyższym poziomie, 5 ekstraktorów zapełni pojedynczy taśmociąg. + - Nie zapomnij o tunelach! + - Nie musisz dzielić równo przedmiotów, by osiągnąć pełną wydajność. + - Przytrymanie SHIFT aktywuje planera taśmociągów, pozwalającego ci + na łatwe budowanie długich taśmociągów. + - Przecinaki zawsze tną pionowo, nie zważając na ich orientację. + - Zmieszanie wszystich 3 barwników daje biały barwnik. + - Pierwsze wyjście z magazynu ma najwyższy piorytet. + - Zainwestuj czas w budowanie powtarzalnych układów fabryk - warto! + - Przytrymanie CTRL pozwala na układanie wielu budynków tego samego + typu. + - Możesz przytrzymać ALT, by odwrócić kierunek układanych taśmociągów. + - Wydajność to klucz do sukcesu! + - Kształty położone dalej od budynku głównego są bardziej skomplikowane. + - Maszyny mają limitowaną prędkość, podziel wejścia między wiele ich, by + zmaksymalizować wydajność. + - Użyj dystrybutorów, by zmaksymalizować wydajność. + - Organizacja jest ważna. Próbuj nie krzyżować zbyt wielu taśmociągów. + - Planuj na przyszłość, albo wszystko będzie wielkim chaosem! + - Nie usuwaj swoich starych fabryk! Będziesz ich potrzebował, by odblokować + ulepszenia. + - Spróbuj przejść poziom 20 samemu, zanim zaczniesz szukać pomocy! + - Nie komplikuj rzeczy, próbuj budować proste rzeczy, a zajdziesz daleko. + - Możesz potrzebować ponownie używać swoich fabryk w późniejszej fazie + rozgrywki. Planuj swoje fabryki, by były zdatne do ponownego użycia. + - Czasami znajdziesz wymagany kształt na mapie, bez potrzeby tworzenia go za + pomoca sklejaczy. + - Pełne "wiatraczki" nigdy nie pojawią się naturalnie na mapie. + - Maluj swoje kształty przed przecianiem dla maksymalnej wydajności. + - Z modułami, miejsce jest tylko tym, co postrzegamy; troska dla + śmiertelników + - Zbuduj osobną fabrykę schematów. Są one bardzo potrzebne do modułów. + - Obejrz dokładnie mikser kolorów, a wszystkie twoje pytania zostaną + rozwiązane. + - Przytrzymaj CTRL i przeciągnij, by zaznaczyć obszar + - Budowanie zbyt blisko budynku głównego może przeszkodzić ci w późniejszych + projektach. + - Ikona pinezki przy każdym kształcie na liście ulepszeń przypina je na + ekranie. + - Połącz wszystkie głowne kolory, by stworzyć biały! + - Masz nieskończoną mapę, nie ściskaj swojej fabryki, rozszerzaj ją! + - Spróbuj też Factorio! To moja ulubiona gra. + - Poczwórny przecinak tnie zgodnie z ruchem wskazówek zegara, zaczynając do + prawej górnej ćwiartki! + - Możesz pobrać swoje zapisy gry w głownym menu gry! + - Ta gra posiada dużo użytecznych skrótów klawiszowych! Sprawdź stronę + ustawień! + - Ta gra posiada mnóstwo ustawień, sprawdź je! + - Znacznik do budynku główneko posiada mały kompas, wskazujący do niego + kierunek! + - By wyczyścić taśmociągi, wytnij obszar i wklej go w tym samym miejscu. + - Naciśnij F4, by zobaczyć ilość FPS i tempo ticków. + - Naciśnij F4 dwa razy, by zobaczyć kratkę twojej myszy i kamery. + - Możesz klinąć przypięty kształt po lewej stronie, by go odpiąć. diff --git a/translations/base-pt-BR.yaml b/translations/base-pt-BR.yaml index 752f6cd8..8e8ea027 100644 --- a/translations/base-pt-BR.yaml +++ b/translations/base-pt-BR.yaml @@ -1,111 +1,62 @@ -# -# 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 é um jogo sobre construir fábricas, automatizando a criação e combinação de formas cada vez mais complexas num mapa infinito. + 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. + discordLinkShort: Discord Oficial + intro: >- + Shapez.io é um jogo relaxante no qual você deve construir fábricas para + produzir formas geométricas automaticamente. - # 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] + Conforme os níveis aumentam, as formas se tornam mais complexas, e você terá que explorar o mapa infinito. - shapez.io é um jogo sobre construir fábricas, automatizando a criação e combinação de formas cada vez mais complexas num mapa infinito. - Após a entrega das formas requisitadas você progredirá no jogo e desbloqueará melhorias para acelerar sua fábrica. + Como se já não bastasse, sua produção deve crescer exponencialmente para satisfazer a demanda - a única solução é expandir! - 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]! + Enquanto no começo você apenas processa as formas, mais a frente você deve pintá-las - para isso você deve extrair e misturar cores! - 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. - - 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! - - 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] - [*] 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]Atualizações Futuras[/b] - - Eu lanço atualizações frequentemente e estou tentando lançar pelo menos um por semana! - - [list] - [*] 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]Esse jogo tem código aberto![/b] - - 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]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]Código fonte(GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Ajude a traduzir[/url] - [/list] - - discordLink: Discord Oficial - Converse comigo! + Comprar o jogo na Steam te garante acesso à versão completa, mas você pode jogar a versão demo em shapez.io primeiro e decidir depois! + title_advantages: Vantagens da versão completa + advantages: + - 12 Novos Níveis para um total de 26 níveis! + - 18 Novas Construções para uma fábrica completamente automática! + - 20 Níveis de Melhorias para muitas horas de diversão! + - Atualização da Fiação para uma dimensão completamente nova! + - Modo Escuro! + - Saves ilimitados + - Marcadores ilimitados + - Me ajuda! ❤️ + title_future: Conteúdo Planejado + planned: + - Biblioteca de projetos (Exclusivo para a versão completa) + - Conquistas da Steam + - Modo Puzzle + - Minimapa + - Mods + - Modo Sandbox + - ... e muito mais! + title_open_source: Este jogo tem código aberto! + title_links: Links + links: + discord: Discord Oficial + roadmap: Linha do Tempo + subreddit: Subreddit + source_code: Código-fonte (GitHub) + translate: Ajude a traduzir + text_open_source: >- + Qualquer um pode contribuir, estou ativamente envolvido com a comunidade + e tento ler todas as sugestões e receber críticas quando possível. + Cheque minha lousa no trello para a linha do tempo completa! global: loading: Carregando error: Erro - - # 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" + thousandsDivider: . 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: inf - time: - # Used for formatting past time dates oneSecondAgo: um segundo atrás xSecondsAgo: segundos atrás oneMinuteAgo: um minuto atrás @@ -114,49 +65,36 @@ global: xHoursAgo: horas atrás oneDayAgo: um dia atrás xDaysAgo: dias atrás - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s hoursAndMinutesShort: h m - xMinutes: minutos - keys: tab: TAB control: CTRL alt: ALT escape: ESC - shift: SHIFT - space: ESPAÇO - + shift: Shift + space: Espaço 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 - + intro: Compre a versão completa para desbloquear todas os recursos! mainMenu: play: Jogar - changelog: Changelog - importSavegame: Importar - openSourceHint: Esse jogo tem código aberto! - discordLink: Discord oficial - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - Desculpe, o jogo fica lento em seu navegador! Compre a versão completa ou baixe o Chrome para obter uma experiência completa. - - savegameLevel: Nível - savegameLevelUnknown: Nível desconhecido - - - helpTranslate: Ajude a traduzir! continue: Continuar newGame: Novo jogo - madeBy: Feito por + changelog: Changelog subreddit: Reddit - + importSavegame: Importar save + openSourceHint: Esse jogo tem código aberto! + discordLink: Discord oficial + helpTranslate: Ajude a traduzir! + madeBy: Feito por + browserWarning: O jogo pode ficar lento em seu navegador! Compre a versão + completa ou baixe o Chrome para obter uma experiência completa. + savegameLevel: Nível + savegameLevelUnknown: Nível desconhecido + savegameUnnamed: Sem nome dialogs: buttons: ok: OK @@ -164,123 +102,116 @@ 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: title: Erro de importação - text: >- - Houve uma falha ao importar seu jogo salvo: - + text: "Houve uma falha ao importar seu jogo salvo:" importSavegameSuccess: title: Jogo salvo importado - text: >- - Seu jogo salvo foi importado com sucesso. - + text: Seu jogo salvo foi importado com sucesso. gameLoadFailure: - title: Jogo salvo quebrado - text: >- - Houve uma falha ao carregar seu jogo salvo: - + title: Jogo salvo corrompido + text: "Houve uma falha ao carregar seu jogo salvo:" confirmSavegameDelete: title: Confirmar exclusão - text: >- - Tem certeza que quer excluir esse jogo salvo? - + text: Tem certeza que deseja deletar o jogo a seguir?

'' + no nível

Isso não pode ser revertido! savegameDeletionError: title: Falha ao deletar - text: >- - Houve uma falha ao deletar seu jogo salvo: - + text: "Houve uma falha ao deletar seu jogo salvo:" restartRequired: - title: Ação necessária - text: >- - Voce precisa reiniciar o jogo para aplicar as mudanças. - + title: Reinicialização necessária + text: Você precisa reiniciar o jogo para aplicar as mudanças. editKeybinding: title: Alterar tecla - desc: Pressiona a tecla que deseja vincular, ou ESC para cancelar. - + desc: Pressione a tecla que deseja vincular, ou ESC para cancelar. resetKeybindingsConfirmation: title: Resetar controles desc: Essa opção deixa os controles nas definições padrão. - keybindingsResetOk: - title: Resetar controles + title: Controles resetados desc: Os controles foram resetados para as definições padrão. - featureRestriction: title: Versão Demo - desc: Você tentou acessar um recurso () que não está disponível na demo. Considere obter a versão completa para a proceder! - + desc: Você tentou acessar um recurso () que não está disponível na + demo. Considere obter a versão completa para a proceder! oneSavegameLimit: - title: Jogo salvo limitado - desc: Você pode ter apenas um jogo salvo por vez na versão demo. Remova o existente ou obtenha a versão completa! - + title: Limite de jogos salvos + desc: Você pode ter apenas um jogo salvo por vez na versão demo. Remova o + existente ou obtenha a versão completa! updateSummary: title: Nova Atualização! - desc: >- - Aqui estão as alterações desde a última vez que você jogou: - + desc: "Aqui estão as alterações desde a última vez que você jogou:" upgradesIntroduction: title: Desbloquear melhorias - desc: >- - 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. - + desc: 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: - title: Deletar - desc: >- - Você está deletando vários objetos ( para ser exato)! Você quer continuar? - + title: Deletar? + 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: Você não conseguirá colar essa área! Tem certeza que quer cortá-la?? blueprintsNotUnlocked: title: Não desbloqueado ainda - desc: >- - Os projetos ainda não foram desbloqueados! Complete mais níveis para desbloqueá-los. - + desc: Os projetos ainda não foram desbloqueados! Complete mais níveis para + desbloqueá-los. keybindingsIntroduction: 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.
- ALT: Inverte as posições.
- + 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/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: Editar Marcação + titleEdit: Editar Marcador + desc: Dê um nome significativo, você também pode incluir um código + de uma forma (Você pode gerá-lo aqui) markerDemoLimit: - desc: >- - Você só pode criar dois marcadores na versão demo. Adquira a versão completa para marcadores ilimitados! - - massCutConfirm: - title: Confirmar Corte - desc: >- - Você está cortando vários objetos ( para ser exato)! Você quer continuar? - + 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: Confirmar Corte - 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! + editSignal: + title: Defina o sinal + descItems: "Escolha um item pré-definido:" + descShortKey: ... ou insira o código de uma forma (Você pode + gerá-lo aqui) + renameSavegame: + title: Renomear Save + desc: Você pode renomear seu save aqui. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? 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 @@ -288,120 +219,14 @@ ingame: placeBuilding: Construir objeto createMarker: Criar marcador delete: Destruir - selectBuildings: Selecionar área pasteLastBlueprint: Colar último projeto - lockBeltDirection: Ativar Planejador de Esteiras - plannerSwitchSide: Flip planner side + lockBeltDirection: Ativar Planejamento de Esteiras + plannerSwitchSide: Girar Planejamento cutSelection: Cortar - copySelection: Colar + copySelection: Copiar clearSelection: Limpar Seleção - pipette: Pipeta - switchLayers: Trocar camadas - - # 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: Aperte para variações. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - - infoTexts: - speed: Velocidade - range: Distância - storage: Estoque - oneItemPerSecond: 1 item / segundo - itemsPerSecond: itens / s - itemsPerSecondDouble: (x2) - - tiles: tiles - - # The notification when completing a level - levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: Nível - completed: Completado - unlockText: Desbloqueado ! - buttonNextLevel: Próximo Nível - - # Notifications on the lower right - notifications: - newUpgrade: Nova melhoria disponível! - gameSaved: Seu jogo foi salvo. - - # The "Upgrades" window - shop: - title: Melhorias - buttonUnlock: Comprar - - # 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 - statistics: - title: Estatísticas - dataSources: - stored: - title: Estoque - description: Exibindo a quantidade de formas armazenadas em seu edifício 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.. - noShapesProduced: Nenhuma forma foi produzida até o momento. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" - settingsMenu: - playtime: Tempo de Jogo - - buildingsPlaced: Construções - beltsPlaced: Esteiras - - buttons: - continue: Continuar - settings: Definições - menu: Voltar ao menu - - # Bottom left tutorial hints - tutorialHints: - title: Quer ajuda? - showHint: Mostrar dica - hideHint: Fechar - - # When placing a blueprint - blueprintPlacer: - cost: Custo - - # Map markers - 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. - creationSuccessNotification: Marcador criado. - - # Interactive tutorial - interactiveTutorial: - title: Tutorial - hints: - 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! - - 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. - + pipette: Conta-Gotas + switchLayers: Trocar Camadas colors: red: Vermelho green: Verde @@ -410,304 +235,571 @@ ingame: purple: Roxo cyan: Ciano white: Branco - uncolored: Sem cor black: Preto + uncolored: Sem cor + buildingPlacement: + cycleBuildingVariants: Aperte para variações. + hotkeyLabel: "Hotkey: " + infoTexts: + speed: Velocidade + range: Distância + storage: Estoque + oneItemPerSecond: 1 item / segundo + itemsPerSecond: itens / s + itemsPerSecondDouble: (x2) + tiles: tiles + levelCompleteNotification: + levelTitle: Nível + completed: Concluído + unlockText: Desbloqueado ! + buttonNextLevel: Próximo Nível + notifications: + newUpgrade: Nova melhoria disponível! + gameSaved: Seu jogo foi salvo. + freeplayLevelComplete: Level has been completed! + shop: + title: Melhorias + buttonUnlock: Melhorar + tier: Nível + maximumLevel: NÍVEL MÁXIMO (Velocidade x) + statistics: + title: Estatísticas + dataSources: + stored: + title: Estoque + description: Exibindo a quantidade de formas armazenadas no seu HUB. + 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 no seu HUB. + noShapesProduced: Nenhuma forma foi produzida até o momento. + shapesDisplayUnits: + second: / s + minute: / m + hour: / h + settingsMenu: + playtime: Tempo de Jogo + buildingsPlaced: Construções + beltsPlaced: Esteiras + tutorialHints: + title: Quer ajuda? + showHint: Mostrar dica + hideHint: Esconder dica + blueprintPlacer: + cost: Custo + 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 à partir da exibição + atual ou clique com o botão direito do mouse para + criar um marcador no local selecionado. + creationSuccessNotification: Marcador criado. shapeViewer: title: Camadas - empty: Vazio - copyKey: Copy Key - -# All shop upgrades + empty: Vazio + copyKey: Copiar Chave + interactiveTutorial: + title: Tutorial + hints: + 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! + 1_3_expand: Este NÃO é um jogo idle! 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. + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." + connectedMiners: + one_miner: 1 Extrator + n_miners: Extratores + limited_items: Limite de + watermark: + title: Versão Demo + desc: Clique aqui para ver as vantagens da versão completa! + get_on_steam: Adquira na Steam + standaloneAdvantages: + title: Adquira a versão completa! + no_thanks: Não, obrigado! + points: + levels: + title: 12 Novos Níveis + desc: Para um total de 26 novos níveis! + buildings: + title: 18 Novas Construções + desc: Automatize sua fábrica inteira! + savegames: + title: Saves ∞ + desc: Quantos o seu coração mandar! + upgrades: + title: 20 Níveis de Melhorias + desc: Essa demo tem apenas 5! + markers: + title: Marcadores ∞ + desc: Nunca se perca na sua fábrica! + wires: + title: Fiação + desc: Uma dimensão completamente nova! + darkmode: + title: Modo Escuro + desc: Não machuque mais seus olhos! + support: + title: Me ajuda + desc: Eu desenvolvo o jogo no meu tempo livre! 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 de cores e Pintura description: Velocidade x → x - -# Buildings and their name / description buildings: - belt: - default: - name: &belt Esteira Transportadora - description: Transporta itens; mantenha pressionado e arraste para colocar vários. - - 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 - 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. - - tier2: - name: Túnel Classe II - description: Permite transportar recursos sob construções. - - splitter: # Internal name for the Balancer - default: - name: &splitter Balanceador - description: Multifuncional - Distribui uniformemente todas as entradas em todas as saídas. - - compact: - name: Balanceador (compacto) - description: Mescla duas esteiras transportadoras em uma. - - compact-inverse: - name: Balanceador (compacto) - description: Mescla 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! - 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! - - rotater: - default: - name: &rotater Rotacionador - description: Gira as formas no sentido horário em 90 graus. - ccw: - name: Rotacionador (Anti-horário) - description: Gira as formas no sentido anti-horário em 90 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. - - mixer: - default: - name: &mixer Misturador de Cores - description: Mistura duas cores usando mistura aditiva. - - painter: - 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 - - trash: - default: - name: &trash Lixo - description: Aceita qualquer item e os destrói. PARA SEMPRE. - - 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 + endOfDemo: Fim da Demo + belt: + default: + name: Esteira Transportadora + description: Transporta itens; mantenha pressionado e arraste para colocar + vários. wire: default: - name: Fio de energia + name: Fio de Energia description: Permite transportar energia. - advanced_processor: + second: + name: Fio + description: Transfere sinais, que podem ser de itens, cores ou binários (1 / + 0). Fios com cores diferentes não se conectam. + miner: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Entregue - toGenerateEnergy: Para + name: Extrator + description: Coloque sobre uma forma ou cor para extraí-la. + chainable: + name: Extrator (em Cadeia) + description: Coloque sobre uma forma ou cor para extraí-la. Pode ser ligado a + outros extratores. + underground_belt: default: - name: Gerador de Energia - description: Consome figuras para gerar energia. - wire_crossings: + name: Túnel + description: Permite transportar recursos por baixo de construções e esteiras. + tier2: + name: Túnel Classe II + description: Permite transportar recursos por baixo de construções e outras + esteiras. + cutter: default: - name: Separador de Fios - description: Divide um fio de energia em dois. + name: 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! + 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! + rotater: + default: + name: Rotacionador + description: Gira as formas no sentido horário em 90 graus. + ccw: + name: Rotacionador (Anti-horário) + description: Gira as formas no sentido anti-horário em 90 graus. + rotate180: + name: Rotacionador (180) + description: Gira as formas em 180 graus. + stacker: + default: + name: Empilhador + description: Empilha os dois itens. Se eles não puderem ser unidos, o item + direito será colocado acima do item esquerdo. + mixer: + default: + name: Misturador de Cores + description: Mistura duas cores usando mistura aditiva. + painter: + default: + name: Pintor + description: Colore a forma inteira na entrada esquerda com a cor da entrada + direita. + mirrored: + name: Pintor + description: Colore a forma inteira na entrada esquerda com a cor da entrada + direita. + double: + name: Pintor (Duplo) + description: Colore as formas na entrada esquerda com a cor da entrada superior. + quad: + name: Pintor (Quádruplo) + description: Permite que você pinte cada quadrante da forma individualmente. + Apenas entradas com um sinal verdadeiro no + plano de fios serão pintadas! + trash: + default: + name: Lixo + description: Aceita qualquer item e os destrói. PARA SEMPRE. + balancer: + default: + name: Balanceador + description: Multifuncional - Distribui igualmente todas as entradas para todas + as saídas. merger: - name: Juntador de Fios - description: Junta dois fios de energia em um. - + name: Unificador (compacto) + description: Une duas esteiras em uma. + merger-inverse: + name: Unificador (compacto) + description: Une duas esteiras em uma. + splitter: + name: Divisor (compacto) + description: Divide uma esteira em duas. + splitter-inverse: + name: Divisor (compacto) + description: Divide uma esteira em duas. + storage: + default: + name: Armazenamento + description: Estoca itens em excesso, até uma certa capacidade. Prioriza a saída + da esquerda e pode ser usado como um mecanismo de escape. + wire_tunnel: + default: + name: Cruzamento de Fios + description: Permite cruzar dois fios sem conectá-los. + constant_signal: + default: + name: Sinal Constante + description: Emite um sinal constante, que pode ser uma forma, cor ou binário (1 + / 0). + lever: + default: + name: Interruptor + description: Pode ser ativado para emitir um sinal binário (1 / 0) no plano da + fiação, que pode então ser usado para controlar um filtro, por + exemplo. + logic_gate: + default: + name: Portão E (AND) + description: Emite um sinal binário "1" se ambas as entradas forem verdadeiras. + (Ser verdadeira significa receber um sinal de forma, cor ou + binário "1") + not: + name: Portão NEGAR (NOT) + description: Emite um sinal binário "1" se a entrada for falsa. (Ser verdadeira + significa receber um sinal de forma, cor ou binário "1") + xor: + name: Portão OU EXCLUSIVO (XOR) + description: Emite um sinal binário "1" se uma das entradas for verdadeira, mas + não duas. (Ser verdadeira significa receber um sinal de forma, + cor ou binário "1") + or: + name: Portão OU (OR) + description: Emite um sinal binário "1" se uma das entradas for verdadeira. (Ser + verdadeira significa receber um sinal de forma, cor ou binário + "1") + transistor: + default: + name: Transistor + description: Envia o sinal adiante se a entrada for verdadeira. (Ser verdadeira + significa receber um sinal de forma, cor ou binário "1") + mirrored: + name: Transistor + description: Envia o sinal adiante se a entrada for verdadeira. (Ser verdadeira + significa receber um sinal de forma, cor ou binário "1") + filter: + default: + name: Filtro + description: Conecte um sinal para rotear todos os itens desejador para o topo e + o restante para a direita. Pode ser controlado por sinais + binários também. + display: + default: + name: Display + description: Conecte um sinal para exibí-lo no display - Pode ser uma forma, cor + ou binário. + reader: + default: + name: Leitor de Esteira + description: Permite medir a passagem média de itens na esteira. Emite o último + item lido no plano da fiação (quando desbloquado). + analyzer: + default: + name: Analizador de Formas + description: Analiza o quadrante superior direito da camada mais baixa da forma + e fornece sua forma e cor. + comparator: + default: + name: Comparador + description: Devolve um sinal binário "1" se ambos os sinais forem idênticos. + Pode comparar formas, itens e binário. + virtual_processor: + default: + name: Cortador Virtual + description: Corta virtualmente as formas em duas metades. + rotater: + name: Rotacionador Virtual + description: Rotaciona virtualmente a forma, tanto no sentido horário quanto no + anti-horário. + unstacker: + name: Separador Virtual + description: Extrai virtualmente a camada mais acima para a saída direita e as + restantes para a esquerda. + stacker: + name: Empilhador Virtual + description: Empilha virtualmente a forma da direita em cima da forma da + esquerda. + painter: + name: Pintor Virtual + description: Pinta virtualmente a forma da entrada inferior com a forma da + entrada direita. + item_producer: + default: + name: Fábricante de Itens + description: Disponível no modo sandbox apenas, envia o sinal recebido do plano + de fios para o plano regular. 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ê acabou de desbloquear o cortador, que corta formas + pela metade de cima para baixo independente de sua + orientação!

Lembre-se de se livrar do lixo, caso + contrário, a máquina irá entupir - Por isso eu te + dei o lixo, que destrói tudo que você coloca nele! 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! - + desc: "O Pintor foi desbloqueado - Extraia alguns pigmentos + coloridos (assim como você fez com as formas) e combine-os com uma + forma no pintor para colorí-las!

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: Divisor + desc: Você desbloqueou uma variante divisora do + balanceador - Ela aceita uma entrada e a divide em + duas saídas! reward_tunnel: title: Túnel - desc: O túnel foi desbloqueado - Agora você pode canalizar itens sob construções! - + desc: O túnel foi desbloqueado - Agora você pode transportar + itens abaixo do solo! reward_rotater_ccw: title: Rotação anti-horária - desc: Você desbloqueou uma variante do rotacionador - permite girar no sentido anti-horário! Para construí-lo, selecione o rotacionador e pressione 'T' para alternar suas variantes! - + desc: Você desbloqueou uma variante do rotacionador - permite + girar no sentido anti-horário! Para construí-lo, selecione o + rotacionador e pressione 'T' para alternar suas + variantes! reward_miner_chainable: title: Extrator em Cadeia - desc: Você desbloqueou o extrator em cadeia! Ele pode encaminhar seus recursos para outros extratores, para que você possa extrair recursos com mais eficiência! - + desc: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" reward_underground_belt_tier_2: title: Túnel Classe II - 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! - + 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_cutter_quad: title: Cortador quádruplo - desc: Você desbloqueou uma variante do cortador - permite cortar formas em quatro partes em vez de apenas duas! - + desc: Você desbloqueou uma variante do cortador - permite + cortar formas em quatro partes em vez de apenas + duas! 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! - - reward_painter_quad: - title: Pintura quádrupla - desc: Você desbloqueou uma variante do pintor - permite pintar cada parte da forma individualmente! - + 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_storage: title: Acúmulo de excesso - desc: Você desbloqueou uma variante do lixo - Permite armazenar itens até uma determinada capacidade! - + desc: You have unlocked the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! reward_freeplay: title: Modo Livre - desc: Você conseguiu! Você desbloqueou o modo de jogo livre! Isso significa que as formas agora são geradas aleatoriamente! (Não se preocupe, mais conteúdo está planejado para o jogo completo!) - + desc: Você conseguiu! Você desbloqueou o modo livre! Isso + significa que formas agora são geradas + aleatóriamente!

Já que o HUB vai precisar + de uma entrada constante a partir de agora, eu + altamente recomendo que você construa uma máquina que entregue + automaticamente as formas pedidas!

O HUB emite a forma + pedida no plano dos fios, então tudo que você precisa fazer é + analizá-la e automaticamente configurar sua fábrica baseado nessa + análise. 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). - - # Special reward, which is shown when there is no reward actually + 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). no_reward: title: Próximo nível - desc: >- - Este nível não lhe deu nenhuma recompensa, mas em breve?!

PS: Melhor não destruir sua fábrica existente - Você precisa de todas essas formas posteriormente mais tarde para desbloquear atualizações! - + desc: "Este nível não lhe deu nenhuma recompensa, mas em breve?!

PS: + Melhor não destruir sua fábrica existente - Você precisa de + todas essas formas posteriormente mais tarde para + desbloquear atualizações!" 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. - + desc: Parabéns! Aliás, mais conteúdo vindo na versão completa! + reward_balancer: + title: Balanceador + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Unificador Compacto + desc: Você desbloqueou uma variante unificadora do + balanceador - Ele aceita duas entradas e as junta + em uma esteira! + reward_belt_reader: + title: Leitor de Esteira + desc: Você desbloqueou o leitor de esteira! Ele permite que + você meça a passagem de itens em uma esteira.

Espere até você + desbloquear os fios - ele se torna muito útil! + reward_rotater_180: + title: Rotacionador (180 graus) + desc: Você acabou de desbloquear o rotacionador de 180 graus! - + Ele permite que você rotacione uma forma em 180 graus (Surpresa! :D) + reward_display: + title: Display + desc: "Você desbloqueou o Display - Conecte um sinal no plano + de fios para poder vê-lo!

PS: Você percebeu que ambos o + leitor de esteiras e o armazenamento emitem o último item lido? + Tente mostrar isso em um display!" + reward_constant_signal: + title: Sinal Constante + desc: Você desbloqueou a construção que emite um sinal + constante no plano de fios! Isso é útil para conectar no + filtro de itens por exemplo.

O sinal + constante pode emitir um sinal de forma, + cor ou binário (1 / 0). + reward_logic_gates: + title: Portões Lógicos + desc: Você desbloqueou portões lógicos! Você não precisa se + animar com isso, mas na verdade é SUPER legal!

Com estes + portões você pode computar operações E (AND), OU (OR), OU EXCLUSIVO + (XOR) e NEGAR (NOT).

c E para a cereja do bolo, eu também te + dei um transistor! + reward_virtual_processing: + title: Processamento Virtual + desc: Eu acabei de te dar um monte de novas construções que te permitem + simular o processamento de formas!

Você + pode simular um cortador, rotacionador, empilhador e mais no plano + de fiação! Com isso você tem agora três maneiras de continuar + jogando:

- Construir uma máquina automática + para criar qualquer forma possível pedida pelo HUB (Você deveria + tentar!).

- Construir algo legal com os fios.

- + Continuar jogando normalmente.

Independente da sua escolha, + lembre de se divertir! + reward_wires_painter_and_levers: + title: Fios e Pintor Quádruplo + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Filtro de Itens + desc: Você desbloqueou o Filtro de Itens! Ele irá rotear os + itens para a saída superior ou da direit dependendo se eles batem + com o sinal vindo do plano dos fios ou não.

Você também pode + inserir um sinal binário (1 / 0) para ativá-lo ou desativá-lo + completamente + reward_demo_end: + title: Fim da Demo + desc: Você chegou no fim da versão demo! settings: - title: opções + title: Opções categories: - game: Jogo - app: Aplicação - + general: Geral + userInterface: Interface de Usuário + advanced: Avançado + performance: Performance versionBadges: dev: Desenvolvedor staging: Teste prod: Produção buildDate: Compilado - labels: uiScale: title: Fonte - 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. + 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 autosave. + description: Controla a frequência com que o jogo salva automaticamente. Você + também pode desativá-lo completamente por 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). + 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 - - fullscreen: - title: Tela Cheia - description: >- - É recomendado jogar o jogo em tela cheia para obter a melhor experiência. Disponível apenas na versão completa. - - soundsMuted: - title: Som - description: >- - Se ligado o jogo fica mudo - - musicMuted: - title: Musica - description: >- - Se ligado, a musica fica muda. - - theme: - title: Tema - description: >- - Escolha o tema entre (Claro / Escuro). - - themes: - dark: Escuro - light: Claro - - refreshRate: - title: Frequência - description: >- - Se você possui um monitor de 144 hz, altere a taxa de atualização aqui para que o jogo seja simulado corretamente com taxas de atualização mais altas. Isso diminuir o FPS consideravelmente se o computador for muito lento. - - 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. - - offerHints: - title: Dicas e tutoriais - description: >- - Se serão oferecidas dicas e tutoriais enquanto estiver jogando. - - 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. @@ -718,65 +810,136 @@ settings: 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. - vignette: - title: Vignette - description: >- - 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. - + 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. + description: Habilita várias ferramentas que te permitem jogar se você é + daltônico. + fullscreen: + title: Tela Cheia + description: É recomendado jogar o jogo em tela cheia para obter a melhor + experiência. Disponível apenas na versão completa. + soundsMuted: + title: Som + description: Se ligado, o jogo fica mudo. + musicMuted: + title: Música + description: Se ligado, a música fica muda. + theme: + title: Tema + description: Escolha o tema entre (Claro / Escuro). + themes: + dark: Escuro + light: Claro + refreshRate: + title: Frequência + description: Se você possui um monitor de 144 hz, altere a taxa de atualização + aqui para que o jogo seja simulado corretamente com taxas de + atualização mais altas. Isso diminuir o FPS consideravelmente se + o computador for muito lento. + alwaysMultiplace: + title: Posicionamento Múltiplo + description: 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 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. + 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. + vignette: + title: Vinheta + description: Habilita o modo vinheta que escurece os cantos da tela e facilita a + leitura do texto. 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. - + 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. + 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: Desativa as caixas de diálogo de aviso exibidas ao cortar / excluir + mais de 100 entidades. + soundVolume: + title: Volume dos sons + description: Defina um volume para os efeitos sonoros + musicVolume: + title: Volume da música + description: Defina um volume para a música + lowQualityMapResources: + title: Recursos do Mapa em Baixa Qualidade + description: Simplifica a renderização de recursos no mapa com o zoom aplicado + para melhorar a performance. Parece até mais limpo, então tenha + certeza de testar! + disableTileGrid: + title: Desabilite a Grade + description: Desabilitar a grade pode ajudar com a performance. Isso também faz + o jogo parecer mais limpo! + clearCursorOnDeleteWhilePlacing: + title: Limpar Cursor com Clique Direito + description: Habilitado por padrão, limpa o cursor sempre que você clica com o + botão direito enquanto você tem uma construção selecionada. Se + desabilitado, você pode deletar construções clicando com o botão + direito enquanto tiver algo selecionado. + lowQualityTextures: + title: Texturas de Baixa Qualidade (Feio) + description: Usa texturas de baixa qualidade para ajudar com a performance. Vai + deixar o jogo bem feio! + displayChunkBorders: + title: Mostrar Bordas das Chunks + description: O jogo é dividido em chunks de 16x16 ladrilhos, se está + configuração estiver habilitada, as bordas de cada chunk ficarão + à mostra. + pickMinerOnPatch: + title: Selecionar Extrator em uma Fonte de Recursos + description: Habilitador por padrão, seleciona o extrator se você usar o + conta-gotas em uma fonte de recursos. + simplifiedBelts: + title: Esteiras Simplificadas (Feio) + description: Não renderiza itens nas esteiras, exceto quando o cursor estiver em + cima da esteira, para melhorar a performance. Eu não recomendo + jogar com essa configuração habilitada se você não precisar + muito da melhoria de performance. + enableMousePan: + title: Habilitar Movimento com o Mouse + description: Permite mover o mapa ao mover o cursor para as bordas da tela. A + velocidade depende da configuração Velocidade de Movimento. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: Controles - hint: >- - Tip: Certifique-se de usar CTRL, SHIFT e ALT! Eles permitem diferentes opções de construção. - + hint: "Tip: Certifique-se de usar CTRL, SHIFT e ALT! Eles permitem diferentes + opções de construção." resetKeybindings: Resetar Controles - categoryLabels: general: Geral ingame: Jogo navigation: Navegação - placement: Construção - massSelect: Seleção - buildings: Atalhos de objetos + placement: Posicionamento + massSelect: Seleção em Massa + buildings: Construções placementModifiers: Modificadores - mappings: confirm: Confirmar back: Voltar @@ -784,84 +947,149 @@ keybindings: mapMoveRight: Mover para direita mapMoveDown: Mover para baixo mapMoveLeft: Mover para a esquerda + mapMoveFaster: Mover mais rápido centerMap: Centralizar mapa - mapZoomIn: Aproximar mapZoomOut: Distanciar - createMarker: Criar marcação - + createMarker: Criar marcador menuOpenShop: Melhorias menuOpenStats: Estatísticas - + menuClose: Fechar Menu toggleHud: Ocultar Interface - toggleFPSInfo: Mostar FPS - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + toggleFPSInfo: Mostrar FPS e Debug Info + switchLayers: Alternar Camadas + exportScreenshot: Exportar Base Inteira como Imagem + belt: Esteira Transportadora + underground_belt: Túnel + miner: Extrator + cutter: Cortador + rotater: Rotacionador + stacker: Empilhador + mixer: Misturador de Cores + painter: Pintor + trash: Lixo + wire: Fio de Energia + pipette: Conta-Gotas rotateWhilePlacing: Rotacionar - rotateInverseModifier: >- - Modifier: Rotação anti-horária + rotateInverseModifier: "Modificador: 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 planejamento de esteira + 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: Conta-gotas - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire - + balancer: Balanceador + storage: Armazenamento + constant_signal: Sinal Constante + logic_gate: Portão Lógico + lever: Interruptor (regular) + filter: Filtro + wire_tunnel: Cruzamento de Fios + display: Display + reader: Leitor de Esteira + virtual_processor: Cortador Virtual + transistor: Transistor + analyzer: Analizador de Forma + comparator: Comparador + item_producer: Produtor de Itens (Sandbox) + copyWireValue: "Fios: Copiar valor abaixo do cursor" 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.

- - Finalmente, agradeço muito ao meu melhor amigo - Niklas - Sem nossas sessões de Factorio, - esse jogo nunca teria existido. + 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. changelog: title: Alterações - 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. +tips: + - O HUB aceita qualquer tipo de forma, não apenas a pedida! + - Tenha certeza que seus designs são modulares - vai valer a pena! + - Não construa muito perto do HUB, ou será um caos! + - Se o empilhamento não funcionar, tente inverter as entradas. + - Você pode mudar a direção do planejador de esteiras apertando R. + - Segurar CTRL permite arrastar esteiras sem a orientação automática. + - As proporções se matém, desde que todas as melhorias estejam no mesmo + nível. + - Execução em série é mais eficiete que a paralela. + - Você desbloqueará variantes de construções mais para frente no jogo! + - Você pode usar T para mudar para diferentes variantes. + - Simetria é crucial! + - Você pode entrelaçar diferentes níveis de túnel. + - Tente construir fábricas compactas - vai valer a pena! + - O pintor tem uma variante espelhada que você pode selecionar com T + - Ter as proporções certas para cada construção vai maximizar sua eficiência. + - No nível máximo, 5 extratores vão encher uma única esteira. + - Não se esqueça dos túneis! + - Você não precisa dividir os itens igualmente para ter máxima eficiência. + - Segurar SHIFT vai ativar o planejamento de esteiras, te permitindo + colocar longas esteiras mais facilmente. + - Cortadores sempre cortam verticalmente, independente da orientação. + - Misture todas as cores para obter branco. + - O armazenamento prioriza a saída primária. + - Invista tempo em construir designs que podem ser repetidos - vale a pena! + - Segurar CTRL permite colocar múltiplas construções. + - Segure ALT para inverter a direção de esteiras posicionadas. + - Efficiência é a chave! + - Fontes de recursos mais distantes do HUB são mais complexas. + - Máquinas tem uma velocidade máxima, divida os itens para uma eficiência + máxima. + - Use balanceadores para maximizar sua eficiência. + - Organização é importante. Tente não entrelaçar muitas esteiras. + - Planeje com antecedência, ou tudo será um caos! + - Não remova suas fábricas antigas! Você precisará delas para desbloquear + melhorias. + - Tente passar do nível 20 sozinho antes de pedir ajuda! + - Não complique as coisas, tente manter tudo simples e você irá longe. + - Talvez você precise reusar fábricas antigas no futuro. Planeje-as para que + sejam reutilizáveis. + - As vezes, você pode encontrar uma forma necessária no mapa sem criá-la com + empilhadores. + - Moinhos completos nunca vão aparecer naturalmente. + - Pinte suas formas antes de cortar para ter máxima eficiência. + - Com módulos, espaço é meramente uma percepção; uma preocupação para + mortais. + - Faça uma fábrica separada para projetos. Eles são importantes para os + módulos. + - Dê uma olhada mais de perto no misturador de cores, e suas perguntas serão + respondidas. + - Use CTRL + Clique para selecionar uma área. + - Construções muito perto do HUB podem entrar no caminho de projetos futuros. + - O ícone de pin ao lado de cada forma na lista de melhorias fixa essa forma + na tela. + - Misture todas as cores primárias para fazer tinta branca! + - Você tem um mapa infinito, não amontoe sua fábrica, expanda! + - Tente também Factorio! É meu jogo favorito. + - O cortador quádruplo corta no sentido anti-horário começando pelo topo + direito! + - Você pode baixar seus saves no menu principal! + - Este jogo tem um monte de teclas úteis! Tenha certeza de checar a aba de + configurações. + - Este jogo tem muitas configurações, então dê uma olhada! + - O marcador para o HUB tem uma pequena bússola para indicar sua direção! + - Para limpar as esteiras, corte a área e cole-a no mesmo lugar. + - Pressione F4 para mostrar seu FPS e taxa de tiques. + - Pressione F4 duas vezes para mostrar o ladrilho do seu mouse e da câmera. + - Você pode clicar em uma forma fixada na esquerda para tirá-la de lá. diff --git a/translations/base-pt-PT.yaml b/translations/base-pt-PT.yaml index 2f3e19be..c6c18b98 100644 --- a/translations/base-pt-PT.yaml +++ b/translations/base-pt-PT.yaml @@ -1,111 +1,64 @@ -# -# 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 é 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. + 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. + discordLinkShort: Discord Oficial + intro: >- + Shapez.io é um jogo relaxante onde tens de construir fábricas para + autumatizar a produção de formas geométricas. - # 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] + Com o aumento do nível, as formas começam a ser cada vez mais e mais complexas, e tu terás de te expandir num mapa infinito. - 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, progredirás no jogo e desbloquearás melhorias para acelerar a produção da tua fábrica. + E como se isso não fosse suficiente, tu também terás de produzir de forma exponencial para satisfazeres as tuas necessidades - a única coisa que ajuda é aumentar! - 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! + Embora no inicio apenas tenhas de processar formas, mais tarde, vais ter de as colorir - para isto terás de extrair e misturar cores! - Rapidamente precisarás de misturar cores e pintar as formas com elas - Combina os recursos de cores vermelha, verde e azul para produzir ainda mais cores e usá-las para pintar as formas geométricas com o intuito de satisfazer a procura. + Comprar o jogo na Steam dar-te-á acesso à versão completa, mas também podes jogar a versão demo em shapez.io primeiro e decidir mais tarde! + title_advantages: Vantagens da versão completa + advantages: + - 12 Novos Níveis para um total de 26 Níves + - 18 Novas Construções para uma fábrica totalmente automatizada! + - 20 Níveis de Melhoria para muitas horas de diversão! + - Atualização de Fios para uma dimensão totalmente nova! + - Modo escuro! + - Savegames ilimitados + - Marcos ilimitados + - Ajuda-me! ❤️ + title_future: Conteúdo Planeado + planned: + - Biblioteca Blueprint (Exclusivo na versão Completa) + - Conquistas na Steam + - Modo Puzzle + - Minimapa + - Modos + - Modo Sandbox + - ... e Muito Mais! + title_open_source: Este jogo é open source (código aberto)! + title_links: Links + links: + discord: Discord Oficial + roadmap: Roteiro de desenvolvimento + subreddit: Subreddit + source_code: Código Fonte (GitHub) + translate: Ajuda a Traduzir + text_open_source: >- + Qualquer um pode contribuir, estou ativamente envolvido na comunidade e + tento ver todas as sugestões e ter em consideração o feedback recebido + assim que possível. - 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! - - Ao comprar o jogo, terás acesso à versão completa, que contém funcionalidades adicionais, e também a conteúdos desenvolvidos recentemente. - - [b]Vantagens do jogo completo[/b] - - [list] - [*] 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]Atualizações futuras[/b] - - Atualizo o jogo frequentemente e tento lançar uma atualização pelo menos todas as semanas! - - [list] - [*] 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]Este jogo é open source (código aberto)![/b] - - 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]Ligações[/b] - - [list] - [*] [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]Código fonte (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Ajuda a traduzir[/url] - [/list] - - discordLink: Discord oficial - Conversa comigo! - global: - loading: A carregar + loading: A Carregar error: Erro - - # 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. + decimalSeparator: . suffix: thousands: k millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: inf - time: - # Used for formatting past time dates oneSecondAgo: há um segundo xSecondsAgo: há segundos oneMinuteAgo: há um minuto @@ -114,14 +67,10 @@ global: xHoursAgo: há horas oneDayAgo: há um dia xDaysAgo: há dias - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s hoursAndMinutesShort: h m - xMinutes: minutos - keys: tab: TAB control: CTRL @@ -129,13 +78,9 @@ global: escape: ESC shift: SHIFT space: SPACE - demoBanners: - # This is the "advertisement" shown in the main menu and other various places title: Versão Demo - intro: >- - Compra a versão completa para desbloqueares todas as funcionalidades! - + intro: Compra a versão completa para desbloqueares todas as funcionalidades! mainMenu: play: Jogar changelog: Changelog @@ -143,20 +88,16 @@ mainMenu: openSourceHint: Este jogo é código aberto! discordLink: Discord oficial helpTranslate: Ajuda a traduzir! - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - Desculpa, mas este jogo parece correr mais lentamente no teu navegador! Compra o jogo completo ou baixa o chrome para melhorares a tua experiência. - + browserWarning: Desculpa, mas este jogo parece correr mais lentamente no teu + navegador! Compra o jogo completo ou baixa o chrome para melhorares a + tua experiência. savegameLevel: Nível savegameLevelUnknown: Nível desconhecido - - continue: Continuar newGame: Novo Jogo madeBy: Criado por subreddit: Reddit - + savegameUnnamed: Sem Nome dialogs: buttons: ok: OK @@ -170,112 +111,110 @@ dialogs: viewUpdate: Ver Update showUpgrades: Mostrar Upgrades showKeybindings: Mostrar Atalhos - importSavegameError: title: Erro de importação - text: >- - Erro ao importar o teu savegame: - + text: "Erro ao importar o teu savegame:" importSavegameSuccess: title: Savegame importado - text: >- - O teu savegame foi importado com sucesso. - + text: O teu savegame foi importado com sucesso. gameLoadFailure: title: O jogo está em baixo - text: >- - Erro ao carregar o teu savegame: - + text: "Erro ao carregar o teu savegame:" confirmSavegameDelete: title: Confirmar eliminação - text: >- - Tens a certeza que pretendes eliminar o jogo? - + text: Tens a certeza que queres apagar o seguinte jogo?

'' + no nível

Isto não pode ser desfeito! savegameDeletionError: title: Erro de eliminação - text: >- - Erro ao eliminar o teu savegame: - + text: "Erro ao eliminar o teu savegame:" restartRequired: title: Necessário reiniciar - text: >- - Precisas de reiniciar o jogo para aplicar as mudanças. - + text: Precisas de reiniciar o jogo para aplicar as mudanças. editKeybinding: title: Mudar Atalhos - desc: Pressiona a tecla ou botão do rato que pretendes definir, ou Escape para cancelar. - + desc: Pressiona a tecla ou botão do rato que pretendes definir, ou Escape para + cancelar. resetKeybindingsConfirmation: title: Resetar Atalhos - desc: Isto irá resetar todos os Atalhos para os seus valores pré-definidos. Confirma por favor. - + desc: Isto irá resetar todos os Atalhos para os seus valores pré-definidos. + Confirma por favor. keybindingsResetOk: title: Atalhos resetados desc: Os Atalhos foram resetados para os respetivos valores pré-definidos! - featureRestriction: title: Versão Demo - desc: Tentaste aceder a uma funcionalidade () que não está disponivel no Demo. Considera adquirir o jogo completo para a melhor experiência do jogo! - + desc: Tentaste aceder a uma funcionalidade () que não está disponivel + no Demo. Considera adquirir o jogo completo para a melhor + experiência do jogo! oneSavegameLimit: title: Savegames limitados - desc: Apenas podes ter um savegame de cada vez na versão Demo. Por favor remove o savegame existente ou adquire a versão completa! - + desc: Apenas podes ter um savegame de cada vez na versão Demo. Por favor remove + o savegame existente ou adquire a versão completa! updateSummary: title: Nova atualização! - desc: >- - Aqui estão as mudanças desde a última vez que jogaste: - + desc: "Aqui estão as mudanças desde a última vez que jogaste:" upgradesIntroduction: title: Desbloqueia upgrades - desc: >- - Todas as formas geométricas que produzes podem ser usadas para desbloquear upgrades - Não destruas as tuas fábricas antigas! - A aba dos upgrades pode ser encontrada no canto superior direito do ecrã. - + desc: Todas as formas geométricas que produzes podem ser usadas para desbloquear + upgrades - Não destruas as tuas fábricas antigas! A + aba dos upgrades pode ser encontrada no canto superior direito do + ecrã. massDeleteConfirm: title: Confirmar eliminação - desc: >- - Estás a apagar muitas construções, ( para ser exato)! Tens a certeza? - + desc: Estás a apagar muitas construções, ( para ser exato)! Tens a + certeza? blueprintsNotUnlocked: title: Ainda não está desbloqueado - desc: >- - Os Projetos ainda não foram desbloqueados! Completa mais níveis para os desbloquear. - + desc: Os Projetos ainda não foram desbloqueados! Completa mais níveis para os + desbloquear. keybindingsIntroduction: title: Atalhos úteis - desc: >- - Este jogo tem vários Atalhos que tornarão mais fácil a construção de grandes fábricas. - Aqui estão alguns, mas verifica os restantes Atalhos!

- CTRL + Drag: Seleciona a área para copiar / eliminar.
- SHIFT: Mantém pressionado para colocar várias construções.
- ALT: Inverte as posições.
- + desc: "Este jogo tem vários Atalhos que tornarão mais fácil a construção de + grandes fábricas. Aqui estão alguns, mas verifica os + restantes Atalhos!

CTRL + Drag: Seleciona a área para copiar + / eliminar.
SHIFT: Mantém + pressionado para colocar várias construções.
ALT: Inverte as posições.
" createMarker: 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) + desc: Dá-lhe um nome com significado, também poderás adicionar um + pequeno código de uma forma. (Pode ser gerado + aqui) titleEdit: Editar Marco - markerDemoLimit: - desc: Apenas podes criar dois marcos na versão Demo. Adquire o jogo completo para colocar marcos infinitos! + desc: Apenas podes criar dois marcos na versão Demo. Adquire o jogo completo + para colocar marcos infinitos! massCutConfirm: title: Confirmar corte - desc: >- - Estás a cortar muitas construções ( para ser exato)! Tens a certeza? - + desc: Estás a cortar muitas construções ( para ser exato)! Tens a + certeza? exportScreenshotWarning: title: Exportar captura de ecrã - desc: >- - Tu estás a pedir pra exportar a tua base como uma captura de ecrã. Por favor tem em atenção que isto pode - ser um pouco lento para uma base muito grande até mesmo bloquear o teu jogo! - + desc: Tu estás a pedir pra exportar a tua base como uma captura de ecrã. Por + favor tem em atenção que isto pode ser um pouco lento para uma base + muito grande até mesmo bloquear o teu jogo! massCutInsufficientConfirm: title: Confirma o corte - desc: Não consegues pagar para colar esta área! Tens a certeza que pretendes cortá-la? - + desc: Não consegues pagar para colar esta área! Tens a certeza que pretendes + cortá-la? + editSignal: + title: Define o Sinal + descItems: "Escolhe um item pre-definido:" + descShortKey: ... ou insere o pequeno código de uma forma (Pode + ser gerado aqui) + renameSavegame: + title: Renomear Savegame + desc: Podes renomear o teu savegame aqui. + tutorialVideoAvailable: + title: Tutorial Disponível + desc: Existe um vídeo de tutorial disponível para este nível! Gostarias de + o ver? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Disponível + desc: Existe um vídeo de tutorial disponível para este nível, mas apenas + está disponível em Inglês. Gostarias de o ver? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Mover selectBuildings: Selecionar área @@ -296,18 +235,9 @@ ingame: clearSelection: Cancelar pipette: Pipeta switchLayers: Troca de camadas - - # 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: Pressionar para obter variações. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Atalho: - + hotkeyLabel: "Atalho: " infoTexts: speed: Velocidade range: Alcance @@ -315,36 +245,21 @@ ingame: oneItemPerSecond: 1 item / segundo itemsPerSecond: itens / s itemsPerSecondDouble: (x2) - tiles: telas - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Nível completed: Completo unlockText: desbloqueado! buttonNextLevel: Próximo nível - - # Notifications on the lower right notifications: newUpgrade: Está disponível um novo upgrade! gameSaved: O teu jogo foi guardado. - - # The "Upgrades" window + freeplayLevelComplete: Level has been completed! shop: title: Upgrades buttonUnlock: Upgrade - - # 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 statistics: title: Estatísticas dataSources: @@ -353,55 +268,70 @@ ingame: description: Formas geométricas armazenadas no edifício central. produced: title: Produzido - description: Formas geométricas que toda a fábrica produz, incluindo produtos intermédios. + description: Formas geométricas que toda a fábrica produz, incluindo produtos + intermédios. delivered: title: Entregue description: Formas geométricas entregues no edifício central. noShapesProduced: Não foram ainda produzidas formas geométricas. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Tempo de jogo - buildingsPlaced: Construções beltsPlaced: Tapetes rolantes - - buttons: - continue: Continuar - settings: Definições - menu: Voltar ao menu - - # Bottom left tutorial hints tutorialHints: title: Precisas de ajuda? showHint: Mostrar dica hideHint: Fechar - - # When placing a blueprint blueprintPlacer: cost: Preço - - # Map markers waypoints: waypoints: Marcos hub: Edifício Central - description: Carrega com o botão esquerdo num marco para saltar, botão direito para o eliminar.

Pressiona para criar um marco na vista atual, ou botão direito para criar um marco no local selecionado. + description: Carrega com o botão esquerdo num marco para saltar, botão direito + para o eliminar.

Pressiona para criar um marco + na vista atual, ou botão direito para criar um + marco no local selecionado. creationSuccessNotification: Marco criado com sucesso. - - # Interactive tutorial interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Coloca um extrator em cima da forma circular para extraí-la! - 1_2_conveyor: >- - Liga o extrator a um tapete rolante em direção ao Edifício Central!

Dica: Clica e arrasta o tapete com o rato! - - 1_3_expand: >- - Isto NÃO é um jogo idle! Constrói mais extratores e tapetes para atingir o objetivo mais rapidamente.

Dica: Pressiona SHIFT para colocar vários extratores, e usa R para os rodar. - + 1_1_extractor: Coloca um extrator em cima da forma + circular para extraí-la! + 1_2_conveyor: "Liga o extrator a um tapete rolante em direção + ao Edifício Central!

Dica: Clica e + arrasta o tapete com o rato!" + 1_3_expand: "Isto NÃO é um jogo idle! Constrói mais extratores + e tapetes para atingir o objetivo mais rapidamente.

Dica: + Pressiona SHIFT para colocar vários extratores, + e usa R para os rodar." + 2_1_place_cutter: "Agora coloca um Cortador para cortares os circulos + em duas metades!

PS: O cortador corta sempre de cima para + baixo independentemente da sua orientação" + 2_2_place_trash: O cortador pode encravar e parar!

Usa + um lixo para de livrares do atual (!) não + é necessário desperdício. + 2_3_more_cutters: "Bom trabalho! Agora colocamais 2 cortadores para acelerades + este progresso lento!

PS: Usa os atalhos + 0-9 para acederes às contruções mais rapidamente!" + 3_1_rectangles: "Agora vamos extrair alguns retângulos! Constrói 4 + extratores e conecta-os ao edifício central.

PS: + Pressiona SHIFT enquanto arrastas um tapete rolante + para ativares o planeador de tapetes!" + 21_1_place_quad_painter: Coloca o pintor quádruplo e arranja alguns + círculos, cores branca e + vermelha! + 21_2_switch_to_wires: Troca para a camada de fios pressionando + E!

A seguir conecta todas as quatro + entradas do pintor com fios! + 21_3_place_button: Fantástico! Agora coloca o Interruptor e conecta-o + com os fios! + 21_4_press_button: "Pressiona o interruptor para que ele emita um + sinal verdadeiro, isso irá ativar o pintor.

PS: Tu + não tens de conectar todas as entradas! Tenta conectar apenas duas." colors: red: Vermelho green: Verde @@ -416,8 +346,42 @@ ingame: title: Camadas empty: Vazio copyKey: Chave de cópia - -# All shop upgrades + connectedMiners: + one_miner: 1 Extrator + n_miners: Extratores + limited_items: Limite de + watermark: + title: Versão Demo + desc: Clica aqui para veres as vantagens da versão na Steam! + get_on_steam: Compra na Steam + standaloneAdvantages: + title: Obtém a versão completa! + no_thanks: Não, obrigado! + points: + levels: + title: 12 Novos Níveis + desc: Para um total de 26 Níveis! + buildings: + title: 18 Novas contruções + desc: Para uma fábrica totalmente automatizada! + savegames: + title: Savegames ∞ + desc: Tantos quanto o teu corção desejar! + upgrades: + title: 20 Níveis de melhoria + desc: Nesta versão demo apenas tens 5! + markers: + title: Marcos ∞ + desc: Nunca te percas na tua Fábrica! + wires: + title: Fios + desc: Uma dimensão totalmente nova!! + darkmode: + title: Modo Escuro + desc: Não magoes os teus olhos! + support: + title: Ajuda-me + desc: Eu desenvolvo este jogo no meu tempo livre! shopUpgrades: belt: name: Tapetes, Distribuidores e Túneis @@ -431,281 +395,446 @@ shopUpgrades: painting: name: Mistura e Pintura description: Velocidade x → x - -# Buildings and their name / description buildings: belt: default: - name: &belt Tapete Rolante - description: Transporta items. Mantém pressionado e arrasta para colocar vários. - - miner: # Internal name for the Extractor + name: Tapete Rolante + description: Transporta itens. Mantém pressionado e arrasta para colocar vários. + miner: default: - name: &miner Extrator + name: Extrator description: Coloca em cima de uma forma geométrica para extraí-la. - chainable: name: Extrator (Série) - description: Coloca em cima de uma forma geométrica para extraí-la. Pode ser colocado em série. - - underground_belt: # Internal name for the Tunnel + description: Coloca em cima de uma forma geométrica para extraí-la. Pode ser + colocado em série. + underground_belt: default: - name: &underground_belt Túnel + name: Túnel description: Permite transportar recursos por baixo de construções e tapetes. - tier2: name: Túnel Nível II description: Permite transportar recursos por baixo de construções e tapetes. - - splitter: # Internal name for the Balancer - default: - name: &splitter Distribuidor - description: Multifunções - Distribui igualmente todas as entradas por todas as saídas. - - compact: - name: Misturador (Comp.) - description: O Misturador Compacto é uma variante do distibruidor. Junta dois tapetes rolantes num só. - - compact-inverse: - name: Misturador (Comp.) - description: O Misturador Compacto é uma variante do distibruidor. Junta dois tapetes rolantes num só. - cutter: default: - name: &cutter Cortador - description: Corta as formas, de cima para baixo, em duas partes. Se apenas usares uma parte, destrói a outra para não encravar a produção! + name: Cortador + description: Corta as formas, de cima para baixo, em duas partes. Se + apenas usares uma parte, destrói a outra para não encravar a + produção! quad: - name: Cortador (Quad) - description: Corta as formas geométricas em quatro partes. Se apenas usares uma parte, destrói as outras partes para não encravar a produção! - + name: Cortador (Quád) + description: Corta as formas geométricas em quatro partes. Se apenas + usares uma parte, destrói as outras partes para não encravar a + produção! rotater: default: - name: &rotater Rodar + name: Rodar description: Roda as formas 90º no sentido dos ponteiros do relógio. ccw: name: Rodar (CCW) - description: Roda as formas 90º no sentido contrário ao dos ponteiros do relógio. - + description: Roda as formas 90º no sentido contrário ao dos ponteiros do + relógio. + rotate180: + name: Rodar (180º) + description: Roda as formas 180º. stacker: default: - name: &stacker Empilhador - description: Empilha dois itens. Se não podem ser empilhados, o item da direita será colocado em cima do item da esquerda. - + name: Empilhador + description: Empilha dois itens. Se não podem ser empilhados, o item da direita + será colocado em cima do item da esquerda. mixer: default: - name: &mixer Misturador de cor + name: Misturador de cor description: Mistura duas cores através de mistura aditiva. - painter: default: - name: &painter Pintor - description: &painter_desc Pinta a forma geométrica da entrada esquerda com a cor da entrada superior. + name: Pintor + description: Pinta a forma geométrica da entrada esquerda com a cor da entrada + superior. double: name: Pintor (Duplo) - description: Pinta as formas geométricas das entradas esquerdas com a cor da entrada superior. + description: Pinta as formas geométricas das entradas esquerdas com a cor da + entrada superior. quad: name: Pintor (Quádruplo) - description: Pinta cada quadrante da forma geométrica com uma cor diferente. + description: Permite colorir cada quadrante da forma individualmente. Apenas + entradas com um sinal verdadeira na camada de + fios irá ser pintada! mirrored: - name: *painter - description: *painter_desc - + name: Pintor + description: Pinta a forma geométrica da entrada esquerda com a cor da entrada + superior. trash: default: - name: &trash Lixo + name: Lixo description: Aceita entradas de todos os lados e destrói-os. Para sempre. - - storage: - name: Armazém - description: Armazena items em excesso até uma determinada capacidade. Pode ser usado como uma porta de transbordo. hub: deliver: Entrega toUnlock: para desbloquear levelShortcut: NVL + endOfDemo: Fim do Demo wire: default: name: Fio Elétrico - description: Permite o transporte de energia. - advanced_processor: + description: Tranfere sinais, que podem ser itens, cores ou um sinal binário (1 + ou 0). Fios de cores diferestes não se conectam. + second: + name: Fio Elétrico + description: Tranfere sinais, que podem ser itens, cores ou um sinal binário (1 + ou 0). Fios de cores diferestes não se conectam. + balancer: default: - name: Inversor de Cor - description: Aceita uma cor ou forma e inverte-a. - energy_generator: - deliver: Entrega - toGenerateEnergy: Para - default: - name: Gerador - description: Gera energia consumindo formas. - wire_crossings: - default: - name: Repartidor - description: Divide um fio elétrico em dois. + name: Distribuidor + description: Multifunções - Distribui igualmente todas as entradas por todas as + saídas. merger: - name: Conector de junção - description: Junta dois fios elétricos num só. - + name: Misturador (comp.) + description: Junta dois tapetes rolantes num só. + merger-inverse: + name: Misturador (comp.) + description: Junta dois tapetes rolantes num só. + splitter: + name: Divisor (compacto) + description: Divide um tapete rolante em dois. + splitter-inverse: + name: Divisor (compacto) + description: Divide um tapete rolante em dois. + storage: + default: + name: Armazém + description: Armazena itens em excesso, até uma determinada capacidade. Dá + prioridade à saída da esquerda e pode ser usado como uma porta + de transbordo. + wire_tunnel: + default: + name: Túnel de Fios + description: Permite que dois fios cruzem sem conectarem-se um ao outro. + constant_signal: + default: + name: Sinal Constante + description: Emite um sinal constante , que pode ser uma forma, cor ou um sinal + binário (1 ou 0). + lever: + default: + name: Interruptor + description: Pode emitir alternadamente um sinal binário (1 ou 0) na camada de + fios, que pode posteriormente ser usado, por exemplo, num filtro + de itens. + logic_gate: + default: + name: Portão AND + description: 'Emite um sinal binário "1" se ambas as entradas forem verdadeiras. + (Verdadeiro significa: forma, cor ou sinal binário "1")' + not: + name: Portão NOT + description: 'Emite um sinal binário "1" se a entrada não for verdadeira. + (Verdadeiro significa: forma, cor ou sinal binário "1")' + xor: + name: Portão XOR + description: 'Emite um sinal binário "1" se uma das entradas for verdadeira, mas + não as duas. (Verdadeiro significa: forma, cor ou sinal binário + "1")' + or: + name: Portão OR + description: 'Emite um sinal binário "1" se uma entrada é verdadeira. + (Verdadeiro significa: forma, cor ou sinal binário "1")' + transistor: + default: + name: Transístor + description: Encaminha a entrada inferior se a entrada lateral for verdade (uma + forma, cor ou "1"). + mirrored: + name: Transístor + description: Encaminha a entrada inferior se a entrada lateral for verdade (uma + forma, cor ou "1"). + filter: + default: + name: Filtro de Itens + description: Conecta um sinal que irá encaminhar todos os itens correspondentes + para o topo e os restantes para a direita. Também pode ser + controlado com sinais binários. + display: + default: + name: Visor + description: Conecta um sinal para mostrar no Visor - Pode ser uma forma, cor ou + um sinal binário. + reader: + default: + name: Leitor de Tapete + description: Permite medir a passagem média de itens no tapete. Fornece o último + item lido na camada de fios (quando desbloqueada). + analyzer: + default: + name: Analizador de Forma + description: Analiza o quadrante superior direito da camada mais baixa da forma + e retorna a forma ou cor. + comparator: + default: + name: Comparador + description: Produz o sinal binário "1" se ambos os itens são exatamente iguais. + Pode comparar formas, itens e sinais binários. + virtual_processor: + default: + name: Cortador Virtual + description: Virtualmente, corta as formas em duas metades. + rotater: + name: Rodador Virtual + description: Virtualmente, roda a forma tanto no sentido horário quanto no + anti-horário. + unstacker: + name: Desempilhador Virtual + description: Virtualmente, remove a camada do topo para a saída da direita e o + restante para a da esquerda. + stacker: + name: Empilhador Virtual + description: Virtualmente empilhada a forma da direita em cima do item da + esquerda. + painter: + name: Pintor Virtual + description: Virtualmente, pinta a forma a forma da entrada de baixo com o item + da entrada da direita. + item_producer: + default: + name: Produtor de Itens + description: Disponível apenas no modo sandbox, produz o sinal dado na camada de + fios na camada normal. storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Corte de formas - desc: Acabaste de desbloquear o Cortador - ele corta as formas geométricas ao meio de cima para baixo independentemente da orientação!

Certifica-te de que te livras do desperdício, caso contrário encravará - Para isso, dou-te um lixo, que destruirá tudo o que lá colocares! - + desc: Acabaste de desbloquear o cortador, que corta as formas + ao meio de cima para baixo independentemente da sua + orientação!

Certefica-te de que te livras do + desperdício, caso contrário irá encravar e parar - + Para este propósito eu dei-te um lixo, que destrói + tudo o que lá colocares! reward_rotater: title: Rotação - desc: O Rodador foi desbloqueado! Ele roda as formas geométricas 90º no sentido dos ponteiros do relógio. - + desc: O Rodador foi desbloqueado! Ele roda as formas + geométricas 90º no sentido dos ponteiros do relógio. reward_painter: title: Pintura - desc: >- - O Pintor foi desbloqueado - Extrai alguns pigmentos coloridos (tal como fazes com as formas) e combina-os com uma forma no pintor para a colorir!

PS: Se fores daltónico, existe um modo daltónico nas definições! - + desc: "O Pintor foi desbloqueado - Extrai alguns pigmentos + coloridos (tal como fazes com as formas) e combina-os com uma forma + no pintor para a colorir!

PS: Se fores daltónico, existe um + modo daltónico nas definições!" reward_mixer: title: Mistura de Cores - desc: O Misturador foi desbloqueado - Combina duas cores através de mistura aditiva com esta construção! - + desc: O Misturador foi desbloqueado - Combina duas cores + através de mistura aditiva com esta construção! reward_stacker: title: Combinador - desc: Agora podes combinar formas geométricas com o Combinador! Ambas as entradas são combinados e, se puderem ser colocados lado-a-lado, serão fundidas. Caso contrário, a entrada da direita é empilhada em cima da da esquerda! - + desc: Agora podes combinar formas geométricas com o Combinador! + Ambas as entradas são combinados e, se puderem ser colocados + lado-a-lado, serão fundidas. Caso contrário, a + entrada da direita é empilhada em cima da da + esquerda! reward_splitter: - title: Distribuidor/Misturador - desc: O Distribuidor multi-funções foi desbloqueado - Pode ser usado para construir fábricas maiores separando e convergindo items para vários tapetes!

- + title: Divisor + desc: Desbloqueaste o dvisor uma variante do + distribuidor - Aceita uma entradae divide-a em + duas! reward_tunnel: title: Túnel - desc: O Túnel foi desbloqueado - Com ele podes passar itens através de tapetes e construções! - + desc: O Túnel foi desbloqueado - Com ele podes passar itens + através de tapetes e construções! reward_rotater_ccw: title: Rotação CCW - desc: Desbloqueaste uma variante do Rodador - Permite rodar no sentido contrário ao dos ponteiros do relógio! Para construí-lo, seleciona o Rodador e pressiona 'T' para escolher as variantes! - + desc: Desbloqueaste uma variante do Rodador - Permite rodar no + sentido contrário ao dos ponteiros do relógio! Para construí-lo, + seleciona o Rodador e pressiona 'T' para escolher as + variantes! reward_miner_chainable: title: Extração em série - desc: Desbloqueaste o Extrator em série! Permite enviar o recurso extraído para outros extratores, permitindo uma extração mais eficiente! - + desc: "Desbloqueaste o extrator em séire! Permite + enviar os recursos para outros extratores, sendo + assim permite uma extração de recursos mais eficiente!

PS: O + extrator antigo já foi trocado na tua lista de construções!" reward_underground_belt_tier_2: title: Túnel Nível II - desc: Desbloqueaste uma nova variante do Túnel - Tem um maior alcance, e podes interlaçar as duas variantes entre si! - - reward_splitter_compact: - title: Distribuidor compacto - desc: >- - Desbloqueaste uma variante compacta do Distribuidor - Aceita duas entradas e junta-as numa só! - + desc: Desbloqueaste uma nova variante do Túnel - Tem um + maior alcance, e podes interlaçar as duas variantes + entre si! reward_cutter_quad: title: Corte quádruplo - desc: Desbloqueaste a variante do Cortador - Permite cortar formas geométricas em quatro partes em vez de apenas duas! - + desc: Desbloqueaste a variante do Cortador - Permite cortar + formas geométricas em quatro partes em vez de + apenas duas! reward_painter_double: title: Pintura dupla - desc: Desbloqueaste uma variante do Pintor - Funciona como um pintor normal mas processa duas formas ao mesmo tempo consumindo apenas uma cor em vez de duas! - - reward_painter_quad: - title: Pintura quádrupla - desc: Desbloqueaste uma variante do Pintor - Permite pintar cada parte da forma geométrica individualmente! - + desc: Desbloqueaste uma variante do Pintor - Funciona como um + pintor normal mas processa duas formas ao mesmo + tempo consumindo apenas uma cor em vez de duas! reward_storage: title: Armazém - desc: Desbloqueaste uma variante do Lixo - Permite armazenar items até uma determinada capacidade! - + desc: Desbloqueaste uma variante do lixo - Permite armazenar + itens, até uma determinada capacidade!

Dá prioridade à saída + da esquerda e pode ser usado como uma porta de + transbordo! reward_freeplay: title: Jogo livre - desc: Conseguiste! Desbloqueaste o modo jogo livre! Isto significa que agora as formas são geradas aleatoriamente! (Não te prepcupes, está planeado mais conteúdo para o jogo completo!) - + desc: Conseguiste! Desbloqueaste o modo jogo livre! Isto + significa que agora as formas são geradas + aleatoriamente!

Como o edifício central vai + precisar de uma taxa de rendimento a partir de + agora, recomendo vivamente a contruires uma máquina que, + automaticamente, entraga as formas pedidas!

O edifício + central emite a forma pedida na camada de fios,sendo assim tudo o + que tens a fazer é analiza-la e automaticamente configurares a tua + fábrica baseada nisso. reward_blueprints: title: Projetos - desc: Agora podes copiar e colar partes da tua fábrica! Seleciona uma área (Mantém pressionado CTRL e arrasta com o rato), e pressiona 'C' para copiar.

Colar não é gratuito, precisas de produzir formas projeto para o pagares! (Aquelas que acabaste de entregar). - - # Special reward, which is shown when there is no reward actually + desc: Agora podes copiar e colar partes da tua fábrica! + Seleciona uma área (Mantém pressionado CTRL e arrasta com o rato), e + pressiona 'C' para copiar.

Colar não é + gratuito, precisas de produzir formas + projeto para o pagares! (Aquelas que acabaste de entregar). no_reward: title: Próximo nível - desc: >- - Este nível não te deu nenhuma recompensa, mas o próximo dará!

PS: É melhor não destruires a tua fábrica atual - Precisarás de todas essas formas no futuro para desbloquear upgrades! - + desc: "Este nível não te deu nenhuma recompensa, mas o próximo dará!

+ PS: É melhor não destruires a tua fábrica atual - Precisarás de + todas essas formas no futuro para + desbloquear upgrades!" no_reward_freeplay: title: Próximo nível - desc: >- - Parabéns! Já agora, está planeado mais conteúdo para o jogo completo! - + desc: Parabéns! Já agora, está planeado mais conteúdo para o jogo completo! + reward_balancer: + title: Distribuidor + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Misturador (compacto) + desc: Desbloqueaste um misturador, uma variante do + distribuidor - Aceita duas entradas e junta-as num + só tapete rolante! + reward_belt_reader: + title: Leitor de Tapete + desc: Desbloqueaste o leitor de tapete! Permite-te medires a + passagem média de itens no tapete.

E espera por desbloqueares + os fios - aí é que vão ser bastante úteis! + reward_rotater_180: + title: Rodar (180º) + desc: Desbloqueaste o rodador de 180 graus! - Permite-te + rodares formas 180 graus (Surpresa! :D) + reward_display: + title: Visor + desc: "Desbloqueaste o Visor - Conecta um sinal na camada de + fios para o visualizares!

PS: Reparaste que o leitor de + tapete e o armazém emitem o último item lido por eles? tenta mostrar + isso num visor!" + reward_constant_signal: + title: Sinal Constante + desc: Desbloqueaste o sinal constante contruido na camada de + fios! Isto é útil conectado com um filtro de itens + por exemplo.

O sinal constante pode emitir uma + forma, cor ou sinal + binário (1 ou 0). + reward_logic_gates: + title: Portões Lógicos + desc: Desbloqueaste os portões lógicos! N tens de te excitar + com isto, mas é realmente super fixe!

Com estes portões + agora podes realizar operações AND, OR, XOR and NOT.

Como um + bónus anteriormente já de dei um transístor! + reward_virtual_processing: + title: Processamento Virtual + desc: Acadei de te dar um monte de novas construções, que te vão permitir + simular o processamento de formas!

Agora + podes simular um cortador,um rodador, um empilhador e muito mais na + camada de fios! Com isto, agora tens três opções para continuares o + jogo:

- Construir uma máquina automática + para criar qualquer forma possível pedida pelo Edifício Central + (Reconmento-te a experimentares!).

- Contruir algo fixe com + os fios.

- Continuar a jogar regularmente.

+ Independentemente da tua escolha, lembra-te de te divertires! + reward_wires_painter_and_levers: + title: Fios & Pintor Quádruplo + desc: "Desbloquaste a Camada de Fios: É uma camada separada no + topo da camada normal e introduz um monte de novas + mecânicas!

Para o inicio eu dei-te o Pintor + Quádruplo - Conecta as entradas que queres pintar na camada + de fios!

Para trocares para a camada de fios, pressiona a + tecla E.

PS: Ativa as dicas nas + definições para ativares o tutorial de fios!" + reward_filter: + title: Filtro de Itens + desc: Desbloquaste o Filtro de Itens! Vai mandar itens ou para + o topo ou para a saída da esquerda dependendo depending se são + iguais ao sinal da camada de fios ou não.

Também podes + passar um sinal binário (1 ou 0) para ativa-lo ou desativa-lo + totalmente. + reward_demo_end: + title: Fim da Demo + desc: Tu chegaste ao fim da versão demo! settings: title: Definições categories: - game: Jogo - app: Aplicação - + general: Geral + userInterface: Interface de Utilizador + advanced: Avançado + performance: Performance versionBadges: dev: Desenvolvimento staging: Ensaio prod: Produção buildDate: Construido - labels: uiScale: title: Escala da interface - description: >- - Altera o tamanho da interface do utilizador. A interface será redimensionada com base na resolução do teu dispositivo, mas esta definição controla a escala. + description: Altera o tamanho da interface do utilizador. A interface será + redimensionada com base na resolução do teu dispositivo, mas + esta definição controla a escala. scales: super_small: Super pequeno small: Pequeno regular: Médio large: Grande huge: Enorme - scrollWheelSensitivity: title: Sensibilidade do zoom - description: >- - Define o quão sensível é o zoom (Roda do rato ou trackpado). + description: Define o quão sensível é o zoom (Roda do rato ou trackpado). sensitivity: super_slow: Muito lento slow: Lento regular: Normal fast: Rápido super_fast: Muito rápido - language: title: Língua - description: >- - Muda a língua. Todas as traduções são contribuições dos utilizadores e podem estar incompletas! - + description: Muda a língua. Todas as traduções são contribuições dos + utilizadores e podem estar incompletas! fullscreen: title: Ecrã inteiro - description: >- - É recomendado jogar o jogo em ecrã inteiro para a melhor experiência. Apenas disponível no jogo completo. - + description: É recomendado jogar o jogo em ecrã inteiro para a melhor + experiência. Apenas disponível no jogo completo. soundsMuted: title: Desativar sons - description: >- - Se ativado, desativa todos os sons. - + description: Se ativado, desativa todos os sons. musicMuted: title: Desativar música - description: >- - Se ativado, desativa todas as músicas. - + description: Se ativado, desativa todas as músicas. theme: title: Tema do jogo - description: >- - Escolhe o tema do jogo (claro / escuro). - + description: Escolhe o tema do jogo (claro / escuro). themes: dark: Escuro light: Claro - refreshRate: title: Frequência - description: >- - Se tens um monitor 144hz, muda a frequência para que o jogo simule corretamente frequências de autalização altas. Isto pode resultar em perda de FPS se o teu computador for demasiado lento. - + description: Se tens um monitor 144hz, muda a frequência para que o jogo simule + corretamente frequências de autalização altas. Isto pode + resultar em perda de FPS se o teu computador for demasiado + lento. alwaysMultiplace: title: Colocação múltipla - description: >- - Se ativado, todas as construções permanecerão selecionadas após a colocação até cancelares. Isto é equivalente a pressionares SHIFT permanentemente. - + description: Se ativado, todas as construções permanecerão selecionadas após a + colocação até cancelares. Isto é equivalente a pressionares + SHIFT permanentemente. offerHints: title: Dicas e tutoriais - description: >- - Se ativado, dá dicas e tutoriais de apoio ao jogo. Adicionalmente, esconde certos elementos da interface do utilizador até ao nível em que são desbloqueados de forma a simplificar o início do jogo. - + description: Se ativado, dá dicas e tutoriais de apoio ao jogo. Adicionalmente, + esconde certos elementos da interface do utilizador até ao nível + em que são desbloqueados de forma a simplificar o início do + jogo. movementSpeed: title: Velocidade de movimentação description: Define quão rápida é a movimentação usando o teclado. @@ -718,20 +847,17 @@ settings: extremely_fast: Extremamente rápida enableTunnelSmartplace: title: Túneis inteligentes - description: >- - Quando ativado, a colocação de túneis removerá tapetes desnecessários automaticamente. - Isto também permite arrastar túneis e túneis em excesso serão removidos. + description: Quando ativado, a colocação de túneis removerá tapetes + desnecessários automaticamente. Isto também permite arrastar + túneis e túneis em excesso serão removidos. vignette: title: Vinheta - description: >- - Ativa a vinheta, que escurece os cantos do ecrã e torna a leitura do texto - mais fácil. - + description: Ativa a vinheta, que escurece os cantos do ecrã e torna a leitura + do texto mais fácil. autosaveInterval: title: Intervalo de gravação automática - description: >- - Define o quão frequentemente o jogo grava automaticamente. Também podes desativar - aqui. + description: Define o quão frequentemente o jogo grava automaticamente. Também + podes desativar aqui. intervals: one_minute: 1 Minuto two_minutes: 2 Minutos @@ -741,32 +867,79 @@ settings: disabled: Desligado compactBuildingInfo: title: Informações de construções compactas - description: >- - Encurta caixas de informação e apenas mostra os respetivos rácios. Caso contrário - é mostrada a descrição e a imagem. + description: Encurta caixas de informação e apenas mostra os respetivos rácios. + Caso contrário é mostrada a descrição e a imagem. disableCutDeleteWarnings: title: Desativar Avisos de Corte/Eliminação - description: >- - Desativa os avisos mostrados quando é feito o corte ou a eliminação de mais de 100 - entidades. - + description: Desativa os avisos mostrados quando é feito o corte ou a eliminação + de mais de 100 entidades. enableColorBlindHelper: title: Modo Daltónico - description: Ativa várias ferramentas que te permitirão jogar o jogo se fores daltónico. + description: Ativa várias ferramentas que te permitirão jogar o jogo se fores + daltónico. rotationByBuilding: title: Rotação por tipo de construção - description: >- - Cada tipo construção lembra-se da última rotação que definiste. - Esta definição pode ser mais confortável se alterares frequentemente - a colocação de diferentes tipos de construções. - + description: Cada tipo construção lembra-se da última rotação que definiste. + Esta definição pode ser mais confortável se alterares + frequentemente a colocação de diferentes tipos de construções. + soundVolume: + title: Volume do Som + description: Define o volume para efeitos sonoros + musicVolume: + title: Volume da Música + description: Define o volume para música + lowQualityMapResources: + title: Recursos de Mapa de Baixa Qualidade + description: Simplifica a renderização de recursos quando o mapa está ampliado + para melhorar o desempenho. Até parece mais limpo, então + lembra-te de experimentares! + disableTileGrid: + title: Desativar Grelha + description: Desativar a grelha pode ajudar com o desempenho. Isto também fazz o + jogo parecer mais limpo! + clearCursorOnDeleteWhilePlacing: + title: Limpar Cursor com Clique Direito + description: Ativado por padrão, limpa o cursor sempre que pressionas o botão + direito do rato enquanto tens um edifício para colocamento. Se + desativado, podes apagar construções pressionando o botão + direito do rato enquanto colocas um edifício. + lowQualityTextures: + title: Texturas de baixa qualidade (Feio) + description: sa texturas de baixa qualidade para melhorar o desempenho. sto vai + tornar o jogo parecer muito feio! + displayChunkBorders: + title: Mostrar bordas de limites (chunk borders) + description: O jogo está dividido em partes de 16x16 quadrados, se esta + dedinição estiver ativada as bordas de cada limitece são + mostradas. + pickMinerOnPatch: + title: Selecionar extrator num quadrado de recurso + description: Ativado por padrão, seleciona um extrator se usares a pipeta quando + estiveres com o rato em cima de um quadrado de recurso. + simplifiedBelts: + title: Tapetes rolantes simplificados (Feio) + description: Não renderiza os intens nos tapetes excepto quando tens o rato em + cima do tapete para melhorar o desempenho. Não recomendo a + jogares com esta definição ativada a não ser que precises mesmo + de melhorar o desempenho. + enableMousePan: + title: Ativar rato panorâmico + description: Permite-te mover o mapa movento o rato nos cantos do ecrâ. A + velociade depende da definição de velocidade de movimentação. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: Atalhos - hint: >- - Tip: Utiliza o CTRL, o SHIFT e o ALT! Eles permitem diferentes opções de posicionamento. - + hint: "Dica: Utiliza o CTRL, o SHIFT e o ALT! Eles permitem diferentes opções de + posicionamento." resetKeybindings: Resetar Atalhos - categoryLabels: general: Aplicação ingame: Jogo @@ -775,7 +948,6 @@ keybindings: massSelect: Seleção em massa buildings: Atalhos de construções placementModifiers: Modificadores de posicionamento - mappings: confirm: Confirmar back: Retroceder @@ -784,38 +956,30 @@ keybindings: mapMoveDown: Mover para baixo mapMoveLeft: Mover para a esquerda centerMap: Centrar o mapa - mapZoomIn: Zoom in mapZoomOut: Zoom out createMarker: Criar Marco - menuOpenShop: Upgrades menuOpenStats: Estatísticas - toggleHud: Ativar/Desativar HUD toggleFPSInfo: Mostrar FPS e Debug info - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + belt: Tapete Rolante + underground_belt: Túnel + miner: Extrator + cutter: Cortador + rotater: Rodar + stacker: Empilhador + mixer: Misturador de cor + painter: Pintor + trash: Lixo rotateWhilePlacing: Rotação - rotateInverseModifier: >- - Modifier: Rotação CCW + rotateInverseModifier: "Modificador: Rotação CCW" cycleBuildingVariants: Mudar variantes confirmMassDelete: Confirmar eliminação em massa cycleBuildings: Mudar construções - massSelectStart: Pressiona e arrasta para começar massSelectSelectMultiple: Selecionar várias áreas massSelectCopy: Copiar a área - placementDisableAutoOrientation: Desativa orientação automática placeMultiple: Continuar no modo de colocação placeInverse: Inverter orientação automática do tapete @@ -828,32 +992,38 @@ keybindings: pipette: Pipeta menuClose: Fechar Menu switchLayers: Troca de camadas - advanced_processor: Inversor de Cor - energy_generator: Gerador wire: Fio Elétrico + balancer: Distribuidor + storage: Armazém + constant_signal: Sinal Constante + logic_gate: Portões Lógicos + lever: Interruptor (normal) + filter: Filtro de itens + wire_tunnel: Túnel de Fio + display: Display + reader: Leitor de Tapete + virtual_processor: Cortador Virtual + transistor: Transistor + analyzer: Analisador de Forma + comparator: Comparador + item_producer: Produtor de Itens (Sandbox) + copyWireValue: "Fios: Copia o valor debaixo do cursor" about: - title: Sobre o jogo + title: Sobre o Jogo body: >- - Este jogo é código aberto e desenvolvido por Tobias Springer (este sou eu).

+ Este jogo é código aberto e desenvolvido por Tobias Springer + (este sou eu).

- Se quiseres contribuir, dá uma olhadela em shapez.io no github.

+ Se quiseres contribuir, dá uma olhadela em shapez.io no github.

- 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!

+ 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!

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

- - Finalmente, um grande agradecimento ao meu melhor amigo Niklas - Sem as nossas - sessões de factorio este jogo nunca teria existido. + A banda sonora foi feita por Peppsen - Ele é Fantástico.

+ Finalmente, um grande agradecimento ao meu melhor amigo Niklas - Sem as nossas sessões de factorio este jogo nunca teria existido. changelog: title: Changelog - demo: features: restoringGames: Restauro de savegames @@ -861,5 +1031,74 @@ demo: oneGameLimit: Limitado a um savegame customizeKeybindings: Costumizar Atalhos exportingBase: Exportar base como uma imagem - settingNotAvailable: Não disponível no Demo. +tips: + - O edifício central aceita qualquer entrada, não apenas a da forma atual! + - Tem a certeza que as tuas fábricas são modulares - vai valer a pena! + - Não construas demasiado perto do edifício, ou será um grande caos! + - Se empilhar não funciona, tenta trocar as entradas. + - Podes alternar a direção do planeador de tapete rolante ao pressionar + R. + - Ao pressionares CTRL podes arrastar tapetes rolantes sem auto-orientação. + - Os rácios continuam os mesmos, desde que todos os upgrades estejam no + mesmo Nível. + - Execução em série é mais eficiente que em paralelo. + - Vais desbloquear mais variações de edifícios, mais tarde no jogo! + - Podes usar T para trocares entre as diferentes variantes. + - Simetria é a solução! + - Podes entrelaçar diferentes tipos de túneis. + - Tenta construir fábricas compactas - vai valer a pena! + - O pintor tem uma variante espelhada que podes selecionar com T + - Ter os rácios de edifícios corretos vai maximizar a eficiência. + - No nível máximo, 5 extratores vão encher um tapete. + - Não te esqueças dos túneis! + - Não tens de dividir os itens uniformemente para eficiência máxima. + - Segurar SHIFT vai ativar o planeador de tapetes, deixando-te + colocar longas linhas de tapetes facilmente. + - Os cortadores cortam sempre verticalmente, independentemente da sua + orientação. + - Para obter branco junta as três cores. + - O buffer do armazém prioritiza a primeira saída. + - Investe tempo para costruir designs repetiveis - vale a pena! + - Segurar CTRL permite-te colocar vários edifícios. + - Podes segurar ALT para inverter a direção de tapetes colocados. + - Eficiência é a solução! + - As formas que estão mais longes do edifício central são mais complexas. + - As Máquinas têm uma velocidade limitada, divide-as para eficiência máxima. + - Usa balanceadores para maximizar a tua eficiência. + - Organização é importante. Tenta não cruzar demasiados tapetes. + - Planeia antecipadamente, ou vai ser um grande caos! + - Não removas as tuas fábricas antigas! Vais precisar delas para desbloqueares + upgrades. + - Tenta superar o nível 20 sozinho sem procurar ajuda! + - Não complicas as coisas, tenta continuar simples e irás muito longe. + - Talvez precises de reutilizar fábricas, mais tarde no jogo. Planeia as tuas + fábricas para serem reutilizáveis. + - Às vezes, podes encontrar uma forma necessária no mapa sem criar-la com + empilhadoras. + - Moinhos de vento e cataventos completos nunca aparecem naturalmente. + - Pinta as tuas formas antes de as cortares para eficiência máxima. + - Com módulos, o espaço é apenas uma perceção; uma preocupação para pessoas + mortais. + - Faz uma fábrica de diagramas separada. São importantes para módulos. + - Dá uma olhada ao misturador de cores, e as tuas questões serão respondidas. + - Usa CTRL + Clique para selecionar uma área. + - Construir demasiado perto do edifício central pode ficar no caminho de + projetos futuros. + - O ícone de alfinete perto duma forma na lista de upgrades vai afixa-la ao + ecrã. + - Junta todas as cores primárias para fazeres branco! + - Tu tens um mapa infinito, não limites a tua fábrica, expande! + - Tenta também Factorio! É o meu jogo favorito. + - O cortador quádruplo corta no sentido dos ponteiros do relógio começando no canto + superior direito! + - Podes fazer download dos teus savegames no menu principal! + - Este jogo tem muitos atalhos de teclado úteis! Não te esqueças de + verificar a página de configurações. + - Este jogo tem muitas definições, não te esqueças de as verificar! + - O marco para o teu edifício central tem uma pequena bússola para indicar a + sua direção! + - Para limpar tapetes, corta a área e cola-a na mesma localização. + - Pressiona F4 para mostrar os teus FPS e Tick Rate. + - Pressiona F4 duas vezes para mostrar a tile do teu rato e câmara. + - Podes clicar numa forma afixada no lado direito para desafixa-la. diff --git a/translations/base-ro.yaml b/translations/base-ro.yaml index d7b7a8fc..e90ca308 100644 --- a/translations/base-ro.yaml +++ b/translations/base-ro.yaml @@ -1,111 +1,64 @@ -# -# 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 este un joc despre construirea fabricilor pentru a automatiza crearea și combinarea a din ce in ce mai complexe forme într-o hartă infinită. + 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ă. + discordLinkShort: Official Discord + intro: >- + Shapez.io is a relaxed game in which you have to build factories for the + automated production of geometric shapes. - # 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] + As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map. - 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. + And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! - 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]! + While you only process shapes at the beginning, you have to color them later - for this you have to extract and mix colors! - 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. + Buying the game on Steam gives you access to the full version, but you can also play a demo on shapez.io first and decide later! + title_advantages: Standalone Advantages + advantages: + - 12 New Level for a total of 26 levels + - 18 New Buildings for a fully automated factory! + - 20 Upgrade Tiers for many hours of fun! + - Wires Update for an entirely new dimension! + - Dark Mode! + - Unlimited Savegames + - Unlimited Markers + - Support me! ❤️ + title_future: Planned Content + planned: + - Blueprint Library (Standalone Exclusive) + - Steam Achievements + - Puzzle Mode + - Minimap + - Mods + - Sandbox mode + - ... and a lot more! + title_open_source: This game is open source! + title_links: Links + links: + discord: Official Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Help translate + text_open_source: >- + Anybody can contribute, I'm actively involved in the community and + attempt to review all suggestions and take feedback into consideration + where possible. - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! - global: loading: Se Încarcă error: Eroare - - # 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. + decimalSeparator: . suffix: thousands: k millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: inf - time: - # Used for formatting past time dates oneSecondAgo: acum o secundă xSecondsAgo: acum secunde oneMinuteAgo: acum un minut @@ -114,14 +67,10 @@ global: xHoursAgo: acum ore oneDayAgo: acum o zi xDaysAgo: acum zile - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s hoursAndMinutesShort: h m - xMinutes: minute - keys: tab: TAB control: CTRL @@ -129,13 +78,9 @@ global: escape: ESC shift: SHIFT space: SPACE - demoBanners: - # This is the "advertisement" shown in the main menu and other various places title: Versiunea Demo - intro: >- - Ia versiunea Standalone pentru a debloca toate funcțiile! - + intro: Ia versiunea Standalone pentru a debloca toate funcțiile! mainMenu: play: Joacă changelog: Changelog @@ -143,20 +88,15 @@ mainMenu: openSourceHint: Acest joc este open source! discordLink: Serverul oficial de Discord helpTranslate: Ajută să traducem! - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - Scuze dar, jocul este știut să ruleze încet pe browser-ul tău! Ia versiunea standalone sau descarcă chrome pentru experiența completă. - + browserWarning: Scuze dar, jocul este știut să ruleze încet pe browser-ul tău! + Ia versiunea standalone sau descarcă chrome pentru experiența completă. savegameLevel: Nivelul savegameLevelUnknown: Nivel necunoscut - - continue: Continuă newGame: Joc nou madeBy: Făcut de subreddit: Reddit - + savegameUnnamed: Unnamed dialogs: buttons: ok: OK @@ -170,111 +110,109 @@ dialogs: viewUpdate: Vezi Update-ul showUpgrades: Vezi Upgrade-urile showKeybindings: Arată tastele configurate - importSavegameError: title: Eroare la Import - text: >- - Încercarea de import a eșuat: - + text: "Încercarea de import a eșuat:" importSavegameSuccess: title: Savegame importat - text: >- - Savegame-ul tău a fost importat cu succes. - + text: Savegame-ul tău a fost importat cu succes. gameLoadFailure: title: Jocul este stricat - text: >- - Încercarea de încărcat savegame-ul a eșuat: - + text: "Încercarea de încărcat savegame-ul a eșuat:" confirmSavegameDelete: title: Confirmă ștergerea - text: >- - Ești sigur că vrei să ștergi acest joc? - + text: Are you sure you want to delete the following game?

+ '' at level

This can not be + undone! savegameDeletionError: title: Eroare la ștergere - text: >- - Nu a reușit să se ștearga savegame-ul: - + text: "Nu a reușit să se ștearga savegame-ul:" restartRequired: title: Restartare necesară - text: >- - Trebuie să restartezi jocul pentru a aplica setările. - + text: Trebuie să restartezi jocul pentru a aplica setările. editKeybinding: title: Schimbă Tastele configurate - desc: Apasă tasta sau butonul mouse-ului pe care vrei să îl atribui, sau escape pentru a anula. - + desc: Apasă tasta sau butonul mouse-ului pe care vrei să îl atribui, sau escape + pentru a anula. resetKeybindingsConfirmation: title: Resetează Tastele configurate - desc: Acesta va reseta toate tastele configurate la valorile obișnuite. Vă rog să confirmați. - + desc: Acesta va reseta toate tastele configurate la valorile obișnuite. Vă rog + să confirmați. keybindingsResetOk: title: Tastele configurate se resetează desc: Tastele configurate au fost resetate la valorile lor obișnuite! - featureRestriction: title: Demo Version - desc: Ai încercat să accesezi o funcție () care nu este disponibilă în demo. Consideră să iei standalone-ul pentru experiența completă! - + desc: Ai încercat să accesezi o funcție () care nu este disponibilă în + demo. Consideră să iei standalone-ul pentru experiența completă! oneSavegameLimit: title: Savegame-uri limitate - desc: Poți avea doar un savegame în același timp în versiunea demo. Te rugăm șterge-o pe cea existentă sau ia standalone-ul! - + desc: Poți avea doar un savegame în același timp în versiunea demo. Te rugăm + șterge-o pe cea existentă sau ia standalone-ul! updateSummary: title: Update nou! - desc: >- - Aici sunt schimbările de când ai jucat ultima oară: - + desc: "Aici sunt schimbările de când ai jucat ultima oară:" upgradesIntroduction: title: Deblochează Upgrade-uri - desc: >- - Toate formele pe care le produci pot fi folosite să deblochezi upgrade-uri - Nu îți distruge vechile fabrici! - Fila upgrade-urilor poate fi găsită în colțul din dreapta sus al ecranului. - + desc: Toate formele pe care le produci pot fi folosite să deblochezi upgrade-uri + - Nu îți distruge vechile fabrici! Fila + upgrade-urilor poate fi găsită în colțul din dreapta sus al + ecranului. massDeleteConfirm: title: Confirmă ștergerea - desc: >- - Stergeți multe construcții ( pentru a fi exact)! Sunteți sigur că vreți să faceți asta? - + desc: Stergeți multe construcții ( pentru a fi exact)! Sunteți sigur că + vreți să faceți asta? blueprintsNotUnlocked: title: Nu este deblocat încă - desc: >- - Planurile nu au fost deblocate încă! Completează mai multe nivele să le deblochezi. - + desc: Planurile nu au fost deblocate încă! Completează mai multe nivele să le + deblochezi. keybindingsIntroduction: title: Taste configurate folositoare - desc: >- - Acest joc are multe taste configurate care fac construitul fabricilor mari mai ușor. - Aici sunt câteva dar, fii sigur să verifici tastele configurate!

- CTRL + Drag: Selectează o zonă pentreu a copia / delete.
- SHIFT: Ține apăsat pentru a plasa mai multe dintr-o clădire.
- ALT: Inversează orientația a benzilor rulante.
- + desc: "Acest joc are multe taste configurate care fac construitul fabricilor + mari mai ușor. Aici sunt câteva dar, fii sigur să verifici + tastele configurate!

CTRL + Drag: Selectează o zonă pentreu a + copia / delete.
SHIFT: Ține + apăsat pentru a plasa mai multe dintr-o clădire.
ALT: Inversează orientația a benzilor + rulante.
" createMarker: title: Nou waypoint - desc: Dă-i un nume plin de înțeles, de asemenea poți include a codul scurt al unei forme (Pe care îl poți genera here) + 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: Poți crea decât două waypoint-uri personalizate în demo. Ia standalone-ul pentru Waypoint-uri nelimitate! + desc: Poți crea decât două waypoint-uri personalizate în demo. Ia standalone-ul + pentru Waypoint-uri nelimitate! massCutConfirm: title: Confirmă tăierea - desc: >- - Tu tai multe construcții ( pentru a fi precis)! Sunteți sigur că vreți să faceți asta? - + desc: Tu tai multe construcții ( pentru a fi precis)! Sunteți sigur că + vreți să faceți asta? exportScreenshotWarning: title: Exportează captură de ecran - desc: >- - Ai solicitat să exportezi baza ta ca o captură de ecran. Vă rugăm să rețineți că asta poate fi destul de lent pentru o bază mare și poate chiar să blocheze jocul! - + desc: Ai solicitat să exportezi baza ta ca o captură de ecran. Vă rugăm să + rețineți că asta poate fi destul de lent pentru o bază mare și poate + chiar să blocheze jocul! massCutInsufficientConfirm: title: Confirm cut desc: You can not afford to paste this area! Are you sure you want to cut it? - + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: Rename Savegame + desc: You can rename your savegame here. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Move selectBuildings: Selectează zona @@ -295,18 +233,9 @@ ingame: clearSelection: Golește Secțiunea pipette: Pipette switchLayers: Switch layers - - # 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: Apasă pentru a cicla variantele. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Tasta: - + hotkeyLabel: "Tasta: " infoTexts: speed: Viteză range: Distanță @@ -314,36 +243,21 @@ ingame: oneItemPerSecond: 1 obiect / second itemsPerSecond: obiecte / s itemsPerSecondDouble: (x2) - tiles: Câmpuri - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Nivelul completed: Completat unlockText: Ai deblocat ! buttonNextLevel: Nivelul următor - - # Notifications on the lower right notifications: newUpgrade: Un upgrade nou este disponibil! gameSaved: Jocul tău a fost salvat. - - # The "Upgrades" window + freeplayLevelComplete: Level has been completed! shop: title: Upgrade-uri buttonUnlock: Upgrade - - # Gets replaced to e.g. "Tier IX" tier: Tier - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: NIVELUL MAXIM (Speed x) - - # The "Statistics" window statistics: title: Statistici dataSources: @@ -352,55 +266,71 @@ ingame: description: Afișează numărul de forme stocate în construcția centrală . produced: title: Produse - description: Afișează toate formele pe care fabrica ta le produce, incluzând produsele intermediate. + description: Afișează toate formele pe care fabrica ta le produce, incluzând + produsele intermediate. delivered: title: Livrate description: Afișează formele care sunt livrate la construcția centrală. noShapesProduced: Nicio formă nu a fost produsă până acum. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Timp jucat - buildingsPlaced: Construcții beltsPlaced: Benzi - - buttons: - continue: Continuă - settings: Setări - menu: Întoarce-te în meniu - - # Bottom left tutorial hints tutorialHints: title: Ai nevoie de ajutor? showHint: Arată o idee hideHint: Închide - - # When placing a blueprint blueprintPlacer: cost: Preț - - # Map markers waypoints: waypoints: Waypointuri hub: Interfață - description: Click-stânga pe un waypoint pentru a merge la el, click-dreapta pentru a îl șterge.

Apasă pentru a crea un waypoint din perspectiva actuală, sau click-dreapta pentru a crea un waypoint. + description: Click-stânga pe un waypoint pentru a merge la el, click-dreapta + pentru a îl șterge.

Apasă pentru a crea un + waypoint din perspectiva actuală, sau click-dreapta + pentru a crea un waypoint. creationSuccessNotification: Waypointul a fost creat. - - # Interactive tutorial interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Plasează un extractor pe o formă de cerc pentru a o extrage! - 1_2_conveyor: >- - Conectează extractorul cu obandă rulantă până la centru!

Sfat: Click și trage banda cu mouse-ul tău! - - 1_3_expand: >- - Acesta NU este un joc idle! Construiește mai multe extractoare și benzi pentru a finaliza scopul mai rapid.

Sfat: Ține apăsat SHIFT pentru a plasa mai multe extractoare, și flosește R pentru a le roti. - + 1_1_extractor: Plasează un extractor pe o formă de + cerc pentru a o extrage! + 1_2_conveyor: "Conectează extractorul cu obandă rulantă până la + centru!

Sfat: Click și trage banda cu + mouse-ul tău!" + 1_3_expand: "Acesta NU este un joc idle! Construiește mai multe + extractoare și benzi pentru a finaliza scopul mai + rapid.

Sfat: Ține apăsat SHIFT pentru a + plasa mai multe extractoare, și flosește R + pentru a le roti." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." colors: red: Roșu green: Verde @@ -415,8 +345,42 @@ ingame: title: Start empty: Gol copyKey: Copy Key - -# All shop upgrades + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limited to + watermark: + title: Demo version + desc: Click here to see the Steam version advantages! + get_on_steam: Get on steam + standaloneAdvantages: + title: Get the full version! + no_thanks: No, thanks! + points: + levels: + title: 12 New Levels + desc: For a total of 26 levels! + buildings: + title: 18 New Buildings + desc: Fully automate your factory! + savegames: + title: ∞ Savegames + desc: As many as your heart desires! + upgrades: + title: 20 Upgrade Tiers + desc: This demo version has only 5! + markers: + title: ∞ Markers + desc: Never get lost in your factory! + wires: + title: Wires + desc: An entirely new dimension! + darkmode: + title: Dark Mode + desc: Stop hurting your eyes! + support: + title: Support me + desc: I develop it in my spare time! shopUpgrades: belt: name: Benzi, Distribuitor & Tunele @@ -430,281 +394,436 @@ shopUpgrades: painting: name: Amestecare & Pictare description: Viteza x → x - -# Buildings and their name / description buildings: belt: default: - name: &belt Benzi Rulante + name: Benzi Rulante description: Transportă obiecte, ține apăsat și trage pentru a plasa mai multe. - - miner: # Internal name for the Extractor + miner: default: - name: &miner Extractor + name: Extractor description: Plasează peste o formă sau culoare pentru a o extrage. - chainable: name: Extractor (lanț) - description: Plasează peste o formă sau culoare pentru a o extrage. Poate fi înlănțuit. - - underground_belt: # Internal name for the Tunnel + description: Plasează peste o formă sau culoare pentru a o extrage. Poate fi + înlănțuit. + underground_belt: default: - name: &underground_belt Tunel + name: Tunel description: Permite transportarea resurselor pe sub construcții și benzi. - tier2: name: Tunnel Tier II description: Permite transportarea resurselor pe sub construcții și benzi. - - splitter: # Internal name for the Balancer - default: - name: &splitter Distribuitor - description: Multifuncțional - Distribuie egal toate input-urile pe toate output-urile. - - compact: - name: Combinator (compact) - description: Combină două benzi rulante în una. - - compact-inverse: - name: Combinator (compact) - description: Combină două benzi rulante în una. - cutter: default: - name: &cutter Tăietor - description: Taie forme de sus în jos și scoate ambele jumătăți. Dacă folosești doar o parte, ține minte să o distrugi pe cealaltă sau producția se va opri! + name: Tăietor + description: Taie forme de sus în jos și scoate ambele jumătăți. Dacă + folosești doar o parte, ține minte să o distrugi pe cealaltă sau + producția se va opri! quad: name: Tăietor (Quad) - description: Taie formele în patru părți. Dacă folosești doar o parte, ține minte să o distrugi pe cealaltă sau producția se va opri! - + description: Taie formele în patru părți. Dacă folosești doar o parte, + ține minte să o distrugi pe cealaltă sau producția se va + opri! rotater: default: - name: &rotater Rotate + name: Rotate description: Rotește formele în sensul acelor de ceasornic la 90 de grade. ccw: name: Rotate (CCW) - description: Rotește formele în inversul sensului acelor de ceasornic la 90 de grade. - + description: Rotește formele în inversul sensului acelor de ceasornic la 90 de + grade. + rotate180: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: - name: &stacker Mașină de presat - description: Unește ambele obiecte. Dacă ele nu poti fi unite, obiectul drept va fi pus peste obiectul stâng. - + name: Mașină de presat + description: Unește ambele obiecte. Dacă ele nu poti fi unite, obiectul drept va + fi pus peste obiectul stâng. mixer: default: - name: &mixer Mixer de culori + name: Mixer de culori description: Amestecă două culori folosind amestecuri aditive. - painter: default: - name: &painter Mașină de pictat - description: &painter_desc Colorează întreaga formă din input-ul stâng folosind culoarea din input-ul drept. + name: Mașină de pictat + description: Colorează întreaga formă din input-ul stâng folosind culoarea din + input-ul drept. double: name: Mașină de pictat (Dublu) - description: Colorează formele din input-urile din stânga folosind culoarea din input-ul de sus. + description: Colorează formele din input-urile din stânga folosind culoarea din + input-ul de sus. quad: name: Mașină de pictat (Quad) - description: Permite colorarea fiecărui cadrant al formei cu o culoare diferită . + description: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! mirrored: - name: *painter - description: *painter_desc - + name: Mașină de pictat + description: Colorează întreaga formă din input-ul stâng folosind culoarea din + input-ul drept. trash: default: - name: &trash Gunoi - description: Acceptă input-uri din toate părțile și le distruge. Pentru totdeauna. - - storage: - name: Depozit - description: Depozitează obiectele in exces, până la o capacitate dată. Poate fi folosit ca un overflow gate. + name: Gunoi + description: Acceptă input-uri din toate părțile și le distruge. Pentru + totdeauna. hub: deliver: Deliver toUnlock: pentru a debloca levelShortcut: LVL + endOfDemo: End of Demo wire: default: name: Energy Wire description: Allows you to transport energy. - advanced_processor: + second: + name: Wire + description: Transfers signals, which can be items, colors or booleans (1 / 0). + Different colored wires do not connect. + balancer: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For - default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Merger (compact) + description: Merges two conveyor belts into one. + merger-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + storage: + default: + name: Storage + description: Stores excess items, up to a given capacity. Prioritizes the left + output and can be used as an overflow gate. + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: Switch + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means + shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. + (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means + shape, color or boolean "1") + transistor: + default: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + mirrored: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: Belt Reader + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: Virtual Cutter + description: Virtually cuts the shape into two halves. + rotater: + name: Virtual Rotater + description: Virtually rotates the shape, both clockwise and counter-clockwise. + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the + remaining ones to the left. + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the shape on + the right input. + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the + wires layer on the regular layer. storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Tăierea formelor - desc: Tocmai ai deblocat tăietorul - taie forme pe jumate de jos în sus indiferent de orientație!

Ține minte să scapi de deșeuri, altfel se va opri - În acest scop ți-am dat un gunoi, care distruge tot ce pui în el! - + desc: You just unlocked the cutter, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! reward_rotater: title: Rotitul - desc: rotater-ul a fost deblocat! El rotește formele la 90 de grade. - + desc: rotater-ul a fost deblocat! El rotește formele la 90 de + grade. reward_painter: title: Pictatul - desc: >- - The Mașina de pictat a fost deblocată - Extrage niște culori (la fel cum faci și cu formele) și combină-le cu o formă în mașina de pictat pentru a le colora!

PS: Dacă ești orb, acolo este un mod pentru orbi în setări! - + desc: "The Mașina de pictat a fost deblocată - Extrage niște + culori (la fel cum faci și cu formele) și combină-le cu o formă în + mașina de pictat pentru a le colora!

PS: Dacă ești orb, acolo + este un mod pentru orbi în setări!" reward_mixer: title: Amestecatul culorilor - desc: Mixerul a fost deblocat - Combină două culori folosind amestecul de aditivi cu această clădire! - + desc: Mixerul a fost deblocat - Combină două culori folosind + amestecul de aditivi cu această clădire! reward_stacker: title: Mașina de presat - desc: Acum poți combina forme cu mașina de presat! Ambele input-uri vor fi combinate, iar dacă ele pot fi puse alături, ele vor fi sudate. Dacă nu, input-ul drept este pus peste input-ul stâng! - + desc: Acum poți combina forme cu mașina de presat! Ambele + input-uri vor fi combinate, iar dacă ele pot fi puse alături, ele + vor fi sudate. Dacă nu, input-ul drept este + pus peste input-ul stâng! reward_splitter: title: Distribuitor/Combinator - desc: Multifuncționalul distribuitor a fost deblocat - El poate fi folosit pentru a construi fabrici mai mari prin distribuirea și combinarea obiectelor pe benzi multiple!

- + desc: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! reward_tunnel: title: Tunel - desc: Tunelul a fost deblocat - Acum poți deplasa obiecte prin benzi și construcții cu el! - + desc: Tunelul a fost deblocat - Acum poți deplasa obiecte prin + benzi și construcții cu el! reward_rotater_ccw: title: Rotarea CCW - desc: Ai deblocat o variantă a rotater-ului - El permite rotația în sensul invers al acelor de ceasornic! Pentru a îț construi, selectează rotater-ul și apasă 'T' pentru a cicla printre variante! - + desc: Ai deblocat o variantă a rotater-ului - El permite + rotația în sensul invers al acelor de ceasornic! Pentru a îț + construi, selectează rotater-ul și apasă 'T' pentru a cicla + printre variante! reward_miner_chainable: title: Chaining Extractor - desc: Ai deblocat Extractorul în lanț! El își poate transmite resursele la alte extractoare ca tu să poți extrage resurse mai eficient! - + desc: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" reward_underground_belt_tier_2: title: Tunnel Tier II - desc: Ai deblocat o variantă nouă a tunelului - El are distanță mai mare, iar tu poți de asemenea să alternezi acele tunele acum! - - reward_splitter_compact: - title: Distribuitor compact - desc: >- - Ai deblocat o variantă compactă a distribuitorului - El acceptă două input-uri și le combină intr-una! - + desc: Ai deblocat o variantă nouă a tunelului - El are + distanță mai mare, iar tu poți de asemenea să + alternezi acele tunele acum! reward_cutter_quad: title: Tăiatul quadriplu - desc: Ai deblocat o variantă a tăietorului - El îți permite să tai forme în patru părți în loc de doar două! - + desc: Ai deblocat o variantă a tăietorului - El îți permite să + tai forme în patru părți în loc de doar două! reward_painter_double: title: Pictatul dublu - desc: Ai deblocat o variantă a Mașini de pictat - Funcționează la fel ca o mașină de pictat normală dar, procesează două forme odată consumând doar o culoare în loc de două! - - reward_painter_quad: - title: Pictatul quadruplu - desc: Ai deblocat o variantă a Mașini de pictat - Ea permite să pictezi fiecare parte a formei individual! - + desc: Ai deblocat o variantă a Mașini de pictat - Funcționează + la fel ca o mașină de pictat normală dar, procesează două + forme odată consumând doar o culoare în loc de două! reward_storage: title: Depozitul - desc: Ai deblocat o variantă a gunoiului - El permite să depoziți obiecte până într-o capacitate dată! - + desc: You have unlocked the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! reward_freeplay: title: Jocul liber - desc: Ai făcut-o! Ai deblocat modul de joc liber! Asta înseamnă că formele sunt acum generate aleatoriu! (Fără griji, mai mult conținut este planificat pentru versiunea standalone!) - + desc: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. reward_blueprints: title: Planuri - desc: Acum poți copia și lipi părți ale fabrici tale! Selectează o zonă (Ține apăsat CTRL, apoi trage cu mouse-ul tău), și apasă 'C' pentru a o copia.

Lipitul nu este gratis, ai nevoie să produci forme de planuri pentru a ți le permite! (Acelea pe care tocmai le-ai livrat). - - # Special reward, which is shown when there is no reward actually + desc: Acum poți copia și lipi părți ale fabrici tale! + Selectează o zonă (Ține apăsat CTRL, apoi trage cu mouse-ul tău), și + apasă 'C' pentru a o copia.

Lipitul nu este + gratis, ai nevoie să produci forme de + planuri pentru a ți le permite! (Acelea pe care tocmai + le-ai livrat). no_reward: title: Nivelul următor - desc: >- - Acest nivel nu ți-a dat nimic dar, următor îți va da!

PS: Mai bine nu îți distruge fabricile construite - Ai nevoie de toate acele forme mai târziu din nou pentru a debloca upgrade-uri! - + desc: "Acest nivel nu ți-a dat nimic dar, următor îți va da!

PS: Mai + bine nu îți distruge fabricile construite - Ai nevoie de + toate acele forme mai târziu din nou pentru a + debloca upgrade-uri!" no_reward_freeplay: title: Nivelul următor - desc: >- - Felicitări! Apropo, mai mult conținut este planificat pentru versiunea standalone! - + desc: Felicitări! Apropo, mai mult conținut este planificat pentru versiunea + standalone! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: End of Demo + desc: You have reached the end of the demo version! settings: title: Setări categories: - game: Joc - app: Aplicație - + general: General + userInterface: User Interface + advanced: Advanced + performance: Performance versionBadges: dev: Dezvoltare staging: Beta prod: Producere buildDate: Construit - labels: uiScale: title: Scala de interfață - description: >- - Schimbă dimensiunea interfeței utilizatorului. Această interfață tot se va scala bazată pe rezoluția dispozitivului dumneavoastră dar, această setare controlează cantitatea scalări. + description: Schimbă dimensiunea interfeței utilizatorului. Această interfață + tot se va scala bazată pe rezoluția dispozitivului dumneavoastră + dar, această setare controlează cantitatea scalări. scales: super_small: Foarte mică small: Mică regular: Normal large: Mare huge: Imens - scrollWheelSensitivity: title: Sensitivitatea Zoom-ului - description: >- - Schimbă cât de sensitiv zoom-ul este (Fie roata mouse-ului ori trackpadlui). + description: Schimbă cât de sensitiv zoom-ul este (Fie roata mouse-ului ori + trackpadlui). sensitivity: super_slow: Foarte încet slow: Încet regular: Regulat fast: Rapid super_fast: Foarte rapid - language: title: Limba - description: >- - Schimbă limba. Toate traducerile sunt contribuite de utilizatori și pot fi incomplete! - + description: Schimbă limba. Toate traducerile sunt contribuite de utilizatori și + pot fi incomplete! fullscreen: title: Fullscreen - description: >- - Este recomandat ca jocul să fie jucat în fullscreen pentru a aveam cea mai bună experiență. Doar disponibil în versiunea standalone. - + description: Este recomandat ca jocul să fie jucat în fullscreen pentru a aveam + cea mai bună experiență. Doar disponibil în versiunea + standalone. soundsMuted: title: Oprește sunetele - description: >- - Dacă este activat, oprește toate efectele sonore. - + description: Dacă este activat, oprește toate efectele sonore. musicMuted: title: Oprește muzica - description: >- - Dacă este activat, oprește toată muzica. - + description: Dacă este activat, oprește toată muzica. theme: title: Tema jocului - description: >- - Alege tema jocului (luminoasă / întunecată). - + description: Alege tema jocului (luminoasă / întunecată). themes: dark: Întunecată light: Luminoasă - refreshRate: title: Simulation Target - description: >- - Dacă ai un monitor cu 144hz, schimbă refresh rate-ul aici și jocul va simula la refresh rate-uri mai mari. Acesta poate de fapt scădea FPS-urile dacă calculatorul dumneavoastră este prea lent. - + description: Dacă ai un monitor cu 144hz, schimbă refresh rate-ul aici și jocul + va simula la refresh rate-uri mai mari. Acesta poate de fapt + scădea FPS-urile dacă calculatorul dumneavoastră este prea lent. alwaysMultiplace: title: Plasare multiplă - description: >- - Dacă este activat, toate construcțiile vor sta selectate până le anulezi. Asta este echivalent cu ținutul SHIFT-ului apăsat permanent. - + description: Dacă este activat, toate construcțiile vor sta selectate până le + anulezi. Asta este echivalent cu ținutul SHIFT-ului apăsat + permanent. offerHints: title: Indicii & Tutoriale - description: >- - Dacă este activat, oferă indicii și tutoriale în timpul jocului. De asemenea ascunde anumite elemente ale interfeței utilizatorului certain UI pâna la anumite nivele pentru a ușura înțelegerea jocului. - + description: Dacă este activat, oferă indicii și tutoriale în timpul jocului. De + asemenea ascunde anumite elemente ale interfeței utilizatorului + certain UI pâna la anumite nivele pentru a ușura înțelegerea + jocului. movementSpeed: title: Viteza de deplasare description: Modifică viteza cât de rapid se mișcă vederea folosind tastatura. @@ -717,18 +836,17 @@ settings: extremely_fast: Extrem de Rapid enableTunnelSmartplace: title: Tunele Inteligente - description: >- - Când este activat, plasarea tunelelor va elimina automat benzile nefolositoare. - Aceasta permite de asemenea tragerea tunelelor și tunelele în exces vor fi șterse. + description: Când este activat, plasarea tunelelor va elimina automat benzile + nefolositoare. Aceasta permite de asemenea tragerea tunelelor și + tunelele în exces vor fi șterse. vignette: title: Vignette - description: >- - Dacă este activat, înnegrește colțurile ecranului și face textul mai ușor de citit. - + description: Dacă este activat, înnegrește colțurile ecranului și face textul + mai ușor de citit. autosaveInterval: title: Intervalul de salvare automată - description: >- - Controlează cât de des jocul se salvează automat. Poți de asemenea să o dezactivezi total aici. + description: Controlează cât de des jocul se salvează automat. Poți de asemenea + să o dezactivezi total aici. intervals: one_minute: 1 Minut two_minutes: 2 Minute @@ -738,28 +856,77 @@ settings: disabled: Dezactivat compactBuildingInfo: title: Informații ale construcțiilor compacte - description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise adescription and image is shown. + description: Shortens info boxes for buildings by only showing their ratios. + Otherwise adescription and image is shown. disableCutDeleteWarnings: title: Dezactivre Avertizări Tăiere/Ștergere - description: >- - Dezactivează avertizările dialogului adus când sunt șterse mai mult de 100 de entități. - + description: Dezactivează avertizările dialogului adus când sunt șterse mai mult + de 100 de entități. enableColorBlindHelper: title: Modul pentru orbi de culoare - description: Activează diferite unelte care îți permit să joci jocul chiar dacă ești orb de culoare. + description: Activează diferite unelte care îți permit să joci jocul chiar dacă + ești orb de culoare. rotationByBuilding: title: Rotație după tipul clădirii - description: >- - Fiecare tip de clădire ține minte ultima rotație pe care i-ai setat-o individual. Aceasta poate fi mai confortabil dacă schimbi frecvent între tipurile clădirilor. - + description: Fiecare tip de clădire ține minte ultima rotație pe care i-ai + setat-o individual. Aceasta poate fi mai confortabil dacă + schimbi frecvent între tipurile clădirilor. + soundVolume: + title: Sound Volume + description: Set the volume for sound effects + musicVolume: + title: Music Volume + description: Set the volume for music + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: Tastele setate - hint: >- - Indiciu: Asigură-te că foloseșto CTRL, SHIFT și ALT! Ele activează diferite opțiuni de plasare. - + hint: "Indiciu: Asigură-te că foloseșto CTRL, SHIFT și ALT! Ele activează + diferite opțiuni de plasare." resetKeybindings: Reset Keyinbindings - categoryLabels: general: Aplicație ingame: Joc @@ -768,7 +935,6 @@ keybindings: massSelect: Selectare în masă buildings: Comenzi rapide pentru clădiri placementModifiers: Modificatori de plasare - mappings: confirm: Confirm back: Înapoi @@ -777,38 +943,30 @@ keybindings: mapMoveDown: Mută în joc mapMoveLeft: Mută în stânga centerMap: Centrează harta - mapZoomIn: Mărește imaginea mapZoomOut: Micșorează imaginea createMarker: Creează waypoint - menuOpenShop: Upgrade-uri menuOpenStats: Statistici - toggleHud: Comută interfața toggleFPSInfo: Comută FPS and Debug Info - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + belt: Benzi Rulante + underground_belt: Tunel + miner: Extractor + cutter: Tăietor + rotater: Rotate + stacker: Mașină de presat + mixer: Mixer de culori + painter: Mașină de pictat + trash: Gunoi rotateWhilePlacing: Rotește - rotateInverseModifier: >- - Modifier: Rotește CCW în schimb + rotateInverseModifier: "Modifier: Rotește CCW în schimb" cycleBuildingVariants: Ciclează Variante confirmMassDelete: Confirmă ștergere în masă cycleBuildings: Ciclează clădiri - massSelectStart: Ține apăsat și trage pentru a începe massSelectSelectMultiple: Selectează zone multiple massSelectCopy: Copiază zona - placementDisableAutoOrientation: Dezactivați orientarea automată placeMultiple: Rămâneți în modul de plasare placeInverse: Inversați orientarea automată a benzii @@ -821,33 +979,38 @@ keybindings: pipette: Pipette menuClose: Close Menu switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator wire: Energy Wire - + balancer: Balancer + storage: Storage + constant_signal: Constant Signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" about: title: Despre acest joc body: >- - Acest joc este open source și dezvoltat de Tobias Springer (acesta sunt eu).

+ Acest joc este open source și dezvoltat de Tobias Springer + (acesta sunt eu).

- Dacă vrei să contribui, verifică shapez.io pe github.

+ Dacă vrei să contribui, verifică shapez.io pe github.

- 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!

+ 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!

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

- - În final, mii de mulțumiri prietenului meu Niklas - Fără sesiunile noastre de - factorio acest joc nu ar fi existat niciodată. + Coloana sonoră a fost făcută de Peppsen - Este uimitor.

+ În final, mii de mulțumiri prietenului meu Niklas - Fără sesiunile noastre de factorio acest joc nu ar fi existat niciodată. changelog: title: Lista de schimbări - demo: features: restoringGames: Restabilirea savegame-urilor @@ -855,5 +1018,65 @@ demo: oneGameLimit: Limitat la un savegame customizeKeybindings: Taste customizabile exportingBase: Exportul întregii baze ca imagine - settingNotAvailable: Nu este valabil în demo. +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-ru.yaml b/translations/base-ru.yaml index 6c716fcb..ffbe04e6 100644 --- a/translations/base-ru.yaml +++ b/translations/base-ru.yaml @@ -1,111 +1,63 @@ -# -# 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 — это игра о строительстве фабрик для автоматизации создания и объединения все более сложных фигур на бесконечной карте. + shortText: shapez.io — это игра о строительстве фабрик для автоматизации + создания и объединения все более сложных фигур на бесконечной карте. + discordLinkShort: Официальный Discord сервер + intro: >- + 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: - # - 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 — это игра о строительстве фабрик для автоматизации создания и объединения все более сложных фигур на бесконечной карте. - Развивайтесь в игре и открывайте улучшения для ускорения фабрики, после доставки запрошенных ресурсов. + Если этого мало, то Вам так же придется экспоненциально производить все больше и больше фигур, чтобы удовлетворить потребности Вашей фабрики. Ключ к успеху - расширение! - По мере увеличения спроса на фигуры вам придется увеличивать свою фабрику, чтобы удовлетворить спрос. Однако, не забывайте о ресурсах, несмотря на то что вы будете расширятся на [b]бесконечной карте[/b]! + Вначале игры Вам понадобится производить только фигуры, однако позже фигуры надо будет окрашивать. Для этого добывайте и смешивайте краски! - Вскоре вам придется смешивать цвета и красить ими фигуры. Комбинируйте красный, зеленый и синий красители для получения разных цветов и красьте ими фигуры, чтобы удовлетворить спрос. - - Эта игра имеет 18 уровней развития (но и они займут вас на часы!), но я постоянно добавляю новый контент - там многое запланировано! - - Покупка игры даст доступ к полной версии, которая имеет дополнительные функции, а также вы получите доступ к недавно разработанным функциям. - - [b]Преимущества полной версии[/b] - - [list] - [*] Темный Режим - [*] Неограниченные Метки - [*] Неограниченные Сохранения - [*] Дополнительные настройки - [*] Скоро: Провода & Энергия! Запланировано (примерно) на конец июля 2020 года. - [*] Скоро: Больше уровней - [*] Позволит мне дальше разрабатывать shapez.io ❤️ - [/list] - - [b]Будущие обновления[/b] - - Я очень часто обновляю игру и пытаюсь обновлять ее как минимум каждую неделю! - - [list] - [*] Различные карты и испытания (например, карты с препятствиями) - [*] Пазлы (Доставить запрошенную фигуру с ограничением пространства / набора зданий) - [*] Режим истории, где здания стоят фигур - [*] Настраиваемый генератор карт (настройка ресурса / размера фигуры / плотности, семя и т.д.) - [*] Дополнительные типы фигур - [*] Улучшения производительности (игра уже работает довольно хорошо!) - [*] И многое другое! - [/list] - - [b]Это игра с открытым исходным кодом![/b] - - Любой может внести свой вклад, я активно участвую в жизни сообщества и пытаюсь рассмотреть все предложения и по возможности принять во внимание отзывы. - Не забудьте проверить мою доску trello со всеми планами! - - [b]Ссылки[/b] - - [list] - [*] [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: Официальный Discord - Общайся со мной! + Приобретение игры в Steam предоставляет доступ к полной версии игры, но вы можете опробовать демоверсию игры на shapez.io и принять решение позже! + title_advantages: Преимущества полной версии + advantages: + - 12 новых уровней - всего 26 уровней! + - 18 новых построек для полностью автоматизированной фабрики! + - 20 стадий улучшения для долгих часов веселья! + - Провода - открывает полноценное новое измерение! + - Темная тема! + - Неограниченные сохранения + - Неограниченные маркеры + - Поддержите меня! ❤️ + title_future: Запланированный контент + planned: + - Библиотека чертежей (только для Полной версии) + - Достижения Steam + - Режим головоломок + - Мини-карта + - Моды + - Режим песочницы + - ... и многое другое! + title_open_source: Эта игра находится в открытом доступе! + title_links: Ссылки + links: + discord: Официальный Discord сервер + roadmap: Планы + subreddit: Subreddit + source_code: Исходный код (GitHub) + translate: Помочь с переводом + text_open_source: >- + Кто угодно может внести свой вклад в разработку игры - я активно + вовлечен в сообщество и стараюсь просмотреть все предложения и по + возможности прислушиваться к отзывам. + Не забудьте заглянуть на мой Trello board, чтобы ознакомиться с планами на будущее! global: loading: Загрузка error: Ошибка - - # 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. + decimalSeparator: . suffix: thousands: k millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: ∞ - time: - # Used for formatting past time dates oneSecondAgo: одну секунду назад xSecondsAgo: секунд(ы) назад oneMinuteAgo: одну минуту назад @@ -114,14 +66,10 @@ global: xHoursAgo: часов(а) назад oneDayAgo: один день назад xDaysAgo: дней(я) назад - - # Short formats for times, e.g. '5h 23m' secondsShort: с minutesAndSecondsShort: м с hoursAndMinutesShort: ч м - xMinutes: мин. - keys: tab: TAB control: CTRL @@ -129,14 +77,9 @@ global: escape: ESC shift: SHIFT space: ПРОБЕЛ - demoBanners: - # This is the "advertisement" shown in the main menu and other various places - title: Демо-версия - intro: >- - Приобретите полную версию, чтобы - разблокировать все возможности! - + title: Демоверсия + intro: Приобретите полную версию, чтобы разблокировать все возможности! mainMenu: play: Играть changelog: Список изменений @@ -144,20 +87,16 @@ mainMenu: openSourceHint: Это игра с открытым исходным кодом! discordLink: Офици- альный Дискорд helpTranslate: Помоги с переводом! - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - Извините, но игра работает медленно в вашем браузере! Приобретите полную версию или загрузите Chrome чтобы ознакомится с игрой в полной мере. - + browserWarning: Извините, но игра работает медленно в вашем браузере! + Приобретите полную версию или загрузите Chrome чтобы ознакомится с игрой + в полной мере. savegameLevel: Уровень savegameLevelUnknown: Неизвестный уровень - - continue: Продолжить newGame: Новая Игра madeBy: Создал subreddit: Reddit - + savegameUnnamed: Без названия dialogs: buttons: ok: OK @@ -171,114 +110,107 @@ dialogs: viewUpdate: Посмотреть Обновление showUpgrades: Показать Улучшения showKeybindings: Показать Управление - importSavegameError: title: Ошибка импортирования - text: >- - Не удалось импортировать сохранение игры. - + text: Не удалось импортировать сохранение игры. importSavegameSuccess: title: Сохранение игры импортировано - text: >- - Сохранение игры успешно импортировано. - + text: Сохранение игры успешно импортировано. gameLoadFailure: title: Ошибка загрузки - text: >- - Не удалось загрузить сохранение игры. - + text: Не удалось загрузить сохранение игры. confirmSavegameDelete: title: Подтвердите удаление. - text: >- - Вы действительно хотите удалить сохранение игры? - + text: Вы уверены, что хотите удалить это сохранение?

'' на + уровне

Это не может быть отменено! savegameDeletionError: title: Ошибка удаления - text: >- - Не удалось удалить сохранение игры. - + text: Не удалось удалить сохранение игры. restartRequired: title: Необходим перезапуск - text: >- - Вам необходимо перезапустить игру, чтобы применить настройки. - + text: Вам необходимо перезапустить игру, чтобы применить настройки. editKeybinding: title: Изменение управления - desc: Нажмите клавишу или кнопку мыши, которую хотите назначить, или нажмите «Esc» для отмены. - + desc: Нажмите клавишу или кнопку мыши, которую хотите назначить, или нажмите + «Esc» для отмены. resetKeybindingsConfirmation: title: Сброс управления - desc: Это сбросит все настройки управления к их значениям по умолчанию. Пожалуйста подтвердите. - + desc: Это сбросит все настройки управления к их значениям по умолчанию. + Подтвердите это действие. keybindingsResetOk: title: Сброс управления desc: Настройки управления сброшены до соответствующих значений по умолчанию! - featureRestriction: - title: Демо-версия - desc: Вы попытались получить доступ к функции (), которая недоступна в демо-версии. Вы можете приобрести полную версию чтобы пользоваться всеми функциями! - + title: Демоверсия + desc: Вы попытались получить доступ к функции (), которая недоступна в + демоверсии. Вы можете приобрести полную версию чтобы пользоваться + всеми функциями! oneSavegameLimit: title: Лимит сохранений - desc: Вы можете иметь только одно сохранение игры в демо-версии. Пожалуйста, удалите существующее или приобретите полную версию! - + desc: Вы можете иметь только одно сохранение игры в демоверсии. Пожалуйста, + удалите существующее или приобретите полную версию! updateSummary: title: Новое обновление! - desc: >- - Здесь изменения с тех пор, когда вы в последний раз играли: - + desc: "Здесь изменения с тех пор, когда вы в последний раз играли:" upgradesIntroduction: title: Улучшения открыты! - desc: >- - Все формы, которые вы производите, могут быть использованы для разблокировки - улучшений - Не разрушайте свои старые фабрики! - Вкладка улучшений находится в правом верхнем углу экрана. + desc: Все формы, которые вы производите, могут быть использованы для + разблокировки улучшений - Не разрушайте свои старые + фабрики! Вкладка улучшений находится в правом верхнем углу + экрана. massDeleteConfirm: title: Подтвердить удаление - desc: >- - Вы удаляете много построек (точнее: )! Вы действительно хотите сделать это? - + desc: "Вы собираетесь удалить много построек (точнее: )! Вы действительно + хотите сделать это?" blueprintsNotUnlocked: title: Еще не открыто - desc: >- - Чертежи еще не открыты! Завершите больше уровней, что-бы открыть их. - + desc: Чертежи еще не открыты! Завершите больше уровней, чтобы открыть их. keybindingsIntroduction: title: Полезные горячие клавиши - desc: >- - В этой игре много горячих клавиш, которые облегчают строительство больших фабрик. - Вот несколько, но обязательно проверьте настройки управления!

- CTRL + Потащить: Выбор области для копирования / удаления.
- SHIFT: Удерживайте, чтобы разместить несколько зданий.
- ALT: Инвертировать направление размещаемых конвейерных лент.
- + desc: "В этой игре много горячих клавиш, которые облегчают строительство больших + фабрик. Вот несколько, но обязательно проверьте настройки + управления!

CTRL + + Потащить: Выбор области для копирования / удаления.
SHIFT: Удерживайте, чтобы разместить + несколько зданий.
ALT: + Инвертировать направление размещаемых конвейерных лент.
" createMarker: title: Новый маркер - desc: Дайте ему содержательное имя, также можно добавить сокращение в виде фигуры (Которое можно сгенерировать здесь) + desc: Дайте ему значимое название, вы также можете добавить короткий + ключ фигуры (Который можно сгенерировать + здесь) titleEdit: Редактирование маркера - markerDemoLimit: - desc: Вы можете создать только 2 своих маркера в демо-версии. Приобретите полную версию для безлимитных маркеров. + desc: Вы можете создать только 2 своих маркера в демоверсии. Приобретите полную + версию для безлимитных маркеров. massCutConfirm: title: Подтвердите вырезку - desc: >- - Вы вырезаете много зданий (точнее: )! Вы уверены, - что хотите это сделать? - + desc: "Вы собираетесь вырезать много зданий (точнее: )! Вы уверены, что + хотите это сделать?" exportScreenshotWarning: title: Экспорт скриншота - desc: >- - Вы запросили экспортировать вашу базу в виде скриншота. Обратите внимание, - что это может быть довольно медленным процессом для большой базы - и даже привести к аварийному завершению игры! - + desc: Вы собираетесь экспортировать вашу базу в виде скриншота. Обратите + внимание, что это может быть довольно медленным процессом для + большой базы и даже привести к аварийному завершению игры! massCutInsufficientConfirm: title: Подтвердите вырезку - desc: Вы не можете позволить себе вставить эту область! Вы уверены, что хотите вырезать ее? - + desc: Вы не можете позволить себе вставить эту область! Вы уверены, что хотите + вырезать ее? + editSignal: + title: Установить Сигнал + descItems: "Выберите объект:" + descShortKey: ... или введите короткий ключ фигуры (Который + можно сгенерировать здесь) + renameSavegame: + title: Переименовать Сохранение + desc: Здесь вы можете изменить название своего сохранения. + tutorialVideoAvailable: + title: Доступно обучение + desc: Для этого уровня доступно видео-обучение! Посмотрите его? + tutorialVideoAvailableForeignLanguage: + title: Доступно обучение + desc: Для этого уровня доступно видео-обучение, но только на английском языке. Посмотрите его? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Передвижение selectBuildings: Выбрать область @@ -286,7 +218,7 @@ ingame: rotateBuilding: Повернуть постройку placeMultiple: Поставить несколько reverseOrientation: Реверсировать направление - disableAutoOrientation: Отключить авто-определение направления + disableAutoOrientation: Отключить автоопределение направления toggleHud: Переключить HUD placeBuilding: Разместить постройку createMarker: Создать маркер @@ -299,18 +231,9 @@ ingame: clearSelection: Отменить pipette: Пипетка switchLayers: Переключить слои - - # 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: Нажмите для переключения вариантов. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Клавиша: - + hotkeyLabel: "Клавиша: " infoTexts: speed: Скорость range: Расстояние @@ -318,36 +241,21 @@ ingame: oneItemPerSecond: 1 пред. / сек. itemsPerSecond: пред. / сек. itemsPerSecondDouble: (x2) - tiles: клеток - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Уровень completed: Завершено unlockText: Открыто ! buttonNextLevel: Следующий уровень - - # Notifications on the lower right notifications: newUpgrade: Новое улучшение доступно! gameSaved: Игра сохранена. - - # The "Upgrades" window + freeplayLevelComplete: Уровень завершён! shop: title: Улучшения buttonUnlock: Улучшить - - # Gets replaced to e.g. "Tier IX" tier: Уровень - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: Скорость x (макс.) - - # The "Statistics" window statistics: title: Статистика dataSources: @@ -356,55 +264,66 @@ ingame: description: Показывает количество хранящихся фигур в хабе. produced: title: Производится - description: Показывает производящиеся фигуры, включая промежуточное производство. + description: Показывает производящиеся фигуры, включая промежуточное + производство. delivered: - title: Доставлено + title: Доставляется description: Показывает фигуры, которые доставляются в хаб. noShapesProduced: Фигуры еще не произведены. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / мин. - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / с + minute: / м + hour: / ч settingsMenu: playtime: Игровое время - buildingsPlaced: Постройки beltsPlaced: Конвейеры - - buttons: - continue: Продолжить - settings: Настройки - menu: Вернуться в меню - - # Bottom left tutorial hints tutorialHints: title: Нужна помощь? showHint: Показать подсказку hideHint: Закрыть - - # When placing a blueprint blueprintPlacer: cost: Стоимость - - # Map markers waypoints: waypoints: Маркеры hub: ХАБ - description: ЛКМ по маркеру, чтобы переместиться к нему, ПКМ что-бы удалить.

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

Нажмите чтобы создать маркер в текущей позиции + или ПКМ, чтобы выбрать другое место для создания + маркера. + creationSuccessNotification: Маркер создан. interactiveTutorial: title: Обучение hints: - 1_1_extractor: Поместите экстрактор на фигуру в форме круга чтобы добыть ее! - 1_2_conveyor: >- - Соедините экстрактор конвейером с хабом!

Подсказка: Необходимо выбрать конвейер и нажать и потащить мышку! - - 1_3_expand: >- - Это НЕ idle-игра! Постройте больше экстракторов и конвейеров, чтобы достичь цели быстрее.

Подсказка: Удерживайте SHIFT чтобы разместить несколько экстракторов, а R чтобы вращать их. - + 1_1_extractor: Поместите экстрактор на фигуру в форме + круга чтобы добыть ее! + 1_2_conveyor: "Соедините экстрактор конвейером с + хабом!

Подсказка: Необходимо выбрать конвейер и + нажать и потащить мышку!" + 1_3_expand: "Это НЕ idle-игра! Постройте больше экстракторов и + конвейеров, чтобы достичь цели быстрее.

Подсказка: + Удерживайте SHIFT чтобы разместить несколько + экстракторов, а R чтобы вращать их." + 2_1_place_cutter: "Разместите Резак для разрезания кругов на две половины! +

PS: Резак всегда разрезает сверху вниз независимо от ориентации." + 2_2_place_trash: Резак может засориться и остановиться!

Используйте + мусорку что бы избавиться от в данный момент (!) ненужных частей. + 2_3_more_cutters: "Хорошая работа! Теперь разместите ещё 2 резака что бы ускорить + этот медленный процесс!

PS: Используйте клавиши 0-9 + для быстрого доступа к постройкам!" + 3_1_rectangles: "Теперь давайте извлечём немного прямоугольников! Постройте 4 + экстрактораи соедините их с хабом.

PS: + Удерживайте SHIFT во время удерживания конвейера для активации планировщика + конвейеров!" + 21_1_place_quad_painter: Разместите покрасчик для 4 предметов и получите + круги, белого и + красного цветов! + 21_2_switch_to_wires: Переключите слой проводов нажатием клавиши + E!

Потом соедините все входы покрасчика кабелями! + 21_3_place_button: Отлично! Теперь разместите Переключатель и присоедини его проводами! + 21_4_press_button: "Нажмите на переключатель что бы заставить его выдавать истинный сигнал + и активировать этим покрасчика.

PS: Не обязательно + соединять все входы! Достаточно двух." colors: red: Красный green: Зеленый @@ -419,8 +338,42 @@ ingame: title: Слои empty: Пусто copyKey: Копировать - -# All shop upgrades + connectedMiners: + one_miner: 1 Экстрактор + n_miners: Экстрактора(-ов) + limited_items: Ограничено до + watermark: + title: Демоверсия + desc: Нажмите сюда, чтобы узнать о преимуществах Steam версии! + get_on_steam: Приобрести в Steam + standaloneAdvantages: + title: Приобретите полную версию! + no_thanks: Нет, спасибо! + points: + levels: + title: 12 Новых Уровней! + desc: Всего 26 уровней! + buildings: + title: 18 новых Построек! + desc: Полностью автоматизируйте свою фабрику! + savegames: + title: ∞ Сохранений + desc: Сколько Вашей душе угодно! + upgrades: + title: 20 стадий улучшений! + desc: В демоверсии всего 5! + markers: + title: ∞ Маркеров! + desc: Никогда не теряйтесь в своей фабрике! + wires: + title: Провода! + desc: Полноценное дополнительное измерение! + darkmode: + title: Темная Тема! + desc: Дайте глазам отдохнуть! + support: + title: Поддержите меня + desc: Я занимаюсь разработкой в свободное время! shopUpgrades: belt: name: Конвейеры, Разделители & Туннели @@ -434,284 +387,440 @@ shopUpgrades: painting: name: Смешивание & Покраска description: Скорость x → x - -# Buildings and their name / description buildings: belt: default: - name: &belt Конвейер - description: Транспортирует предметы, держите и тащите, чтобы разместить несколько. - - miner: # Internal name for the Extractor + name: Конвейер + description: Транспортирует предметы. Держите и тащите, чтобы разместить + несколько. + miner: default: - name: &miner Экстрактор - description: Поместите над жилой с фигурами или красителями, чтобы добыть ресурс. - + name: Экстрактор + description: Поместите над жилой с фигурами или красителями, чтобы добыть + ресурс. chainable: - name: Экстрактор(Цеп.) - description: Поместите над жилой с фигурами или красителями, чтобы добыть ресурс. Может последовательно соединяться в цепь. - - underground_belt: # Internal name for the Tunnel + name: Цеп. экстрактор + description: Поместите над жилой с фигурами или красителями, чтобы добыть + ресурс. Может последовательно соединяться в цепь. + underground_belt: default: - name: &underground_belt Туннель + name: Туннель description: Позволяет перевозить ресурсы под зданиями и конвейерами. - tier2: name: Туннель II description: Позволяет перевозить ресурсы под зданиями и конвейерами. - - splitter: # Internal name for the Balancer - default: - name: &splitter Разделитель - description: Многофункциональный - равномерно распределяет все входы на все выходы. - - compact: - name: Соединитель - description: Компактный - занимает всего одну клетку! Объединяет два конвейера в один. - - compact-inverse: - name: Соединитель - description: Компактный - занимает всего одну клетку! Объединяет два конвейера в один. - cutter: default: - name: &cutter Резчик - description: Разрезает фигуры сверху вниз и выводит обе половины. Используя только одну часть - уничтожьте другую, иначе производство остановится! + name: Резак + description: Разрезает фигуры сверху вниз и выводит обе половины. Если + вы собираетесь использовать только одну часть, уничтожьте + другую, иначе производство остановится! quad: - name: Резчик (4Вых.) - description: Разрезает фигуры на четыре части. Используя не все части - уничтожьте оставшиеся, иначе производство остановится! - + name: Резак (4Вых.) + description: Разрезает фигуры на четыре части. Если вы собираетесь + использовать не все части - уничтожьте оставшиеся, иначе + производство остановится! rotater: default: - name: &rotater Вращатель + name: Вращатель description: Поворачивает фигуры по часовой стрелке на 90 градусов. ccw: name: Вращатель (Обр.) description: Поворачивает фигуры против часовой стрелки на 90 градусов. - + rotate180: + name: Вращатель (180) + description: Поворачивает фигуры на 180 градусов. stacker: default: - name: &stacker Объединитель - description: Объединяет два предмета. Если они не могут быть соединены, правый элемент помещается над левым. - + name: Объединитель + description: Объединяет два предмета. Если они не могут быть соединены, правый + элемент помещается над левым. mixer: default: - name: &mixer Смешиватель + name: Смешиватель description: Аддитивно смешивает цвета двух красителей. - painter: default: - name: &painter Покрасчик - description: &painter_desc Красит всю фигуру из левого входа красителем из перпендикулярного. + name: Покрасчик + description: Красит всю фигуру из левого входа красителем из перпендикулярного. double: name: Покрасчик (2Вх.) description: Красит фигуру из левых входов красителем из перпендикулярного. quad: name: Покрасчик (4Вх.) - description: Позволяет раскрасить каждую четверть фигуры разными цветами. + description: Позволяет отдельно окрашивать каждую часть фигуры. Только ячейки с + положительным сигналом на слое с проводами + будут окрашены! mirrored: - name: *painter - description: *painter_desc - + name: Покрасчик + description: Красит всю фигуру из левого входа красителем из перпендикулярного. trash: default: - name: &trash Мусорка - description: Имеет входы со всех сторон. Уничтожает все что принимает, навсегда. - - storage: - name: Хранилище - description: Хранит лишние предметы, до заданной вместимости. Может использоваться в качестве ворот для пропускания излишков. + name: Мусорка + description: Имеет входы со всех сторон. Уничтожает все принимаемые ресурсы. hub: deliver: Доставить toUnlock: чтобы открыть levelShortcut: Ур. + endOfDemo: Конец Демо wire: default: - name: Энергетический провод + name: Энерг. провод description: Позволяет транспортировать энергию. - advanced_processor: + second: + name: Энерг. провод + description: Передает сигналы, которые могут быть ресурсами, цветами или + логическими значениями (1 / 0). Провода разных цветов не + соединяются. + balancer: default: - name: Инвертор цвета - description: Инвертирует цвета красителей или фигур. - energy_generator: - deliver: Доставить - toGenerateEnergy: Для - default: - name: Генератор энергии - description: Производит энергию потребляя фигуры. - wire_crossings: - default: - name: Разделитель провода - description: Разделяет энергетический провод на два. + name: Балансер + description: Многофункциональный - равномерно распределяет все входы на выходы. merger: - name: Соединитель проводов - description: Соединяет два энергетических провода в один. - + name: Соединитель (компактный) + description: Соединяет две линии ковейера в одну. + merger-inverse: + name: Соединитель (компактный) + description: Соединяет две линии ковейера в одну. + splitter: + name: Разделитель (компактный) + description: Разделяет одну линию конвейера на две. + splitter-inverse: + name: Разделитель (компактный) + description: Разделяет одну линию конвейера на две. + storage: + default: + name: Буферное Хранилище + description: Хранит излишние ресурсы пока есть место. Левый выход в приоритете, + может быть использован как буфер. + wire_tunnel: + default: + name: Пересечение Проводов + description: Позволяет пересекать провода при этом их не соединяя. + constant_signal: + default: + name: Постоянный Сигнал + description: Издает постоянный сигнал, который может быть ресурсом, цветом или + логическим значением (1 / 0). + lever: + default: + name: Переключатель + description: Может быть переключен, чтобы издавать логический сигнал (1 / 0) на + слое с проводами, который может быть использован для управления + Фильтром, например. + logic_gate: + default: + name: AND Gate + description: Издает значение "1" если оба входа положительны. (Положительный - + значит ресурс, цвет или логическое значение "1") + not: + name: NOT Gate + description: Издает значение "1" если вход не положительный. (Положительный - + значит ресурс, цвет или логическое значение "1") + xor: + name: XOR Gate + description: Издает значение "1" только один из входов положительный. + (Положительный - значит ресурс, цвет или логическое значение + "1") + or: + name: OR Gate + description: Издает значение "1" если хотя бы один вход положительный. + (Положительный - значит ресурс, цвет или логическое значение + "1"). + filter: + default: + name: Фильтр + description: Подключите сигнал, чтобы направить все подходящие ресурсы наверх, а + остальные направо. Также контролируемо логическими сигналами. + display: + default: + name: Экран + description: Подключите сигнал, чтобы отобразить его на экране. Это может + ресурс, цвет или логическое значение (1 / 0). + reader: + default: + name: Измеритель + description: Позволяет измерять среднюю пропускную способность конвейера. + Отображает последний прошедший ресурс на слое с проводами (когда + разблокировано). + analyzer: + default: + name: Анализатор Фигур + description: Анализирует правую верхнюю часть низшего слоя фигуры и возвращает + ее форму и цвет. + comparator: + default: + name: Сравнить + description: Возвращает значение "1" если оба сигнала полностью одинаковы. Может + сравнивать фигуры, цвета и логические значения. + virtual_processor: + default: + name: Виртуальный Резак + description: Виртуально разрезает фигуру пополам. + rotater: + name: Виртуальный Вращатель + description: Виртуально вращает фигуру как по часовой стрелке, так и против + часовой стрелки. + unstacker: + name: Виртуальный Разъединитель + description: Виртуально извлекает самый верхний слой фигуры направо, а все + остальное направо. + stacker: + name: Виртуальный Объединитель + description: Виртуально помещает правый предмет поверх левого. + painter: + name: Виртуальный Покрасчик + description: Виртуально окрашивает фигуру из нижнего входа цветом из правого + входа. + item_producer: + default: + name: Генератор Ресурсов + description: Доступен только в режиме песочницы, производит заданный на слое с + проводами сигнал на обычном слое. + transistor: + default: + name: Транзистор + description: Пропускает предметы только если вход сбоку имеет истинноре значение (фигура, + цвет или "1"). + mirrored: + name: Транзистор + description: Пропускает предметы только если вход сбоку имеет истинноре значение (фигура, + цвет или "1"). storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Разрезание Фигур - desc: Вы только что открыли резчик - он разрезает фигуры пополам сверху вниз независимо от их ориентации!

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

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

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

PS: Если вы дальтоник, то в настройках есть + Режим Дальтоника!" reward_mixer: title: Смешивание Цветов - desc: Разблокирован смешиватель! Объедините два цвета в этом здании, используя аддитивное смешивание! - + desc: Разблокирован смешиватель! Объедините два цвета в этом + здании, используя аддитивное смешивание! reward_stacker: title: Объединитель - desc: Теперь вы можете объединять фигуры объединителем! Фигуры из обеих входов объединяются. Если они могут быть расположены рядом друг с другом, они будут соединены, иначе фигура из правого входа наложится на фигуру из левого! - + desc: Теперь вы можете объединять фигуры объединителем! Фигуры + из обеих входов объединяются. Если они могут быть расположены рядом + друг с другом, они будут соединены, иначе фигура из + правого входа наложится на фигуру из левого! reward_splitter: title: Разделитель / Соединитель - desc: Разблокирован многофункциональный разделитель! Его можно использовать для создания больших фабрик путем разделения и соединения конвейеров!

- + desc: Разблокирован разделитель один из вариантов + балансера - он принимает один вход и разделяет его + на два! reward_tunnel: title: Туннель - desc: Разблокирован туннель! Теперь вы можете транспортировать предметы сквозь конвейеры и здания! - + desc: Разблокирован туннель! Теперь вы можете транспортировать + предметы под другими конвейерами и зданиями! reward_rotater_ccw: title: Вращатель (обратный) - desc: Разблокирован вариант вращателя, он позволяет вращать фигуры против часовой стрелки! Чтобы построить его, выберите вращатель и нажмите 'T' чтобы переключаться между вариантами! - + desc: Разблокирован вариант вращателя, вращающий фигуры против + часовой стрелки! Чтобы построить его, выберите вращатель и + нажмите 'T', чтобы переключить вариант! reward_miner_chainable: title: Цепной Экстрактор - desc: Разблокирован цепной экстрактор! Он может передавать свои ресурсы другим экстракторам, чтобы вы могли эффективнее извлекать ресурсы! - + desc: "Разблокирован цепной экстрактор! Он может + передавать свои ресурсы другим экстракторам, чтобы + вы могли эффективнее извлекать ресурсы!

PS: Старый + экстрактор был заменен в панели инструментов!" reward_underground_belt_tier_2: title: Туннель II - desc: Разблокирован новый вариант туннеля с большей дальностью, а также вы можете совмещать эти туннели! - - reward_splitter_compact: - title: Компактный Соединитель - desc: >- - Разблокирован компактный вариант разделителя, он объединяет воедино потоки предметов из двух входов! - + desc: Разблокирован новый вариант туннеля с большей + дальностью, а также вы можете совмещать эти туннели! reward_cutter_quad: - title: Резчик (4 Выхода) - desc: Разблокирован вариант резчика - он позволяет разрезать фигуры на четыре части вместо, всего лишь двух! - + title: Резак (4 Выхода) + desc: Разблокирован вариант резака, разрезающий фигуры на + четыре части вместо двух! reward_painter_double: title: Двойной Покрасчик - desc: Разблокирован вариант покрасчика - он работает как обычный покрасчик, но обрабатывает две фигуры одновременно, потребляя только один краситель вместо двух! - - reward_painter_quad: - title: Покрасчик (4 Входа) - desc: Разблокирован вариант покрасчика - он позволяет отдельно раскрашивать каждую четверть фигуры! - + desc: Разблокирован вариант покрасчика - он работает как + обычный покрасчик, но обрабатывает две фигуры + одновременно, потребляя только один краситель вместо двух! reward_storage: title: Буферное Хранилище - desc: Разблокирован вариант мусорки - он позволяет хранить предметы до заданной вместимости! - + desc: Разблокировано буферное хранилище - оно позволяет хранить + в нем ресурсы пока есть место!

Левый выход в приоритете, + может быть использован как буфер! reward_freeplay: title: Свободная игра - desc: У вас получилось! Разблокирован режим свободной игры! Это означает, что фигуры теперь генерируются случайным образом! (Не беспокойтесь, больше контента планируется в полной версии!) - + desc: У Вас получилось! Разблокирован свободный режим! Это + означает что теперь фигуры будут генерироваться + случайно!

Так как ХАБ отныне будет + требовать определенную пропускную способность, я + настоятельно рекомендую построить механизм, автоматически + доставляющий запрашиваемую фигуру!

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

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

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

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

PS: Лучше не + разрушайте вашу существующую фабрику - Вам понадобятся + все эти фигуры позже, чтобы разблокировать + улучшения!" no_reward_freeplay: title: Следующий уровень - desc: >- - Поздравляем! Кстати, больше контента планируется для полной версии! - + desc: Поздравляем! Кстати, больше контента планируется для полной версии! + reward_balancer: + title: Балансер + desc: Многофункциональный банансер разблокирован - Он используется для разделения и обьединения + потора предметов на несколько конвейеров! + reward_merger: + title: Компактный Соединитель + desc: Разблокирован соединитель - вариант + балансера - он принимает два входа и объединяет их + в один конвейер. + reward_belt_reader: + title: Измеритель + desc: Разблокирован измеритель! Он позволяет измерять + пропускную способность конвейера.

А как полезен он будет, + когда вы разблокируете провода! + reward_rotater_180: + title: Вращатель (180 градусов) + desc: Разблокирован вращатель на 180 градусов! - Он позволяет + вращать фигур на 180 градусов (Сюрприз! :D) + reward_display: + title: Экран + desc: "Разблокирован Экран - Подключите сигнал на слое с + проводами чтобы отобразить его!

PS: Заметили ли вы, что + измеритель и буферное хранилище отображают последний ресурс, + прошедший через них? Попробуйте отобразить его на экране!" + reward_constant_signal: + title: Постоянный Сигнал + desc: Разблокирован постоянный сигнал на слое с проводами! Он + полезен для подключения к фильтрам, + например.

Постоянный сигнал может издавать + фигуру, цвет или + логическое значение (1 / 0). + reward_logic_gates: + title: Логические Элементы + desc: Разблокированы логические элементы! Вы не обязаны + радоваться по этому поводу, но вообще это очень круто!

С + этими элементами теперь вы можете производить И, ИЛИ, исключающее + ИЛИ и НЕ операции.

Как бонус, я также дал вам + транзистор! + reward_virtual_processing: + title: Виртуальное Производство + desc: Только что я открыл вам множество новых построек, которые позволят + симулировать производство фигур!

Теперь вы + можете симулировать резак, вращатель, объединитель и др. на слое с + проводами! Теперь у вас есть три варианта продолжения игры:

+ - Построить автоматический механизм для + производства любой фигуры, запрашиваемой ХАБ (рекомендую + попробовать!).

- Построить что-то клевое, используя + провода.

- Продолжить обычную игру.

Что бы вы не + выбрали, не забывайте хорошо проводить время! + reward_wires_painter_and_levers: + title: Провода & Покрасчик (4 входа) + desc: "Вы разблокировали Слой проводов: Это отдельный + слой выше обычного слоя и он предоставляет много новых + механик!

Для начала я разблокировал тебе Покрасчик на 4 входа + - Соедини слоты которые нужно покрасить на слое проводов!

Для переключения видимости слоя проводов, нажми + E.

PS: Включи подсказки в + настройках что бы активировать обучение по проводам!" + reward_filter: + title: Фильтр + desc: Разблокирован Фильтр! Он направит ресурсы наверх или + направо в зависмости от того, совпадают ли они с установленным + сигналом.

Вы также можете передавать логические значения (1 + / 0), чтобы полностью отключить или включить его. + reward_demo_end: + title: Конец Демо + desc: Вы достигли конца демоверсии игры! settings: title: Настройки categories: - game: Игровые - app: Основные - + general: Основные + userInterface: Интерфейс + advanced: Продвинутые + performance: Performance versionBadges: dev: Разработчик staging: Постановка prod: Произведена buildDate: Сборка - labels: uiScale: title: Размер интерфейса - description: >- - Выберите размер пользовательского интерфейса. Интерфейс будет по-прежнему масштабироваться в зависимости от разрешения вашего устройства, но этот параметр управляет величиной масштабирования. + description: Выберите размер пользовательского интерфейса. Интерфейс будет + по-прежнему масштабироваться в зависимости от разрешения вашего + устройства, но этот параметр управляет величиной + масштабирования. scales: super_small: Очень маленький small: Маленький regular: Средний large: Большой huge: Огромный - scrollWheelSensitivity: title: Чувствительность зума - description: >- - Изменяет чувствительность зума (колесико мыши или сенсорная панель). + description: Изменяет чувствительность зума (колесико мыши или сенсорная + панель). sensitivity: super_slow: Очень медленно slow: Медленно regular: Средне fast: Быстро super_fast: Очень быстро - language: title: Язык - description: >- - Выберите язык. Все переводы сделаны пользователями и могут быть не законченными! - + description: Выберите язык. Все переводы сделаны пользователями и могут быть не + законченными! fullscreen: title: Полный экран - description: >- - Для лучшей игры рекомендуется играть в полноэкранном режиме. Доступно только в полной версии. - + description: Для лучшей игры рекомендуется играть в полноэкранном режиме. + Доступно только в полной версии. soundsMuted: title: Выключить звуки - description: >- - Если включено, выключает все звуковые эффекты. - + description: Если включено, выключает все звуковые эффекты. musicMuted: title: Выключить музыку - description: >- - Если включено, выключает музыку. - + description: Если включено, выключает музыку. theme: title: Тема игры - description: >- - Выберите тему игры (светлая / темная). - + description: Выберите тему игры (светлая / темная). themes: dark: Темная light: Светлая - refreshRate: title: Частота обновления - description: >- - Если у вас монитор 144 Гц, измените частоту обновления здесь, чтобы игра правильно выглядела при более высоких частотах обновления. Это может уменьшить FPS, если ваш компьютер работает слишком медленно. - + description: Если у вас монитор 144 Гц, измените частоту обновления здесь, чтобы + игра правильно выглядела при более высоких частотах обновления. + Это может уменьшить FPS, если ваш компьютер работает слишком + медленно. alwaysMultiplace: title: Многократное размещение - description: >- - Если включено, все здания останутся выбранными после размещения, пока вы не отмените выбор. Это эквивалентно постоянному удержанию SHIFT. - + description: Если включено, все здания останутся выбранными после размещения, + пока вы не отмените выбор. Это эквивалентно постоянному + удержанию SHIFT. offerHints: title: Подсказки & Обучение - description: >- - Стоит ли предлагать подсказки и обучающий материал во время игры. Также скрывает определенные элементы пользовательского интерфейса для данного уровня, предназначенные для облегчения "входа" в игру. - + description: Стоит ли предлагать подсказки и обучающий материал во время игры. + Также скрывает определенные элементы пользовательского + интерфейса для данного уровня, предназначенные для облегчения + "входа" в игру. movementSpeed: title: Скорость движения - description: Изменяет скорость перемещения изображения при использовании клавиатуры. + description: Изменяет скорость перемещения изображения при использовании + клавиатуры. speeds: super_slow: Очень медленно slow: Медленно @@ -721,19 +830,17 @@ settings: extremely_fast: Чрезвычайно быстро enableTunnelSmartplace: title: Умные Туннели - description: >- - Если включено, то при размещении туннелей автоматически удаляются ненужные конвейеры. - Это также позволяет протягивать туннели, причем лишние туннели будут удалены. + description: Если включено, то при размещении туннелей автоматически удаляются + ненужные конвейеры. Это также позволяет протягивать туннели, + причем лишние туннели будут удалены. vignette: title: Виньетирование - description: >- - Включает виньетирование, которое затемняет углы экрана и облегчает чтение текста. - + description: Включает виньетирование, которое затемняет углы экрана и облегчает + чтение текста. autosaveInterval: - title: Интервал авто-сохранения - description: >- - Управляет тем, как часто игра автоматически сохраняется. - А также здесь можно полностью отключить авто-сохранение. + title: Интервал автосохранения + description: Управляет тем, как часто игра автоматически сохраняется. Также + здесь можно полностью отключить автосохранение. intervals: one_minute: 1 Минута two_minutes: 2 Минуты @@ -743,32 +850,76 @@ settings: disabled: Отключено compactBuildingInfo: title: Компактная Информация о Зданиях - description: >- - Сокращает отображаемую информацию о зданиях, показывая только их множители. - Иначе информация отображается с описанием и изображением. + description: Сокращает отображаемую информацию о зданиях, показывая только их + множители. Иначе информация отображается с описанием и + изображением. disableCutDeleteWarnings: - title: Отключить Предупреждение о Вырезании\Удалении - description: >- - Отключает диалоговые окна с предупреждениями, появляющиеся при + title: Отключить Предупреждение о Вырезании/Удалении + description: Отключает диалоговые окна с предупреждениями, появляющиеся при вырезании/удалении более 100 объектов. - enableColorBlindHelper: title: Режим Дальтоника - description: Включает различные инструменты, которые позволяют играть в игру дальтоникам. + description: Включает различные инструменты, которые позволяют играть в игру + дальтоникам. rotationByBuilding: title: Поворот по типу здания - description: >- - Каждый тип здания запоминает поворот, который в последний раз был установлен. - С этой настройкой может быть удобнее, при частом переключении между - различными типами зданий. - + description: Каждый тип здания запоминает поворот, который в последний раз был + установлен. С этой настройкой может быть удобнее, при частом + переключении между различными типами зданий. + soundVolume: + title: Громкость Звука + description: Задает громкость звуковых эффектов. + musicVolume: + title: Music Volume + description: Задает громкость музыки. + lowQualityMapResources: + title: Низкое качество ресурсов на карте + description: Упрощает отображение ресурсов на карте при приближении для + улучшения производительности. Оно даже выглядит аккуратнее, + поэтому обязательно попробуйте! + disableTileGrid: + title: Отключить Сетку + description: Отключение разделительной сетки может помочь улучшить + производительность. Кроме того, делает игру визуально проще! + clearCursorOnDeleteWhilePlacing: + title: Очистить Курсор на ПКМ + description: Включено по умолчанию, очищает курсор от выбранной постройки при + нажатии на ПКМ. Если отключено, вы можете удалять постройки при + нажатии на ПКМ во время строительства. + lowQualityTextures: + title: Низкое качество текстур (Некрасиво) + description: Использует низкое качество текстур, чтобы улучшить + производительность. Это сделает игру очень некрасивой! + displayChunkBorders: + title: Отображать границы чанков + description: Эта игра разделена на чанки, состоящие из 16x16 ячеек, если эта + настройка включена, границы чанков будут отображаться. + pickMinerOnPatch: + title: Выбрать Экстрактор над Жилой + description: Включено по умолчанию, выбирает экстрактор, если использовать + пипетку над жилой с ресурсами. + simplifiedBelts: + title: Упрощенные Конвейеры (Некрасиво) + description: Не отображает ресурсы, находящиеся на конвейере, если не навести + курсор для улучшения производительности. Не рекомендую играть с + этой настройкой, если вас устраивает производительность. + enableMousePan: + title: Включить Перемещение Мышкой + description: Позволяет двигать карту, перемещая курсор к краям экрана. Скорость + зависит от настройки Скорости движения. + zoomToCursor: + title: Приближение в точку курсора + description: Если включено, приближение будет в направлении курсора мыши, + иначе в центр экрана. + mapResourcesScale: + title: Размер ресурсов на карте + description: Устанавливает размер фигур на карте (когда вид достаточно отдалён). + rangeSliderPercentage: % keybindings: title: Настройки управления - hint: >- - Подсказка: Обязательно используйте CTRL, SHIFT и ALT! Они дают разные варианты размещения. - + hint: "Подсказка: Обязательно используйте CTRL, SHIFT и ALT! Они дают разные + варианты размещения." resetKeybindings: Сброс настроек управления - categoryLabels: general: Основные ingame: Игровые @@ -777,7 +928,6 @@ keybindings: massSelect: Множественный Выбор buildings: Постройки placementModifiers: Модификаторы Размещения - mappings: confirm: Подтвердить back: Назад @@ -786,41 +936,33 @@ keybindings: mapMoveDown: Вниз mapMoveLeft: Влево centerMap: Центрировать карту - mapZoomIn: Приблизить mapZoomOut: Отдалить createMarker: Создать Маркер - menuOpenShop: Улучшения menuOpenStats: Статистика - toggleHud: Переключить HUD toggleFPSInfo: Включить/выключить FPS и информацию отладки - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + belt: Конвейер + underground_belt: Туннель + miner: Экстрактор + cutter: Резак + rotater: Вращатель + stacker: Объединитель + mixer: Смешиватель + painter: Покрасчик + trash: Мусорка rotateWhilePlacing: Вращать - rotateInverseModifier: >- - Модификатор: Вращать против часовой стрелки + rotateInverseModifier: "Модификатор: Вращать против часовой стрелки" cycleBuildingVariants: Переключение Вариантов confirmMassDelete: Подтверждение Массового Удаления cycleBuildings: Переключение Построек - massSelectStart: Модификатор для выделения области massSelectSelectMultiple: Выбрать несколько областей massSelectCopy: Копировать область - - placementDisableAutoOrientation: Отключить авто-определение направления + placementDisableAutoOrientation: Отключить автоопределение направления placeMultiple: Оставаться в режиме размещения - placeInverse: Инвертировать авто-определение направления конвейеров + placeInverse: Инвертировать автоопределение направления конвейеров pasteLastBlueprint: Вставить последний чертеж massSelectCut: Вырезать область exportScreenshot: Экспорт всей Базы в виде Изображения @@ -830,33 +972,38 @@ keybindings: pipette: Пипетка menuClose: Закрыть меню switchLayers: Переключить слои - advanced_processor: Инвертор цвета - energy_generator: Генератор энергии wire: Энергетический провод - + balancer: Балансер + storage: Буферное Хранилище + constant_signal: Постоянный Сигнал + logic_gate: Логический Элемент + lever: Переключатель (обычный) + filter: Фильтр + wire_tunnel: Пересечение Проводов + display: Экран + reader: Измеритель + virtual_processor: Виртуальный Резак + transistor: Транзистор + analyzer: Анализатор Фигур + comparator: Сравнить + item_producer: Генератор Ресурсов (Песочница) + copyWireValue: "Провода: скопировать значение под курсором" about: title: Об игре body: >- - Эта игра с открытым исходным кодом, разработана Тобиасом Спрингером (это я).

+ Эта игра с открытым исходным кодом, разработана Тобиасом Спрингером + (это я).

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

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

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

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

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

- - Наконец, огромное спасибо моему лучшему другу Niklas - Без наших - игровых сессий в factorio эта игра никогда не существовала бы. + Саундтрек сделал Peppsen - Он потрясающий.

+ Наконец, огромное спасибо моему лучшему другу Niklas - Без наших игровых сессий в Factorio эта игра никогда не существовала бы. changelog: title: Список изменений - demo: features: restoringGames: Восстановить сохранения игр @@ -864,5 +1011,67 @@ demo: oneGameLimit: Ограниченность одним сохранением игры customizeKeybindings: Пользовательская настройка Управления exportingBase: Экспорт всей Базы в виде Изображения - - settingNotAvailable: Не доступно в демо-версии. + settingNotAvailable: Недоступно в демоверсии. +tips: + - ХАБ принимает любые ресурсы, не только текущую фигуру! + - Старайтесь создавать модульные фабрики - вы не пожалеете! + - Не стройте слишком близко к ХАБ-у, иначе начнется ужасный хаос! + - Если не получается объединить фигуры, попробуйте поменять входы местами! + - Вы можете изменить направление конвейера при строительстве, нажав R. + - Удерживая CTRL, вы можете перемещать конвейеры без авто ориентации. + - Соотношения всегда одинаковы, если уровни улучшений равны. + - Последовательное выполнение эффективнее, чем параллельное. + - Вам будут открываться новые варианты построек по мере прохождения! + - Нажмите T, чтобы переключаться между различными вариантами. + - Симметрия - ключ к успеху! + - Вы можете переплетать между собой туннели разных уровней. + - Попробуйте строить компактные фабрики - вы не пожалеете! + - Покрасчик имеет зеркальный вариант, который может быть выбран, нажав + T. + - Правильные соотношения построек позволяет улучшить эффективность фабрики. + - На максимальном уровне, 5 экстракторов заполняют один конвейер. + - Резаки всегда разрезают пополам по вертикали вне зависимости от ориентации. + - Чтобы получить белый цвет, смешайте все три цвета. + - Удерживание SHIFT активирует планировщик конвейеров, что упрощает простройку длинных конвейеров. + - Вкладывайте время в строительство повторяемых механизмов - оно того стоит! + - Смешайте все три цвета для получения булого. + - Буффер хранилища с большим приоритетом выдаёт на левый выход. + - Эффективность - ключ к успеху! + - Удерживание CTRL даёт возможность размещения нескольких построек. + - Можно зажать ALT для инвертирования направления размещаемых конвейеров. + - Используйте балансеры, чтобы максимизировать эффективность. + - Организация очень важна, старайтесь не пересекать конвейеры слишком часто. + - Планируйте заранее, иначе начнется ужасный хаос! + - Не удаляйте свои старые фабрики! Они понадобятся вам, чтобы открывать + улучшения. + - Попробуйте пройти 20-ый уровень самостоятельно, прежде чем искать помощи! + - Не усложняйте себе жизнь, старайтесь думать проще и вы достигните больших + высот. + - Вам может снова понадобиться ваша старая фабрика позже в игре. Старайтесь + планировать фабрику, чтобы она могла быть повторно использована. + - Иногда, вы можете найти необходимую фигуру на карте, вместо того, чтобы + создавать ее самостоятельно. + - Полноценные мельницы/вертушки никогда не генерируются натурально. + - Окрашивайте свои фигуры, прежде чем разрезать для максимальной + эффективности. + - С модулями теряется восприятие пространства; забота смертных. + - Создайте отдельную фабрику чертежей. Они очень важны для модулей. + - Взгляните внимательнее на смешиватель и вы найдете ответы на свои вопросы. + - With modules, space is merely a perception; a concern for mortal men. + - Строительство вблизи ХАБ-а может помешать будущим проектам. + - Иконка булавки на каждой фигуре закрепляет ее на экране. + - Используйте CTRL + ЛКМ для выбора области. + - В вашем распоряжении бесконечная карта! Не загромождайте вашу фабрику, + расширяйтесь! + - Также попробуйте Factorio. Это моя любимая игра. + - Резак(4 входа) разрезает по часовой стрелке, начиная с правой верхней + части! + - Вы можете скачать свои сохранения в главном меню! + - В этой игре множество полезных комбинаций клавиш. Загляните в настройки, + чтобы ознакомиться с ними. + - В этой игре множество настроек, не забудьте с ними ознакомиться. + - Маркер ХАБ-а имеет небольшой компас, указывающий его направление. + - Нажмите F4, чтобы показать FPS и Частоту Обновления. + - Нажмите F4 дважды, чтобы показать координаты курсора и камеры. + - Вы можете нажать на закрепленную фигуру слева, чтобы открепить ее. + - Для очистки конвейеров, вырежьте область и вставьте её в то же место. diff --git a/translations/base-sl.yaml b/translations/base-sl.yaml index ce2a0ae4..516aa9de 100644 --- a/translations/base-sl.yaml +++ b/translations/base-sl.yaml @@ -1,111 +1,64 @@ -# -# 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 je igra grajenja tovarne katere cilj je avtomatiziranje kreiranja in procesiranja vse bolj zapletenih oblik na neskončni ravnini. + shortText: shapez.io je igra grajenja tovarne katere cilj je avtomatiziranje + kreiranja in procesiranja vse bolj zapletenih oblik na neskončni + ravnini. + discordLinkShort: Official Discord + intro: >- + Shapez.io is a relaxed game in which you have to build factories for the + automated production of geometric shapes. - # This is the text shown above the discord link - discordLink: Uradni Discord - Pridruži se klepetu! + As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map. - # 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] + And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! - 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. + While you only process shapes at the beginning, you have to color them later - for this you have to extract and mix colors! - 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]! - - 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. - - 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] - [*] 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] - - Igro posodabljam zelo pogosto in poskušam dodati novosti vsaj vsak teden! - - [list] - [*] 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] - - 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]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]Izvorna Koda (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Pomagaj pri prevodu[/url] - [/list] + Buying the game on Steam gives you access to the full version, but you can also play a demo on shapez.io first and decide later! + title_advantages: Standalone Advantages + advantages: + - 12 New Level for a total of 26 levels + - 18 New Buildings for a fully automated factory! + - 20 Upgrade Tiers for many hours of fun! + - Wires Update for an entirely new dimension! + - Dark Mode! + - Unlimited Savegames + - Unlimited Markers + - Support me! ❤️ + title_future: Planned Content + planned: + - Blueprint Library (Standalone Exclusive) + - Steam Achievements + - Puzzle Mode + - Minimap + - Mods + - Sandbox mode + - ... and a lot more! + title_open_source: This game is open source! + title_links: Links + links: + discord: Official Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Help translate + text_open_source: >- + 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! global: loading: Loading error: Error - - # 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. + decimalSeparator: . suffix: thousands: k millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: inf - time: - # Used for formatting past time dates oneSecondAgo: one second ago xSecondsAgo: seconds ago oneMinuteAgo: one minute ago @@ -114,14 +67,10 @@ global: xHoursAgo: hours ago oneDayAgo: one day ago xDaysAgo: days ago - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s hoursAndMinutesShort: h m - xMinutes: minutes - keys: tab: TAB control: CTRL @@ -129,13 +78,9 @@ global: escape: ESC shift: SHIFT space: SPACE - 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! - + intro: Get the standalone to unlock all features! mainMenu: play: Play continue: Continue @@ -147,14 +92,11 @@ mainMenu: discordLink: Official Discord Server helpTranslate: Help translate! madeBy: Made by - - # 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. - + 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 - + savegameUnnamed: Unnamed dialogs: buttons: ok: OK @@ -168,112 +110,104 @@ dialogs: viewUpdate: View Update showUpgrades: Show Upgrades showKeybindings: Show Keybindings - importSavegameError: title: Import Error - text: >- - Failed to import your savegame: - + text: "Failed to import your savegame:" importSavegameSuccess: title: Savegame Imported - text: >- - Your savegame has been successfully imported. - + text: Your savegame has been successfully imported. gameLoadFailure: title: Game is broken - text: >- - Failed to load your savegame: - + text: "Failed to load your savegame:" confirmSavegameDelete: title: Confirm deletion - text: >- - Are you sure you want to delete the game? - + text: Are you sure you want to delete the following game?

+ '' at level

This can not be + undone! savegameDeletionError: title: Failed to delete - text: >- - Failed to delete the savegame: - + text: "Failed to delete the savegame:" restartRequired: title: Restart required - text: >- - You need to restart the game to apply the settings. - + 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. - resetKeybindingsConfirmation: title: Reset keybindings desc: This will reset all keybindings to their default values. Please confirm. - keybindingsResetOk: title: Keybindings reset desc: The keybindings have been reset to their respective defaults! - 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! - + 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 version! - + 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! - desc: >- - Here are the changes since you last played: - + desc: "Here are the changes since you last played:" upgradesIntroduction: title: Unlock Upgrades - 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. - + 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 - desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? - + 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? - + 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? - + desc: You can not afford to paste this area! Are you sure you want to cut it? blueprintsNotUnlocked: title: Not unlocked yet - desc: >- - Complete level 12 to unlock Blueprints! - + desc: Complete level 12 to unlock Blueprints! keybindingsIntroduction: title: Useful 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.
- + 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.
" 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) + 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: You can only create two custom markers in the demo. Get the standalone for unlimited markers! - + desc: You can only create two custom markers in the demo. Get the standalone for + unlimited markers! 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! - + 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! + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: Rename Savegame + desc: You can rename your savegame here. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Move selectBuildings: Select area @@ -294,8 +228,6 @@ ingame: clearSelection: Clear selection pipette: Pipette switchLayers: Switch layers - - # Names of the colors, used for the color blind mode colors: red: Red green: Green @@ -306,18 +238,9 @@ ingame: white: White black: Black uncolored: No color - - # 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. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - + hotkeyLabel: "Hotkey: " infoTexts: speed: Speed range: Range @@ -325,36 +248,21 @@ ingame: oneItemPerSecond: 1 item / second itemsPerSecond: items / s itemsPerSecondDouble: (x2) - 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 - - # Notifications on the lower right notifications: newUpgrade: A new upgrade is available! gameSaved: Your game has been saved. - - # The "Upgrades" window + freeplayLevelComplete: Level has been completed! shop: title: Upgrades buttonUnlock: Upgrade - - # Gets replaced to e.g. "Tier IX" tier: Tier - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXIMUM LEVEL (Speed x) - - # The "Statistics" window statistics: title: Statistics dataSources: @@ -363,62 +271,110 @@ ingame: description: Displaying amount of stored shapes in your central building. produced: title: Produced - description: Displaying all shapes your whole factory produces, including intermediate products. + description: Displaying all shapes your whole factory produces, including + intermediate products. delivered: title: Delivered 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 - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Playtime - buildingsPlaced: Buildings beltsPlaced: Belts - - buttons: - continue: Continue - settings: Settings - menu: Return to menu - - # Bottom left tutorial hints tutorialHints: title: Need help? showHint: Show hint hideHint: Close - - # When placing a blueprint blueprintPlacer: 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. + 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 hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! - 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. - -# All shop upgrades + 1_1_extractor: Place an extractor on top of a circle + shape to extract it! + 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." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limited to + watermark: + title: Demo version + desc: Click here to see the Steam version advantages! + get_on_steam: Get on steam + standaloneAdvantages: + title: Get the full version! + no_thanks: No, thanks! + points: + levels: + title: 12 New Levels + desc: For a total of 26 levels! + buildings: + title: 18 New Buildings + desc: Fully automate your factory! + savegames: + title: ∞ Savegames + desc: As many as your heart desires! + upgrades: + title: 20 Upgrade Tiers + desc: This demo version has only 5! + markers: + title: ∞ Markers + desc: Never get lost in your factory! + wires: + title: Wires + desc: An entirely new dimension! + darkmode: + title: Dark Mode + desc: Stop hurting your eyes! + support: + title: Support me + desc: I develop it in my spare time! shopUpgrades: belt: name: Belts, Distributor & Tunnels @@ -432,240 +388,386 @@ shopUpgrades: painting: name: Mixing & Painting description: Speed x → x - -# Buildings and their name / description buildings: hub: deliver: Deliver toUnlock: to unlock levelShortcut: LVL - + endOfDemo: End of Demo belt: default: - name: &belt Conveyor Belt + name: Conveyor Belt description: Transports items, hold and drag to place multiple. - wire: default: - name: &wire Wire + name: Wire description: Allows you to transport energy - - miner: # Internal name for the Extractor + second: + name: Wire + description: Transfers signals, which can be items, colors or booleans (1 / 0). + Different colored wires do not connect. + miner: default: - name: &miner Extractor + name: 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 + underground_belt: default: - name: &underground_belt Tunnel + name: Tunnel description: Allows you to tunnel resources under buildings and belts. - tier2: name: Tunnel Tier II description: Allows you 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 halves. If you use only one part, be sure to destroy the other part or it will stall! + name: 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! 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 Advanced Processor - description: Advanced shape processing - + description: Cuts shapes into four parts. If you use only one part, be + sure to destroy the other parts or it will stall! rotater: default: - name: &rotater Rotate + name: Rotate description: Rotates shapes clockwise by 90 degrees. ccw: name: Rotate (CCW) description: Rotates shapes counter-clockwise by 90 degrees. - + rotate180: + name: Rotate (180) + description: Rotates shapes by 180 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. - + name: 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 + name: 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 top input. - + name: Painter + description: Colors the whole shape on the left input with the color from the + top input. mirrored: - name: *painter - description: *painter_desc - + name: Painter + description: Colors the whole shape on the left input with the color from the + top input. double: name: Painter (Double) - description: Colors the shapes on the left inputs with the color from the top input. + 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. - + description: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! trash: default: - name: &trash Trash + name: 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. - - energy_generator: - deliver: Deliver - - # This will be shown before the amount, so for example 'For 123 Energy' - toGenerateEnergy: For - + balancer: default: - 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. + name: Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Merger (compact) + description: Merges two conveyor belts into one. + merger-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + storage: + default: + name: Storage + description: Stores excess items, up to a given capacity. Prioritizes the left + output and can be used as an overflow gate. + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: Switch + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means + shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. + (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means + shape, color or boolean "1") + transistor: + default: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + mirrored: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: Belt Reader + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: Virtual Cutter + description: Virtually cuts the shape into two halves. + rotater: + name: Virtual Rotater + description: Virtually rotates the shape, both clockwise and counter-clockwise. + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the + remaining ones to the left. + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the shape on + the right input. + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the + wires layer on the regular layer. 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, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! reward_rotater: title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. - + desc: The rotater has been unlocked! It rotates shapes + clockwise by 90 degrees. 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 colorblind mode in the settings! - + 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! - + desc: The mixer has been unlocked - Combine two colors using + additive blending with this building! 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! - + 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! 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!

- + desc: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! reward_tunnel: title: Tunnel - desc: The tunnel has been unlocked - You can now tunnel items through belts and buildings with it! - + desc: The tunnel has been unlocked - You can now tunnel items + through belts and buildings with it! 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! - + 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 - desc: You have unlocked the chaining extractor! It can forward its resources to other extractors so you can more efficiently extract resources! - + desc: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" 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! - - 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 belt! - + 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! 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! - + desc: You have unlocked a variant of the cutter - It allows you + to cut shapes in four parts instead of just two! 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! - - 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: 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! 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: You have unlocked the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! 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!) - + desc: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. 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). - - # Special reward, which is shown when there is no reward actually + 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). 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! - + 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: >- - Congratulations! By the way, more content is planned for the standalone! - + desc: Congratulations! By the way, more content is planned for the standalone! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: End of Demo + desc: You have reached the end of the demo version! settings: title: Settings categories: - game: Game - app: Application - + general: General + userInterface: User Interface + advanced: Advanced + performance: Performance versionBadges: dev: Development staging: Staging prod: Production buildDate: Built - labels: uiScale: title: Interface scale - 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. + 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 - autosaveInterval: title: Autosave Interval - description: >- - Controls how often the game saves automatically. You can also disable it entirely here. - + description: Controls how often the game saves automatically. You can also + disable it entirely here. intervals: one_minute: 1 Minute two_minutes: 2 Minutes @@ -673,22 +775,18 @@ settings: ten_minutes: 10 Minutes twenty_minutes: 20 Minutes disabled: Disabled - scrollWheelSensitivity: title: Zoom sensitivity - description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + 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 - movementSpeed: title: Movement speed - description: >- - Changes how fast the view moves when using the keyboard. + description: Changes how fast the view moves when using the keyboard. speeds: super_slow: Super slow slow: Slow @@ -696,87 +794,122 @@ settings: 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! - + description: 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. - + description: Enables various tools which allow you to play the game if you are + color blind. fullscreen: title: Fullscreen - description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. - + description: It is recommended to play the game in fullscreen to get the best + experience. Only available in the standalone. soundsMuted: title: Mute Sounds - description: >- - If enabled, mutes all sound effects. - + description: If enabled, mutes all sound effects. musicMuted: title: Mute Music - description: >- - If enabled, mutes all music. - + description: If enabled, mutes all music. theme: title: Game theme - description: >- - Choose the game theme (light / dark). + description: Choose the game theme (light / dark). themes: dark: Dark light: Light - refreshRate: title: Simulation Target - 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. - + 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: Multiplace - description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. - + description: If enabled, all buildings will stay selected after placement until + you cancel it. This is equivalent to holding SHIFT permanently. offerHints: title: Hints & Tutorials - 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. - + 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 - description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. This also enables you to drag tunnels and excess tunnels will get removed. - + 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 - description: >- - Enables the vignette, which darkens the screen corners and makes text easier to read. - + description: Enables the vignette, which darkens the screen corners and makes + text easier to read. 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. - + 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 - description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. - + description: Shortens info boxes for buildings by only showing their ratios. + Otherwise a description and image is shown. disableCutDeleteWarnings: title: Disable Cut/Delete Warnings - description: >- - Disables the warning dialogs brought up when cutting/deleting more than 100 entities. - + description: Disables the warning dialogs brought up when cutting/deleting more + than 100 entities. + soundVolume: + title: Sound Volume + description: Set the volume for sound effects + musicVolume: + title: Music Volume + description: Set the volume for music + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: Keybindings - hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - + hint: "Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different + placement options." resetKeybindings: Reset Keybindings - categoryLabels: general: Application ingame: Game @@ -785,7 +918,6 @@ keybindings: massSelect: Mass Select buildings: Building Shortcuts placementModifiers: Placement Modifiers - mappings: confirm: Confirm back: Back @@ -795,70 +927,73 @@ keybindings: mapMoveLeft: Move Left mapMoveFaster: Move Faster centerMap: Center Map - mapZoomIn: Zoom in mapZoomOut: Zoom out createMarker: Create Marker - 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 - + belt: Conveyor Belt + underground_belt: Tunnel + miner: Extractor + cutter: Cutter + rotater: Rotate + stacker: Stacker + mixer: Color Mixer + painter: Painter + trash: Trash + wire: Wire pipette: Pipette rotateWhilePlacing: Rotate - rotateInverseModifier: >- - Modifier: Rotate CCW instead + rotateInverseModifier: "Modifier: Rotate CCW instead" cycleBuildingVariants: Cycle Variants confirmMassDelete: Delete area pasteLastBlueprint: Paste last blueprint cycleBuildings: Cycle Buildings lockBeltDirection: Enable belt planner - switchDirectionLockSide: >- - Planner: Switch side - + 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 - + balancer: Balancer + storage: Storage + constant_signal: Constant Signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" 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.

- 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. - changelog: title: Changelog - demo: features: restoringGames: Restoring savegames @@ -866,5 +1001,65 @@ demo: oneGameLimit: Limited to one savegame customizeKeybindings: Customizing Keybindings exportingBase: Exporting whole Base as Image - settingNotAvailable: Not available in the demo. +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-sr.yaml b/translations/base-sr.yaml new file mode 100644 index 00000000..3a9d72ea --- /dev/null +++ b/translations/base-sr.yaml @@ -0,0 +1,1063 @@ +steamPage: + shortText: shapez.io je igra o pravljenju fabrika za automatizaciju stvaranja i + spajanja sve složenijih oblika na beskonačno velikoj mapi. + discordLinkShort: Official Discord + intro: >- + Shapez.io is a relaxed game in which you have to build factories for the + automated production of geometric shapes. + + As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map. + + And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! + + While you only process shapes at the beginning, you have to color them later - for this you have to extract and mix colors! + + Buying the game on Steam gives you access to the full version, but you can also play a demo on shapez.io first and decide later! + title_advantages: Standalone Advantages + advantages: + - 12 New Level for a total of 26 levels + - 18 New Buildings for a fully automated factory! + - 20 Upgrade Tiers for many hours of fun! + - Wires Update for an entirely new dimension! + - Dark Mode! + - Unlimited Savegames + - Unlimited Markers + - Support me! ❤️ + title_future: Planned Content + planned: + - Blueprint Library (Standalone Exclusive) + - Steam Achievements + - Puzzle Mode + - Minimap + - Mods + - Sandbox mode + - ... and a lot more! + title_open_source: This game is open source! + title_links: Links + links: + discord: Official Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Help translate + text_open_source: >- + 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! +global: + loading: Učitavanje + error: Greška + thousandsDivider: " " + decimalSeparator: . + suffix: + thousands: hilj. + millions: mil. + billions: mlrd. + trillions: tril. + infinite: beskonačno + time: + 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 + secondsShort: s + minutesAndSecondsShort: m s + hoursAndMinutesShort: h m + xMinutes: min + keys: + tab: TAB + control: CTRL + alt: ALT + escape: ESC + shift: SHIFT + space: SPACE +demoBanners: + 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 + 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 + savegameUnnamed: Unnamed +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: Are you sure you want to delete the following game?

+ '' at level

This can not be + undone! + 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: Give it a meaningful name, you can also include a short + key of a shape (Which you can generate here) + 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! + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: Rename Savegame + desc: You can rename your savegame here. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? +ingame: + 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 + colors: + red: Crvena + green: Zelena + blue: Plava + yellow: Žuta + purple: Ljubičasta + cyan: Cijan + white: Bela + black: Crna + uncolored: Bez boje + buildingPlacement: + cycleBuildingVariants: Pritisni za različite varijacije građevine. + hotkeyLabel: "Taster: " + infoTexts: + speed: Brzina + range: Domet + storage: Skladište + oneItemPerSecond: 1 premet / sekundi + itemsPerSecond: predmeta / s + itemsPerSecondDouble: (x2) + tiles: polja + levelCompleteNotification: + levelTitle: Nivo + completed: Završen + unlockText: Otključali ste ! + buttonNextLevel: Sledeći nivo + notifications: + newUpgrade: Nova nadogradnja je dostupna! + gameSaved: Igra je sačuvana. + freeplayLevelComplete: Level has been completed! + shop: + title: Nadogradnje + buttonUnlock: Nadogradi + tier: red + maximumLevel: MAKSIMALNI LEVEL (Brzina x) + 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. + shapesDisplayUnits: + second: / s + minute: / m + hour: / h + settingsMenu: + playtime: Vreme igranja + buildingsPlaced: Građevine + beltsPlaced: Trake + tutorialHints: + title: Potrebna pomoć? + showHint: Prikaži savet + hideHint: Zatvori + blueprintPlacer: + cost: Cena + 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. + shapeViewer: + title: Slojevi + empty: Prazno + copyKey: Kopiraj kod oblika + 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." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limited to + watermark: + title: Demo version + desc: Click here to see the Steam version advantages! + get_on_steam: Get on steam + standaloneAdvantages: + title: Get the full version! + no_thanks: No, thanks! + points: + levels: + title: 12 New Levels + desc: For a total of 26 levels! + buildings: + title: 18 New Buildings + desc: Fully automate your factory! + savegames: + title: ∞ Savegames + desc: As many as your heart desires! + upgrades: + title: 20 Upgrade Tiers + desc: This demo version has only 5! + markers: + title: ∞ Markers + desc: Never get lost in your factory! + wires: + title: Wires + desc: An entirely new dimension! + darkmode: + title: Dark Mode + desc: Stop hurting your eyes! + support: + title: Support me + desc: I develop it in my spare time! +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: + hub: + deliver: Dostavite + toUnlock: kako bi otključali + levelShortcut: LVL + endOfDemo: End of Demo + belt: + default: + name: Pokretna traka + description: Prenosi predmete, drži i prevuci za postavku više njih. + wire: + default: + name: Žica + description: Omogućava prenos energije. + second: + name: Wire + description: Transfers signals, which can be items, colors or booleans (1 / 0). + Different colored wires do not connect. + miner: + default: + name: 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: + default: + name: 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. + cutter: + default: + name: 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! + rotater: + default: + name: 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. + rotate180: + name: Rotate (180) + description: Rotates shapes by 180 degrees. + stacker: + default: + name: Slagač + description: Slaže jedan oblik na drugi. Ako se oblici ne mogu spojiti, desni + oblik se postavlja na vrh levog. + mixer: + default: + name: Mešalica boja + description: Spaja dve boje koristeći aditivno mešanje boja. + painter: + default: + name: Farbač + description: Farba ceo oblik na levom ulazu bojom sa gornjeg ulaza. + mirrored: + name: Farbač + description: Farba ceo oblik na levom ulazu bojom sa gornjeg ulaza. + double: + name: Farbač (dupli) + description: Farba ceo oblik na levom ulazu bojom sa gornjeg ulaza. + quad: + name: Farbač (četvorostruki) + description: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! + trash: + default: + name: Smeće + description: Prima stvar sa svih strana i zauvek ih uništava. + balancer: + default: + name: Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. + merger: + name: Merger (compact) + description: Merges two conveyor belts into one. + merger-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + storage: + default: + name: Storage + description: Stores excess items, up to a given capacity. Prioritizes the left + output and can be used as an overflow gate. + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: Switch + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means + shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. + (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means + shape, color or boolean "1") + transistor: + default: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + mirrored: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: Belt Reader + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: Virtual Cutter + description: Virtually cuts the shape into two halves. + rotater: + name: Virtual Rotater + description: Virtually rotates the shape, both clockwise and counter-clockwise. + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the + remaining ones to the left. + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the shape on + the right input. + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the + wires layer on the regular layer. +storyRewards: + reward_cutter_and_trash: + title: Rezanje Oblika + desc: You just unlocked the cutter, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! + 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: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! + 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: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" + 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_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_storage: + title: Skladište + desc: You have unlocked the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! + reward_freeplay: + title: Slobodna Igra + desc: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. + 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). + 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! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: End of Demo + desc: You have reached the end of the demo version! +settings: + title: Podešavanja + categories: + general: General + userInterface: User Interface + advanced: Advanced + performance: Performance + versionBadges: + dev: Razvoj + staging: Skela + 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: + 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. + soundVolume: + title: Sound Volume + description: Set the volume for sound effects + musicVolume: + title: Music Volume + description: Set the volume for music + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % +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: Pokretna traka + underground_belt: Tunel + miner: Rudar + cutter: Rezač + rotater: Obrtač (↻) + stacker: Slagač + mixer: Mešalica boja + painter: Farbač + trash: Smeće + wire: Žica + 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 + balancer: Balancer + storage: Storage + constant_signal: Constant Signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" +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. +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-sv.yaml b/translations/base-sv.yaml index 69d6a1a0..5b2bcf53 100644 --- a/translations/base-sv.yaml +++ b/translations/base-sv.yaml @@ -1,111 +1,63 @@ -# -# 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 är ett spel som går ut på att automatisera skapandet av former med ökande komplexitet inom den oändligt stora världen. + 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. + discordLinkShort: Officiel Discord + intro: >- + Shapez.io is a relaxed game in which you have to build factories for the + automated production of geometric shapes. - # 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] + As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map. - 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. + And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! - 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]! + While you only process shapes at the beginning, you have to color them later - for this you have to extract and mix colors! - 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. + Buying the game on Steam gives you access to the full version, but you can also play a demo on shapez.io first and decide later! + title_advantages: Standalone Advantages + advantages: + - 12 New Level for a total of 26 levels + - 18 New Buildings for a fully automated factory! + - 20 Upgrade Tiers for many hours of fun! + - Wires Update for an entirely new dimension! + - Dark Mode! + - Unlimited Savegames + - Unlimited Markers + - Support me! ❤️ + title_future: Planned Content + planned: + - Blueprint Library (Standalone Exclusive) + - Steam Achievements + - Puzzle Mode + - Minimap + - Mods + - Sandbox mode + - ... and a lot more! + title_open_source: This game is open source! + title_links: Links + links: + discord: Official Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Help translate + text_open_source: >- + Anybody can contribute, I'm actively involved in the community and + attempt to review all suggestions and take feedback into consideration + where possible. - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! - global: loading: Laddar error: Error - - # 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" + thousandsDivider: . 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: inf - time: - # Used for formatting past time dates oneSecondAgo: för en sekund sedan xSecondsAgo: för sekunder sedan oneMinuteAgo: för en minut sedan @@ -114,14 +66,10 @@ global: xHoursAgo: för timmar sedan oneDayAgo: för en dag sedan xDaysAgo: för dagar sedan - - # Short formats for times, e.g. '5h 23m' secondsShort: s minutesAndSecondsShort: m s - hoursAndMinutesShort: t s - + hoursAndMinutesShort: t m xMinutes: minuter - keys: tab: TAB control: CTRL @@ -129,34 +77,26 @@ global: escape: ESC shift: SKIFT space: MELLANSLAG - demoBanners: - # This is the "advertisement" shown in the main menu and other various places title: Demo Version - intro: >- - Skaffa den fristående versionen för att låsa upp alla funktioner! - + intro: Skaffa den fristående versionen för att låsa upp alla funktioner! 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. - + 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 en + bättre upplevelse. savegameLevel: Nivå savegameLevelUnknown: Okänd Nivå - - continue: Fortsätt newGame: Nytt spel madeBy: Skapad av subreddit: Reddit - + savegameUnnamed: Unnamed dialogs: buttons: ok: OK @@ -170,113 +110,108 @@ dialogs: viewUpdate: Se uppdateringar showUpgrades: Visa uppgraderingar showKeybindings: Visa tangentbindingar - importSavegameError: title: Importfel - text: >- - Kunde inte importera sparfil: - + text: "Kunde inte importera sparfil:" importSavegameSuccess: title: Sparfil importerad - text: >- - Din sparfil har blivit importerad. - + text: Din sparfil har blivit importerad. gameLoadFailure: title: Spel är brutet - text: >- - Kunde inte ladda sparfil: - + text: "Kunde inte ladda sparfil:" confirmSavegameDelete: title: Bekräfta radering - text: >- - Är du säker på att du vill radera spelet? - + text: Är du säker på att du vill ta bort följande spel?

'' + på nivå

Detta kan inte ångras! savegameDeletionError: title: Kunde inte radera - text: >- - Kunde inte radera sparfil: - + text: "Kunde inte radera sparfil:" restartRequired: title: Omstart krävs - text: >- - Du behöver starta om spelet för att applicera inställningar. - + text: Du behöver starta om spelet för att applicera inställningar. 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 - desc: Detta kommer att återställa alla tangentbindningar till deras standardtangenter. Var snäll och bekräfta. - + desc: Detta kommer att återställa alla tangentbindningar till deras + standardtangenter. Var snäll och bekräfta. keybindingsResetOk: title: Återställning av snabbtangenter desc: Snabbtangenterna har återställts! - featureRestriction: title: Demoversion - desc: Du försökte nå en funktion () som inte är tillgänglig i demoversionen. Överväg att skaffa den fristående versionen för den fulla upplevelsen! - + desc: Du försökte nå en funktion () som inte är tillgänglig i + demoversionen. Överväg att skaffa den fristående versionen för den + fulla upplevelsen! 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: - + desc: "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! + desc: 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? - + desc: 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. - + desc: 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!

- 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.
- + 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!

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.
" 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 - + desc: Give it a meaningful name, you can also include a short + key of a shape (Which you can generate here) + 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: >- - Du klipper en stor mängd byggnader ( för att vara exakt)! - Är du säker på att du vill göra detta? - + desc: Du klipper en stor mängd byggnader ( för att vara exakt)! Är du + säker på att du vill göra detta? exportScreenshotWarning: 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 - + 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! 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? + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: Byt namn på sparfil + desc: Du kan byta namn på din sparfil här. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: Flytta selectBuildings: Välj yta @@ -285,10 +220,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 @@ -296,19 +231,10 @@ ingame: copySelection: Kopiera clearSelection: Rensa vald pipette: Pipett - switchLayers: Switch layers - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + switchLayers: Byt lager 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: Tryck ned För att bläddra igenom varianter. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - + hotkeyLabel: "Snabbtangent: " infoTexts: speed: Hastighet range: Räckvidd @@ -316,36 +242,21 @@ ingame: oneItemPerSecond: 1 objekt / sekund itemsPerSecond: objekt / s itemsPerSecondDouble: (x2) - tiles: plattor - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Nivå completed: Avklarad unlockText: Upplåst ! buttonNextLevel: Nästa Nivå - - # Notifications on the lower right notifications: newUpgrade: En ny uppgradering är tillgänglig! gameSaved: Ditt spel har sparats. - - # The "Upgrades" window + freeplayLevelComplete: Nivå har blivit avklarad! shop: title: Upgraderingar buttonUnlock: Upgradera - - # Gets replaced to e.g. "Tier IX" tier: Tier - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXNIVÅ (Hastighet x) - - # The "Statistics" window statistics: title: Statistik dataSources: @@ -354,55 +265,70 @@ ingame: description: Visar mängd förvarade former i din centrala byggnad. produced: title: Producerade - description: Visar alla former din fabrik producerar, detta inkluderar mellanhandsprodukter. + description: Visar alla former din fabrik producerar, detta inkluderar + mellanhandsprodukter. delivered: title: Levererade description: Visar former som levereras till din centrala byggnad. noShapesProduced: Inga former har producerats än. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: playtime: Speltid - buildingsPlaced: Byggnader beltsPlaced: Rullband - - buttons: - continue: Fortsätt - settings: Inställningar - menu: Återvänd till meny - - # Bottom left tutorial hints tutorialHints: title: Behöver hjälp? showHint: Visa tips hideHint: Stäng - - # When placing a blueprint blueprintPlacer: cost: Kostnad - - # Map markers waypoints: waypoints: Markörer hub: HUB - description: Vänsterklicka en markör för att hoppa till den, högerklicka för att ta bort den.

Tryck för att skapa en markör från nuvarande position, eller högerklicka för att skapa en markör vid vald plats. + description: Vänsterklicka en markör för att hoppa till den, högerklicka för att + ta bort den.

Tryck för att skapa en markör från + nuvarande position, eller högerklicka för att skapa + en markör vid vald plats. creationSuccessNotification: Markör har skapats. - - # Interactive tutorial interactiveTutorial: title: Tutorial hints: - 1_1_extractor: Placera en extraktor över en cirkel för att extrahera den! - 1_2_conveyor: >- - Koppla extraktorn med ettrullband till din hub!

Tips: Klicka och dra rullbandet med musen! - - 1_3_expand: >- - Detta är INTE ett idle-spel! Bygg fler extraktörer för att klara målet snabbare.

Tips: Håll SKIFT för att placera flera extraktörer, och använd R för att rotera dem. - + 1_1_extractor: Placera en extraktor över en + cirkel för att extrahera den! + 1_2_conveyor: "Koppla extraktorn med ettrullband till din + hub!

Tips: Klicka och dra rullbandet med + musen!" + 1_3_expand: "Detta är INTE ett idle-spel! Bygg fler extraktörer + för att klara målet snabbare.

Tips: Håll + SKIFT för att placera flera extraktörer, och + använd R för att rotera dem." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." colors: red: Röd green: Grön @@ -416,9 +342,43 @@ ingame: shapeViewer: title: Lager empty: Tom - copyKey: Copy Key - -# All shop upgrades + copyKey: Kopiera nyckel + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limited to + watermark: + title: Demo-version + desc: Klicka här för att se fördelarna med Steam-versionen! + get_on_steam: Skaffa på Steam + standaloneAdvantages: + title: Skaffa den fulla versionen! + no_thanks: Nej tack! + points: + levels: + title: 12 nya nivåer! + desc: Totalt 26 nivåer! + buildings: + title: 18 nya byggnader! + desc: Automatisera din fabrik fullkomligt! + savegames: + title: ∞ med sparfiler + desc: Så många som du bara vill! + upgrades: + title: 20 Upgrade Tiers + desc: This demo version has only 5! + markers: + title: ∞ med markeringar! + desc: Tappa aldrig bort dig i din fabrik längre! + wires: + title: Kablar + desc: En helt ny dimension! + darkmode: + title: Mörkt läge + desc: Sluta skada dina ögon! + support: + title: Stöd mig + desc: Jag utvecklar det på min fritid! shopUpgrades: belt: name: Rullband, Distributörer & Tunnlar @@ -432,284 +392,434 @@ shopUpgrades: painting: name: Blandning & Färgning description: hastighet x → x - -# Buildings and their name / description buildings: belt: default: - name: &belt Rullband + name: Rullband description: Transporterar objekt, håll in och dra för att placera flera. - - miner: # Internal name for the Extractor + miner: default: - name: &miner Extraktor + name: Extraktor description: Placera över en form eller färg för att extrahera den. - chainable: name: Extraktor (kedja) description: Placera över en form eller färg för att extrahera den. Kan kedjas. - - underground_belt: # Internal name for the Tunnel + underground_belt: default: - name: &underground_belt Tunnel + name: Tunnel description: Låter dig tunnla under byggnader och rullband. - tier2: name: Tunnel Tier II description: Låter dig tunnla resurser under byggnader och rullband. - - splitter: # Internal name for the Balancer - default: - name: &splitter balancer - description: Multifunktionell - Distribuerar alla inputs och outputs jämt. - - compact: - name: Sammanslagare (kompakt) - description: Slår ihop två rullband till ett. - - compact-inverse: - name: Sammanslagare (kompakt) - description: Slår ihop två rullband till ett. - cutter: default: - name: &cutter Klippare - description: Klipper former från topp till botten och outputtar båda halvor.Om du endast använder en halva, se till att förstöra den andra, annars kommer den blockera maskinen! + name: Klippare + description: Klipper former från topp till botten och outputtar båda + halvor.Om du endast använder en halva, se till att + förstöra den andra, annars kommer den blockera + maskinen! quad: name: Klippare (Quad) - description: Klipper former i fyra delar. Om du endast använder en del, se till att förstöra de andra, annars kommer de blockera maskinen! - + description: Klipper former i fyra delar. Om du endast använder en del, + se till att förstöra de andra, annars kommer de blockera + maskinen! rotater: default: - name: &rotater Roterare + name: Roterare description: Roterar former 90 grader. ccw: name: Roterare (CCW) description: Roterar former 90 motsols. - + rotate180: + name: Rotate (180) + description: Rotates shapes by 180 degrees. stacker: default: - name: &stacker Staplare - description: Staplar båda objekt. Om de inte kan slås ihop, placeras det högra objektet över det vänstra. - + name: Staplare + description: Staplar båda objekt. Om de inte kan slås ihop, placeras det högra + objektet över det vänstra. mixer: default: - name: &mixer Färgblandare + name: Färgblandare description: Blandar två färger genom additiv blandning. - painter: default: - name: &painter Färgläggare - description: &painter_desc Färgar hela formen på den vänstra ingången med färgen från den högra. + name: Färgläggare + description: Färgar hela formen på den vänstra ingången med färgen från den + högra. double: name: Färgläggare (Dubbel) description: Färgar formerna på de vänstra ingångarna med färgen från den högra. quad: name: Färgläggare (Quad) - description: Låter dig färglägga varje hörn av formen med olika färger. + description: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! mirrored: - name: *painter - description: *painter_desc - + name: Färgläggare + description: Färgar hela formen på den vänstra ingången med färgen från den + högra. trash: default: - name: &trash Skräphantering + name: Skräphantering description: Tar in former från alla sidor och förstör dem. För alltid. - - storage: - name: Förvaring - description: Förvarar överskottliga objekt, till kapacitet. Kan användas som överflödsport. hub: deliver: Leverera toUnlock: Att låsa upp levelShortcut: LVL + endOfDemo: End of Demo wire: default: name: Energy Wire description: Allows you to transport energy. - advanced_processor: + second: + name: Wire + description: Transfers signals, which can be items, colors or booleans (1 / 0). + Different colored wires do not connect. + balancer: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For - default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Merger (compact) + description: Merges two conveyor belts into one. + merger-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + storage: + default: + name: Storage + description: Stores excess items, up to a given capacity. Prioritizes the left + output and can be used as an overflow gate. + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: Switch + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means + shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. + (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means + shape, color or boolean "1") + transistor: + default: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + mirrored: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: Belt Reader + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: Virtual Cutter + description: Virtually cuts the shape into two halves. + rotater: + name: Virtual Rotater + description: Virtually rotates the shape, both clockwise and counter-clockwise. + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the + remaining ones to the left. + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the shape on + the right input. + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the + wires layer on the regular layer. storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Att klippa former - desc: Du låste just upp klipparen - den klipper former på hälften från topp till botten oavsett dess orientation!

Se till att ta bort allt överskott, annars kommer det att skapa uppehåll - Av denna anledning gav jag dig skräphantering, vilket förstör allt du inputtar! - + desc: You just unlocked the cutter, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! reward_rotater: title: Rotation - desc: Roteraren har blivit upplåst! Den roterar former 90 grader medsols. - + desc: Roteraren har blivit upplåst! Den roterar former 90 + grader medsols. reward_painter: title: Måleri - desc: >- - Målaren har låsts upp - Extrahera färger (precis som du gör med formerna) och kombinera med en form i målaren för att måla formen!

PS: Om du är färgblind finns det ett färblint läge bland inställningarna! - + desc: "Målaren har låsts upp - Extrahera färger (precis som du + gör med formerna) och kombinera med en form i målaren för att måla + formen!

PS: Om du är färgblind finns det ett färblint + läge bland inställningarna!" reward_mixer: title: Färgblandning - desc: Färgblandaren har blivit upplåst - Kombinera två färger genom additiv färgblandning med denna byggnad! - + desc: Färgblandaren har blivit upplåst - Kombinera två färger + genom additiv färgblandning med denna byggnad! reward_stacker: title: Kombinera - desc: Du kan nu kombinera former medstaplaren! Båda inputs blir kombinerade och om de kan sättas brevid varandra kommer de att sättas ihop. Om inte kommer den högra staplas över den vänstra! - + desc: Du kan nu kombinera former medstaplaren! Båda inputs blir + kombinerade och om de kan sättas brevid varandra kommer de att + sättas ihop. Om inte kommer den högra + staplas över den vänstra! reward_splitter: title: Delning/Sammanslagning - desc: Den multifunktionella balanseraren har blivit upplåst - Den kan användas för att bygga större fabriker genom att dela eller slå ihop objekt till flera rullband!

- + desc: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! reward_tunnel: title: Tunnel - desc: Tunneln blivit upplåst- Du kan nu transportera saker under rullband och byggnader med den! - + desc: Tunneln blivit upplåst- Du kan nu transportera saker + under rullband och byggnader med den! reward_rotater_ccw: title: Motsols rotation - desc: Du har låst upp en variant av roteraren - Den låter dig rotera saker motsols! För att bygga den, välj roteraren och tryck ned 'T' för att bläddra genom dess varianter! - + desc: Du har låst upp en variant av roteraren - Den låter dig + rotera saker motsols! För att bygga den, välj roteraren och + tryck ned 'T' för att bläddra genom dess varianter! reward_miner_chainable: title: Kedjeextraktor - desc: Du har låst upp Kedjeextraktorn! Den kan föra sina resurser framåt till andra extraktorer så att du kan mer effektivt extrahera resurser! - + desc: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" reward_underground_belt_tier_2: title: Tunnel Tier II - desc: Du har låst upp en ny variant av tunneln - Den har en större räckvidd, och du kan också mix-matcha tunnlarna nu! - - reward_splitter_compact: - title: Kompakt Balanserare - desc: >- - Du har låst upp en ny variant av balanseraren - Den accepterar två input och gör dem till en! - + desc: Du har låst upp en ny variant av tunneln - Den har en + större räckvidd, och du kan också mix-matcha + tunnlarna nu! reward_cutter_quad: title: Quad Klippning - desc: Du har låst upp en ny variant av klipparen - Den låter dig klippa former i fyra delar istället för bara två! - + desc: Du har låst upp en ny variant av klipparen - Den låter + dig klippa former i fyra delar istället för bara + två! reward_painter_double: title: Dubbelfärgläggning - desc: Du har låst upp en ny variant av Färgläggaren - Den fungerar som en vanlig färgläggare fast den färglägger två former åt gången och använder bara en färg istället för två! - - reward_painter_quad: - title: Quad Färgläggning - desc: Du har låst upp en ny variant av Färgläggaren - Den låter dig färglägga varje del av en form individuellt! - + desc: Du har låst upp en ny variant av Färgläggaren - Den + fungerar som en vanlig färgläggare fast den färglägger två + former åt gången och använder bara en färg istället för + två! reward_storage: title: Förvaringsbuffert - desc: Du har låst upp en ny variant av skräphantering - Den låter dig förvara objekt upp till en viss kapacitet! - + desc: You have unlocked the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! reward_freeplay: title: Friläge - desc: Du gjorde det! Du låste upp friläge! Det betyder att former är nu slumpmässigt genererade! (oroa dig inte, mer innehåll är planerat för den fristående versionen!) - + desc: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. reward_blueprints: title: Ritningar - desc: Du kan nu kopiera och klistra in delar av din fabrik! Välj ett område (håll in CTRL, dra sedan med musen), och tryck 'C' för att kopiera det.

Att klistra in ärinte gratis, du behöver producera ritningsformer för att ha råd med det! (De du just levererade). - - # Special reward, which is shown when there is no reward actually + desc: Du kan nu kopiera och klistra in delar av din fabrik! + Välj ett område (håll in CTRL, dra sedan med musen), och tryck 'C' + för att kopiera det.

Att klistra in är inte + gratis, du behöver producera + ritningsformer för att ha råd med det! (De du just + levererade). no_reward: title: Nästa nivå - desc: >- - Denna nivå har ingen belöning, men nästa har!

PS: Se till att inte förstöra din redan existerande fabrik - Du behöver alla de där formerna igen för att låsa upp uppgraderingar! - + desc: "Denna nivå har ingen belöning, men nästa har!

PS: Se till att + inte förstöra din redan existerande fabrik - Du behöver + alla de där formerna igen för att låsa upp + uppgraderingar!" no_reward_freeplay: title: Nästa nivå - desc: >- - Grattis! Förresten, mer spelinnehåll är planerat för den fristående versionen! - + desc: Grattis! Förresten, mer spelinnehåll är planerat för den fristående + versionen! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Roterare (180 grader) + desc: Du låste precis upp roteraren! - Den låter dig rotera + former med 180 grader (Vilken överraskning! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: Slutet av demo-versionen + desc: Du har nått slutet av demo-versionen! settings: title: Inställningar categories: - game: Spelinställningar - app: Applikation - + general: General + userInterface: User Interface + advanced: Advanced + performance: Performance versionBadges: dev: Utveckling staging: Iscensättning prod: Produktion buildDate: Skapad - labels: uiScale: title: Gränssnittsskala - description: >- - Ändrar storleken på gränssnittet. gränssnittet kommer fortfarande baseras på skärmupplösning, men denna inställning kontrollerar mängdskala. + description: Ändrar storleken på gränssnittet. gränssnittet kommer fortfarande + baseras på skärmupplösning, men denna inställning kontrollerar + mängdskala. scales: super_small: Superliten small: Liten regular: Normal large: Stor huge: Enorm - scrollWheelSensitivity: title: Zoomkänslighet - description: >- - Ändrar hur känslig zoomen är (Mushjul eller styrplatta). + description: Ändrar hur känslig zoomen är (Mushjul eller styrplatta). sensitivity: super_slow: Superlångsam slow: Långsam regular: Normal fast: Snabb super_fast: Supersnabb - language: title: Språk - description: >- - Ändra språk. Alla språk är användarbidragna och kan vara inkompletta! - + description: Ändra språk. Alla språk är användarbidragna och kan vara + inkompletta! fullscreen: title: Fullskärm - description: >- - Det är rekommenderat att spela i fullskärm för bästa upplevelse. Endast tillgängligt i den fristående versionen. - + description: Det är rekommenderat att spela i fullskärm för bästa upplevelse. + Endast tillgängligt i den fristående versionen. soundsMuted: title: Dämpa Ljud - description: >- - Om på, stänger av alla ljud. - + description: Om på, stänger av alla ljud. musicMuted: title: Dämpa Musik - description: >- - Om på, stänger av all musik. - + description: Om på, stänger av all musik. theme: title: Spelutseende - description: >- - Välj spelutseende (ljust / mörkt). - + description: Välj spelutseende (ljust / mörkt). themes: dark: Mörkt light: Ljust - refreshRate: title: Simulationsmål - description: >- - Om du har en 144hz skärm, ändra uppdateringshastigheten här så kommer spelet simulera vid en högre uppdateringshastighet. Detta kan dock sänka FPS om din dator är långsam. - + description: Om du har en 144hz skärm, ändra uppdateringshastigheten här så + kommer spelet simulera vid en högre uppdateringshastighet. Detta + kan dock sänka FPS om din dator är långsam. alwaysMultiplace: title: Flerplacering - description: >- - Om på, alla byggnader kommer fortsätta vara valda efter placering. Att ha detta på är som att konstant hålla ned SKIFT. - + description: Om på, alla byggnader kommer fortsätta vara valda efter placering. + Att ha detta på är som att konstant hålla ned SKIFT. offerHints: title: Tips & Tutorials - description: >- - Om tips och tutorials ska synas under spelets gång. Gömmer också vissa delar av UI tills senare i spelet för att göra det lättare att komma in i spelet. - + description: Om tips och tutorials ska synas under spelets gång. Gömmer också + vissa delar av UI tills senare i spelet för att göra det lättare + att komma in i spelet. movementSpeed: title: Rörelsehastighet - description: Ändrar hur snabbt kameran förflyttar sig när du använder tangentbordet för att flytta kameran. + description: Ändrar hur snabbt kameran förflyttar sig när du använder + tangentbordet för att flytta kameran. speeds: super_slow: Superlångsamt slow: Långsamt @@ -719,20 +829,17 @@ settings: extremely_fast: Extremt snabbt enableTunnelSmartplace: title: Smarta Tunnlar - description: >- - När på, att placera ut tunnlar kommer automatiskt ta bort onödiga rullband. - Detta låter dig också dra för att sätta ut tunnlar och onödiga tunnlar kommer att tas bort. + description: När på, att placera ut tunnlar kommer automatiskt ta bort onödiga + rullband. Detta låter dig också dra för att sätta ut tunnlar och + onödiga tunnlar kommer att tas bort. vignette: title: Vinjett - description: >- - Sätter på vinjetten vilket gör skärmen mörkare i hörnen och - gör text lättare att läsa - + description: Sätter på vinjetten vilket gör skärmen mörkare i hörnen och gör + text lättare att läsa autosaveInterval: title: Intervall för automatisk sparning - description: >- - Kontrollerar hur ofta spelet sparas atomatiskt. - Du kan också stäng av det helt. + description: Kontrollerar hur ofta spelet sparas atomatiskt. Du kan också stäng + av det helt. intervals: one_minute: 1 Minut two_minutes: 2 Minuter @@ -742,31 +849,77 @@ settings: disabled: Avstängd compactBuildingInfo: title: Kompakt byggnadsinfo - description: >- - Kortar ned infotexter för byggnader genom att endast visa dess storlek. - Annars visas en beskrivning och bild. + description: Kortar ned infotexter för byggnader genom att endast visa dess + storlek. Annars visas en beskrivning och bild. disableCutDeleteWarnings: title: Stäng av klipp/raderingsvarningar - description: >- - Stänger av varningsdialogen som kommer upp då fler än 100 saker - ska tas bort - + description: Stänger av varningsdialogen som kommer upp då fler än 100 saker ska + tas bort enableColorBlindHelper: title: Färgblint läge - description: Aktiverar olika verktyg som låter dig spela spelet om du är färbling. + description: Aktiverar olika verktyg som låter dig spela spelet om du är + färbling. rotationByBuilding: title: Rotering per byggnadstyp - description: >- - Varje byggnadstyp kommer ihåg rotationen du senast var på individuellt. - Detta kan vara mer bekvämt om du ofta bytar byggnader som du placerar. - + description: Varje byggnadstyp kommer ihåg rotationen du senast var på + individuellt. Detta kan vara mer bekvämt om du ofta bytar + byggnader som du placerar. + soundVolume: + title: Ljudvolym + description: Ställ in volymen för ljudeffekter + musicVolume: + title: Musikvolym + description: Ställ in volymen för musiken + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: Snabbtangenter - hint: >- - Tips: Se till att använda CTRL, SKIFT, och ALT! De låter dig använda olika placeringslägen. - + hint: "Tips: Se till att använda CTRL, SKIFT, och ALT! De låter dig använda + olika placeringslägen." resetKeybindings: Återställ Snabbtangenter - categoryLabels: general: Applikation ingame: Spelinställningar @@ -775,7 +928,6 @@ keybindings: massSelect: Massval buildings: Snabbtangenter placementModifiers: Placeringsmodifierare - mappings: confirm: Godkänn back: Tillbaka @@ -784,38 +936,30 @@ keybindings: mapMoveDown: Gå Nedåt mapMoveLeft: Gå Vänster centerMap: Till mitten av världen - mapZoomIn: Zooma in mapZoomOut: Zooma ut createMarker: Skapa Markör - menuOpenShop: Uppgraderingar menuOpenStats: Statistik - toggleHud: Toggle HUD toggleFPSInfo: Toggle FPS och Debug info - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + belt: Rullband + underground_belt: Tunnel + miner: Extraktor + cutter: Klippare + rotater: Roterare + stacker: Staplare + mixer: Färgblandare + painter: Färgläggare + trash: Skräphantering rotateWhilePlacing: Rotera - rotateInverseModifier: >- - Modifiering: Rotera motsols istället + rotateInverseModifier: "Modifiering: Rotera motsols istället" cycleBuildingVariants: Cykla varianter confirmMassDelete: Godkänn massborttagning cycleBuildings: Cykla byggnader - massSelectStart: Håll in och dra för att starta massSelectSelectMultiple: Välj flera ytor massSelectCopy: Kopiera yta - placementDisableAutoOrientation: Stäng av automatisk orientering placeMultiple: Stanna kvar i placeringsläge placeInverse: Invertera automatisk rullbandsorientering @@ -826,35 +970,40 @@ keybindings: lockBeltDirection: Sätt på rullbandsplanerare switchDirectionLockSide: "Planerare: Byt sida" pipette: Pipett - menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire - + menuClose: Stäng meny + switchLayers: Byt lager + wire: Elkabel + balancer: Balancer + storage: Lagring + constant_signal: Konstant signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" about: title: Om detta spel body: >- - Detta spel är open source och utvecklas av Tobias Springer (Det är jag).

+ Detta spel är open source och utvecklas av Tobias Springer + (Det är jag).

- Om du vill hjälpa, kolla in shapez.io på github.

+ Om du vill hjälpa, kolla in shapez.io på github.

- Spelet hade inte varit möjligt utan den fantastiska discordgemenskapen - runt mina spel - Du borde gå med i den discord server!

+ Spelet hade inte varit möjligt utan den fantastiska discordgemenskapen runt mina spel - Du borde gå med i den Discord server!

- Musiken skapades av Peppsen - Han är grym!

- - Och sist men inte minst, tack till min bästa vän Niklas - Utan våra - factoriosessioner hade detta spel aldrig funnits. + Musiken skapades av Peppsen - Han är grym!

+ Och sist men inte minst, tack till min bästa vän Niklas - Utan våra factoriosessioner hade detta spel aldrig funnits. changelog: title: Changelog - demo: features: restoringGames: Återställer sparfiler @@ -862,5 +1011,65 @@ demo: oneGameLimit: Limiterad till endast en sparfil customizeKeybindings: Finjustera snabbtangenter exportingBase: Exportera hela fabriken som en bild - settingNotAvailable: Inte tillgänglig i demoversionen. +tips: + - Hubben accepterar alla sorters former, inte bara den nuvarande formen! + - Se till så dina fabriker är flexibla - det lönar sig! + - Bygg inte för nära hubben, det blir kaos! + - Om staplingen inte fungerar som förväntat kan du prova byta om dess inputs. + - Du kan ändra på bältplanneranens riktning genom att trycka R. + - Genom att hålla nere CTRL kan du dra belt utan auto-orientering. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-tr.yaml b/translations/base-tr.yaml index ea7e3eda..7cc78d33 100644 --- a/translations/base-tr.yaml +++ b/translations/base-tr.yaml @@ -1,111 +1,63 @@ -# -# 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 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. + discordLinkShort: Official Discord + intro: >- + Shapez.io geometrik şekillerin otomatik üretimi için fabrika + kurabildiğiniz sakinleştirici 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: - # - 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] + Seviye arttıkça şekiller daha karmaşık hale gelecek ve sonsuz haritada genişlemen gerekecek! - 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. + Ve bu yeterli değilmiş gibi, şekiller için talebi karşılamak için daha fazla üretim yapmalısın - buna tek yardımcı olacak şey ise genişleme! - 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]! + En başta sadece şekilleri işlerken, sonradan onları boyaman gerekecek - bunun için boyaları çıkarmalı ve karıştırmalısın! - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! + Oyunu Steam'de satın almak tam sürüme erişimi sağlayacak, ama herzaman shapez.io deneme sürümünü oynayıp sonradan karar verebilirsin! + title_advantages: Bağımsıza özel Avantajlar + advantages: + - 12 Yeni Seviye toplamda 26 seviye. + - 18 Yeni Yapı tam otomatik bir fabrika için! + - 20 Geliştirme Aşaması saatlerce eğlence için! + - Kablolar Güncellemesi tamamen yeni bir boyut için! + - Gece Modu! + - Sınırsız Oyun Kaydı + - Sınırsız Yerimi + - Beni destekleyin! ❤️ + title_future: Planlanan İçerik + planned: + - Taslak Kütüphanesi (Bağımsıza Özel) + - Steam Başarımları + - Yapboz Modu + - Küçük Harita + - Modlar + - Kum Kutusu Modu + - ... ve daha fazlası! + title_open_source: Bu oyun açık kaynak kodlu! + title_links: Bağlantılar + links: + discord: Resmi Discord Sunucusu + roadmap: Yol Haritası + subreddit: Subreddit + source_code: Kaynak kodu (GitHub) + translate: Çeviriye yardım et + text_open_source: >- + Herkes bu oyuna katkıda bulunabilir. Toplulukla aktif bir şekilde + ilgileniyorum. Bütün önerileri ve geri dönüşleri incelemeye çalışıyorum + ve mümkün olanları değerlendirmeye alıyorum. + Bütün yol haritasına Trello kartımda göz atmayı unutma! 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. + decimalSeparator: . suffix: thousands: b millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: sonsuz - time: - # Used for formatting past time dates oneSecondAgo: bir saniye önce xSecondsAgo: saniye önce oneMinuteAgo: bir dakika önce @@ -114,14 +66,10 @@ global: xHoursAgo: saat önce oneDayAgo: bir gün önce xDaysAgo: gün önce - - # Short formats for times, e.g. '5h 23m' - secondsShort: s - minutesAndSecondsShort: d s - hoursAndMinutesShort: S m - + secondsShort: sn + minutesAndSecondsShort: dk dk + hoursAndMinutesShort: sa sa xMinutes: dakika - keys: tab: TAB control: CTRL @@ -129,740 +77,1011 @@ global: escape: ESC shift: SHIFT space: SPACE - 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! - + title: Deneme Sürümü + intro: 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! - - # 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. - + discordLink: Resmİ Discord Sunucusu + helpTranslate: Çevİrİye yardım et! + browserWarning: Ü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 - + savegameUnnamed: Unnamed 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 - text: >- - Failed to import your savegame: - + title: Kayıt yükleme hatası + text: "Oyun kaydı yükleme başarısız:" importSavegameSuccess: - title: Savegame Imported - text: >- - Kayıtlı oyun başarıyla yüklendi. - + title: Oyun Kaydı Yüklendi + text: Oyun kaydı başarıyla yüklendi. gameLoadFailure: - title: Game is broken - text: >- - Failed to load your savegame: - + title: Oyun bozuk + text: "Oyun yükleme başarısız:" confirmSavegameDelete: - title: Confirm deletion - text: >- - Oyunu silmek istediğinizden emin misiniz? - + title: Silme işlemini onayla + text:

Bu kayıdı silmek istiyor musunuz? + ''

. seviyede. Bu işlem geri + alınamaz! savegameDeletionError: - title: Failed to delete - text: >- - Failed to delete the savegame: - + title: Silme başarısız + text: "Oyun kaydını silme başarısız:" restartRequired: - title: Restart required - text: >- - You need to restart the game to apply the settings. - + title: Yeniden başlatma gerekiyor + text: 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! - desc: >- - Here are the changes since you last played: - + title: Yeni güncelleme! + desc: "Son oynadığınızdan bu yana gelen değişikler:" upgradesIntroduction: - title: Unlock Upgrades - 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. - + title: Geliştirmeleri Aç + desc: Ü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 - desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? - + title: Silmeyi onayla + desc: Çok fazla yapı siliyorsunuz (tam olarak adet)! Bunu yapmak + istediğinize emin misiniz? blueprintsNotUnlocked: - title: Not unlocked yet - desc: >- - Complete level 12 to unlock Blueprints! - + title: Henüz açılmadı + desc: Taslakları açmak için 12. seviyeyi tamamlamalısınız! keybindingsIntroduction: - title: Useful 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 area to delete.
- SHIFT: Hold to place multiple of one building.
- ALT: Invert orientation of placed belts.
- + title: Kullanışlı tuş atamaları + desc: "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: Anlamlı bir isim ver. Ayrıca Şekil koduda koyabilirsiniz + (Buradan kod yapabilirisinz ) + 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 - desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you - want to do this? - + title: Kesmeyi onayla + desc: Çok fazla yapı kesiyorsunuz (tam olarak adet)! Bunu yapmak + istediğinize emin misiniz? 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: Ekran görüntüsünü dışa aktar + desc: 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? + editSignal: + title: Sinyal Ata + descItems: "Önceden tanımlı bir eşya seçin:" + descShortKey: ... veya şekil kodunu girin (Buradan + edinebileceğiniz) + renameSavegame: + title: Oyun Kaydının Yeniden Adlandır + desc: Oyun kaydını buradan adlandırabilirsiniz. + tutorialVideoAvailable: + title: Eğitim Mevcut + desc: Bu seviye için eğitim vidyosu mevcut! İzlemek + ister misin? + tutorialVideoAvailableForeignLanguage: + title: Eğitim Mevcut + desc: Bu seviye için eğitim vidyosu mevcut, ama İngilizce dilinde. + İzlemek ister misin? 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 - plannerSwitchSide: Flip planner side - cutSelection: Cut - copySelection: Copy - clearSelection: Clear Selection - pipette: Pipette - switchLayers: Switch layers - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + 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: Planlayıcıyı ters çevir + cutSelection: Kes + copySelection: Kopyala + clearSelection: Seçİmİ temİzle + pipette: Pİpet + switchLayers: Katman değİştİr 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. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - + cycleBuildingVariants: Yapının farklı türlerine geçmek için tuşuna bas. + hotkeyLabel: "Kısayol: " infoTexts: - speed: Speed - range: Range - storage: Storage - oneItemPerSecond: 1 item / second - itemsPerSecond: items / s + range: Menzil + storage: Depo + oneItemPerSecond: 1 eşya / saniye + itemsPerSecond: eşya / sn itemsPerSecondDouble: (x2) - - tiles: tiles - - # The notification when completing a level + tiles: karo + speed: Speed levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: Level - completed: Completed - unlockText: Unlocked ! - buttonNextLevel: Next Level - - # Notifications on the lower right + levelTitle: SEVİYE + completed: Tamamlandı + unlockText: Açıldı ! + buttonNextLevel: Sonrakİ Sevİye notifications: - newUpgrade: A new upgrade is available! - gameSaved: Your game has been saved. - - # The "Upgrades" window + newUpgrade: Yeni geliştirme mevcut! + gameSaved: Oyun kaydedildi. + freeplayLevelComplete: Seviye tamamlandı! shop: - title: Upgrades - buttonUnlock: Upgrade - - # Gets replaced to e.g. "Tier IX" - tier: Tier - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - - maximumLevel: MAXIMUM LEVEL (Speed x) - - # The "Statistics" window + title: Gelİştİrmeler + buttonUnlock: Gelİştİr + tier: Aşama + maximumLevel: SON SEVİYE (Hız x) 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. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + title: Teslim Edilen + description: Merkez binanıza giden bütün şekilleri gösterir. + noShapesProduced: Henüz hiçbir şekil üretilmedi. + shapesDisplayUnits: + second: / sn + minute: / dk + hour: / sa settingsMenu: - playtime: Oynama zamani - + playtime: Oynama zamanı buildingsPlaced: Yapılar - beltsPlaced: Belts - - buttons: - continue: Continue - settings: Settings - menu: Return to menu - - # Bottom left tutorial hints + beltsPlaced: Taşıma bantları tutorialHints: - title: Need help? - showHint: Show hint - hideHint: Close - - # When placing a blueprint + title: Yardım? + showHint: İpucu Göster + hideHint: Kapat blueprintPlacer: - cost: Cost - - # Map markers + cost: Bedel 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. - - # Interactive tutorial + 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. interactiveTutorial: - title: Tutorial + title: Eğİtİm hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! - 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. - + 1_1_extractor: Daire üretmek için daire şekli üzerine bir + üretici yerleştir! + 1_2_conveyor: "Ü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: "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." + 2_1_place_cutter: "Şimdi daireleri yarıya bölmek için bir Kesici yerleştir!

+ Not: Kesici şekilleri yönünden bağımsız olarak her zaman yukarıdan aşağıya + keser." + 2_2_place_trash: Kesicinin çıkış hatları doluysa durabilir!

+ Bunun için kullanılmayan çıktılara çöp + yerleştirin. + 2_3_more_cutters: "İyi iş çıkardın! Şimdi işleri hızlandırmak için iki kesici daha + yerleştir.

Not: 0-9 tuşlarını kullanarak yapılara + daha hızlı ulaşabilirsin!" + 3_1_rectangles: "Şimdi biraz dikdörtgen üretelim! 4 Üretici yerleştir ve + bunları merkeze bağla.

Not: SHIFT tuşuna + basılı tutarak bant planlayıcıyı + etkinleştir!" + 21_1_place_quad_painter: Dörtlü boyayıcıyı yerleştirin ve daireyi, + beyaz ve kırmızı renkleri + elde edin! + 21_2_switch_to_wires: Kablo katmanına E tuşuna basarak geçiş yapın!

+ Sonra boyayıcının dört girişini kablolara + bağlayın! + 21_3_place_button: Harika! Şimdi bir Anahtar yerleştirin ve onu + kablolarla bağlayın! + 21_4_press_button: "Anahtara basarak gerçekçi sinyal(1) gönderin ve bununla + boyayıcıyı aktifleştirin.

Not: Bütün girişleri bağlamanıza gerek yok! + Sadece iki tanesini kabloyla bağlamayı deneyin." 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 - -# All shop upgrades + title: Katmanlar + empty: Boş + copyKey: Şekil Kodunu Kopyala + connectedMiners: + one_miner: 1 Üretici + n_miners: Üretici + limited_items: Sınır + watermark: + title: Deneme sürümü + desc: Steam sürümü avantajlarını görmek için buraya tıklayın! + get_on_steam: Steam'de al + standaloneAdvantages: + title: Tam versiyonu al! + no_thanks: Hayır, teşekkürler! + points: + levels: + title: 12 Yeni Seviye + desc: Toplamda 26 seviye! + buildings: + title: 18 Yeni Yapı + desc: Fabrikanı tamamen otomatikleştir! + savegames: + title: ∞ Oyun Kayıtları + desc: Canın ne kadar isterse! + upgrades: + title: 20 Geliştirme Aşaması + desc: Bu deneme sürümünde sadece 5 tane var! + markers: + title: ∞ Yer imleri + desc: Fabrikanda asla kaybolma! + wires: + title: Kablolar + desc: Tamamen yeni bir boyut! + darkmode: + title: Gece Modu + desc: Gözlerini artık yorma! + support: + title: Beni destekleyin + desc: Boş zamanımda bu oyunu geliştiriyorum! 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: Üretici + 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 - -# Buildings and their name / description + name: Karıştırma & Boyama + description: Hız x → x buildings: hub: - deliver: Deliver - toUnlock: to unlock - levelShortcut: LVL - + deliver: Teslİm et + toUnlock: Açılacak + levelShortcut: SVY + endOfDemo: Deneme Sürümünün Sonu belt: default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. - - miner: # Internal name for the Extractor + name: Taşıma Bandı + description: Eşyaları taşır, basılı birden fazla yerleştirmek için tutup + sürükle. + miner: default: - name: &miner Extractor - description: Place over a shape or color to extract it. - + name: Üretİcİ + description: Bir şekli veya rengi üretmek için üzerlerini yerleştir. chainable: - name: Extractor (Chain) - description: Place over a shape or color to extract it. Can be chained. - - underground_belt: # Internal name for the Tunnel + name: Üretİcİ (Zİncİrleme) + description: Bir şekli veya rengi üretmek için üzerlerini yerleştir. Zincirleme + bağlanabilir. + underground_belt: default: - name: &underground_belt Tunnel - description: Allows to tunnel resources under buildings and belts. - + name: 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. - - 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. - + 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. 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: 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: 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. + rotate180: + name: Dödürücü (180 Derece) + 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: 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: Renk Karıştırıcısı + description: İ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: Boyayıcı + description: 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ı (İkili) + 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: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! mirrored: - name: *painter - description: *painter_desc - + name: Boyayıcı + description: Sol girdideki bütün şekli aşağı girdideki renk ile boyar. 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. + name: Çöp + description: Her yönden giren girdileri yok eder. Tamamen. wire: default: - name: Energy Wire - description: Allows you to transport energy. - advanced_processor: + name: Kablo + description: Sinyali, eşyalar veya ikili değerler(1 / 0), aktarmayı sağlar. + Farklı renkteki kablolar bağlanamaz. + second: + name: Kablo + description: Sinyali, eşyalar veya ikili değerler(1 / 0), aktarmayı sağlar. + Farklı renkteki kablolar bağlanamaz. + wire_tunnel: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For + name: Kablo Tüneli + description: İki farklı kabloyu birbirine bağlamadan bir köprü oluşturur. + balancer: default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Dengeleyici + description: Çok işlevli - bütün girdileri eşit olarak bütün çıkışlara dağıtır. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Bİrleştİrİcİ (tekİl) + description: İki taşıma bandını bir çıktı verecek şekilde birleştirir. + merger-inverse: + name: Birleştİrİcİ (tekİl) + description: İki taşıma bandını bir çıktı verecek şekilde birleştirir. + splitter: + name: Ayırıcı (tekİl) + description: Bir taşıma bandını iki çıktı verecek şekilde ayırır. + splitter-inverse: + name: Ayırıcı (tekİl) + description: Bir taşıma bandını iki çıktı verecek şekilde ayırır. + storage: + default: + name: Storage + description: Belirli bir sınıra kadar fazla eşyaları depolar. Taşırma kapısı + olarak kullanıla bilir. + constant_signal: + default: + name: Sabit Sinyal + description: Şekil, renk veya ikili değer (1 / 0) olan sabit bir sinyal + gönderir. + lever: + default: + name: Anahtar + description: Kablolarda ikili sinyal (1 / 0) gönderebilmek için açılıp + kapanabilir. Örneğin bir eşya filtresini kontrol etmek için + kullanılabilir. + logic_gate: + default: + name: AND Kapısı + description: Eğer iki girdi de doğruysa, bu kapı"1" sinyali gönderir. (Doğru; + bir şekil, renk veya "1" girdisi demektir.) + not: + name: NOT Kapısı + description: Eğer girdi doğru değilse, bu kapı "1" sinyali gönderir. (Doğru; bir + şekil, renk veya "1" girdisi demektir.) + xor: + name: XOR Kapısı + description: Eğer iki girdiden sadece biri "1" sinyali alıyorsa, bu kapı "1" + gönderir. (Doğru; bir şekil, renk veya "1" girdisi demektir.) + or: + name: OR Kapısı + description: Eğer iki girdiden herhangi biri "1" sinyali alıyorsa, bu kapı "1" + gönderir. (Doğru; bir şekil, renk veya "1" girdisi demektir.) + transistor: + default: + name: Transistör + description: Eğer yan girdi doğruysa aşağı doğru sinyal akışına izin verir. + (Şekil, renk veya "1"). + mirrored: + name: Transistör + description: Eğer yan girdi doğruysa aşağı doğru sinyal akışına izin verir. + (Şekil, renk veya "1"). + filter: + default: + name: Filtre + description: Bütün eşleşen eşyaları yukarı, geri kalanını aşağı göndermek için + bir sinyal bağla. İkili (1/0) sinyaller ile de kontrol + edilebilir. + display: + default: + name: Ekran + description: Ekranda göstermek için bir sinyal bağla - Bu sinyal bir şekil, renk + veya ikili değer (1/0) olabilir. + reader: + default: + name: Band Okuyucu + description: Bant üzerindeki ortalama hızı ölçer. Kablo katmanında son okunan + eşyayı gösterir (açıldığında). + analyzer: + default: + name: Şekil Analizcisi + description: Şeklin en alt katmanında sağ üst köşesinde bulunan şekli analiz + eder, şekli ve rengini verir. + comparator: + default: + name: Karşılaştırıcı + description: Eğer iki sinyal aynıysa "1" çıktısı verir. Şekiller, eşyalar ve + ikili değerler karşılaştırılabilir. + virtual_processor: + default: + name: Sanal Kesici + description: Sanal olarak şekli ikiye böler. + rotater: + name: Sanal Döndürücü + description: Sanal olarak şekli saat yönünde veya saatin tersi yönünde döndürür. + unstacker: + name: Sanal Katman Ayırıcı + description: Sanal olarak şeklin en üstteki katmanını ayırarak sağ çıktıya ve + geri kalanları sol çıktıya verir. + stacker: + name: Sanal Kaynaştırıcı + description: Sanal olarak sağdaki şekli soldaki şeklin üstüne kaynaştırır. + painter: + name: Sanal Boyayıcı + description: Sanal olarak aşağı girdideki şekli sağ girdideki renk ile boyar. + item_producer: + default: + name: Eşya Üretici + description: Sadece kum kutusu modunda açık, kablo katmanındaki sinyali normal + katmanda çıktı olarak verir. 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: Kesici açıldı, bu alet şekilleri yönelimi ne + olursa olsun ortadan ikiye böler!

Çıkan şekilleri + kullanmayı veya çöpe atmayı unutma yoksa makine + tıkanır! - Bu nedenle sana gönderdiğin bütün her şeyi yok + eden çöpü de 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ünde 90 + derece döndürür. 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! - + title: Boyama + desc: "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: Ayırıcıyı açtın! dengeleyicin başka bir + türü - Tek giriş alıp ikiye ayırır 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 Üretici + desc: " zincirleme üreticiyiaçtın! bununla + kaynaklarını diğer çıkarıcılarla paylaşıp daha + verimli bir şekilde çıkartabilirsin!

not: Eskilerini + yenileri ile değiştirdim!" 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! - - 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! - + title: Tünel Aşama II + desc: 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_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! - - 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: Çİ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_storage: - title: Storage Buffer - desc: You have unlocked a variant of the trash - It allows 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: Depo + desc: Depoyu açtınız! - Gönderdiğin eşyaları içinde + biriktirir!

Öncelikli olarak sol tarafından eşyaları + gönderir eğer sol taraf tıkanırsa sağ taraftan göndermeye başlar. + Bunu fazlalık eşyaları değerlendirmek için + kullanabilirsin! 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). - - # Special reward, which is shown when there is no reward actually + 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). 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! - + title: Sonrakİ Sevİye + desc: "Bu seviyenin bir ödülü yok ama bir sonrakinin olacak!

Not: Şu + anki fabrikalarını yok etmemeni öneririm - Daha sonra + Geliştirmeleri açmak için bütün + hepsine ihtiyacın olacak!" no_reward_freeplay: - title: Next level - desc: >- - Congratulations! By the way, more content is planned for the standalone! - + title: Sonrakİ Sevİye + desc: Tebrikler! + reward_freeplay: + title: Özgür Mod + desc: Başardın! Özgür modu açtın! Bu artık gelen şekillerin + rastgele oluşacağı anlamına geliyor!

Bundan + sonra ana bölge belirli bir miktar eşya değil belirli bir + miktar eşya geliş hızına bağlı olarak level atlayacaksın, + istenilen şekilleri otomatik olarak yapacak bir fabrika inşa etmeni + öneririm!

Ana bölgenin istediği şekil kablo katmanında sol + taraftan sinyal olarak gönderiliyor, yani sadece bu şekli analiz + ederek üretecek tamen otomatik bir alet yapman yeterli. + reward_demo_end: + title: Deneme Sürümünün Sonu + desc: Deneme sürümünün sonuna geldin! + reward_balancer: + title: Dengeleyici + desc: Çok fonksiyonlu dengeleyici açıldı. - Eşyaları + bantlara ayırarak ve bantları birleştirerek daha büyük + fabrikalar kurmak için kullanılabilir! + reward_merger: + title: Tekil Birleştirici + desc: Birleştiriciyi açtın ! dengeleyecinin + bir türü - İki giriş alıp tek banta atar. + reward_belt_reader: + title: Bant Okuyucu + desc: Bant okuyucu açıldı! Bu yapı taşıma bandındaki akış + hızını ölçmeyi sağlar.

Kabloları açana kadar bekle - o zaman + çok kullanışlı olacak. + reward_rotater_180: + title: Dödürücü (180 derece) + desc: 180 derece döndürücüyü açtınız! - Şekilleri 180 derece + döndürür (Süpriz! :D) + reward_display: + title: Ekran + desc: "Ekranı açtın. - Kablo katmanında bir sinyal bağla ve onu + ekranda göster!

Not: Bant okuyucunun ve deponun son + okudukları eşyayı çıkardığını fark ettin mi? Bunu ekranda göstermeyi + dene!" + reward_constant_signal: + title: Sabit Sinyal + desc: Kablo katmanında inşa edilebilen sabit sinyal'i açtın! + Bu yapı örneğin eşya filtrelerine bağlanabilir.

+ Sabit sinyal şekil, renk veya + ikili değer (1 veya 0) + gönderelebilir. + reward_logic_gates: + title: Mantık Kapıları + desc: Mantık kapıları açıldı! Çok heyecanlanmana gerek yok, ama + bu gerçekten havalı!

Bu kapılarla artık AND, OR, XOR veya + NOT işlemlerini hesaplatabilirsin.

Bonus olarak sana bir de + transistör verdim! + reward_virtual_processing: + title: Sanal İşleme + desc: Az önce bir sürü yen yapıya sahip oldun. Bu yapılar şekillerin + işlenmelerini sanal olarak denemeni sağlayacak!

+ Artık bir kesiciyi, döndürücüyü, kaynaştırıcıyı ve daha fazlasını + kablo katmanında deneyebilirsin! Bununla birlikte oyuna devam + edebilmek için 3 seçeneğin var:

- Merkez tarafından talep + edilen her türlü şekli üretecek otomatik bir makine + inşa et (Denemeni tavsiye ederim!).

- Kablolarla havalı + birşeyler inşa et.

- Oyuna normal bir şekilde devam + et.

Ne seçersen seç eğlenmeyi unutma! + reward_wires_painter_and_levers: + title: Kablolar ve Dörtlü Boyayıcı + desc: "Az önce Kablo Katmanını açtın: Normal oyunun bulunduğu + katmanın üzerinde ayrı bir katmandır ve bir sürü yeni özelliği + vardır!

Başlangıç olarak senin için Dörtlü + Boyayıcıyı açıyorum. - Kablo katmanında boyamak için + istediğin hatları bağla!

Kablo katmanına geçiş yapmak için + E tuşunu kullan.

Not: İpuçlarını kablo eğitimlerini + görmek için ayarlarda aktifleştirmeyi unutma." + reward_filter: + title: Eşya Filtresi + desc: Eşya filtresini açtın! Kablo katmanından gelen sinyalle + eşleşmelerine bağlı olarak eşyaları yukarıdaki yada aşağıdaki çıkışa + yönlendirir.

Ayrıca filtreyi tamamen açıp kapatmak için + ikili sinyal (1 / 0) kullanabilirsin. settings: - title: Settings + title: Ayarlar categories: - game: Game - app: Application - + general: Genel + userInterface: Kullanıcı Arayüzü + advanced: Gelİşmİş + performance: Performans versionBadges: - dev: Development - staging: Staging - prod: Production - buildDate: Built - + dev: Geliştirme + staging: Yükseltme + prod: Üretim + buildDate: derlendi + rangeSliderPercentage: % labels: 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. + title: Arayüz Ölçeğİ + description: 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 - description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + title: Yakınlaştırma Hassasİyeti + description: 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 - description: >- - Change the language. All translations are user contributed and might be incomplete! - + title: Dİl + description: Dili değiştirir. Bütün çevirmeler kullanıcı katkılarıyla + oluşturulmuştur ve tam olmayabilir! fullscreen: - title: Fullscreen - description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. - + title: Tam Ekran + description: En iyi oyun tecrübesi için oyunun tam ekranda oynanması tavsiye + edilir. Sadece tam sürümde mevcut. soundsMuted: - title: Mute Sounds - description: >- - If enabled, mutes all sound effects. - + title: Ses Efektlerİnİ Sustur + description: Aktif edildiğinde bütün ses efektleri susturulur. musicMuted: - title: Mute Music - description: >- - If enabled, mutes all music. - + title: Müzİğİ Sustur + description: Aktif edildiğinde bütün müzikler susturulur. theme: - title: Game theme - description: >- - Choose the game theme (light / dark). - + title: Renk Teması + description: 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 - 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. - + title: Sİmülasyon Hızı + description: 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 - description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. - + title: Çoklu Yerleştirme + description: 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 - 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. - - 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 + title: İpuçları ve Eğİtİmler + description: İpuçları ve eğitimleri açar. Ayrıca bazı arayüz elemanlarını oyunun + daha kolay öğrenilebilmesi için gizler. 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. + title: Akıllı Tüneller + description: Aktif edildiği zaman, inşa edilen tüneller yol üzerindeki işe + yaramayan bantları otomatik olarak siler. Bu ayar aynı zamanda + tünellerin çekilerek inşa edilmesi ve aşırı uzağa yerleştirilen + tünel uçlarının silinmesini de sağlar. vignette: - title: Vignette - description: >- - Enables the vignette which darkens the screen corners and makes text easier - to read. - + title: Gölgelendİrme + description: Gölgelendirmeyi açar. Gölgelendirme ekranın köşelerini karartır ve + yazıları daha kolay okuyabilmeinizi sağlar. autosaveInterval: - title: Autosave Interval - description: >- - Controls how often the game saves automatically. You can also disable it - entirely here. + title: Otomatİk Kayıt Sıklığı + description: 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 - description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a - description and image is shown. + title: Derlİ Toplu Yapı Bİlgİlerİ + description: 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 - description: >- - Disable the warning dialogs brought up when cutting/deleting more than 100 - entities. - + title: Kes/Sİl Uyarılarını Devredışı Bırak + description: 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. - + title: Yapı Türüne Göre Döndür + description: 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. + movementSpeed: + title: Hareket Hızı + description: Haritanın klavye veya fare ile gezinme hızını değiştirir. + speeds: + super_slow: Çok Yavaş + slow: Yavaş + regular: Normal + fast: Hızlı + super_fast: Çok Hızlı + extremely_fast: Aşırı Hızlı + soundVolume: + title: Ses Ayarı + description: Ses efektlerinin seviyesini ayarlar + musicVolume: + title: Müzİk Ayarı + description: Müzik seviyesini ayarlar + lowQualityMapResources: + title: Düşük Kalİte Harİta Kaynakları + description: Oyun performansını artırmak için haritada görünen kaynakların çizim + kalitesinin sadeleştirir. Kaynaklar daha açık görüneceğinde bu + özelliği bir dene! + disableTileGrid: + title: Harİta Çİzgİlerİnİ Gizle + description: Harita çizgilerini gizlemek oyun performansına yardımcı olabilir. + Aynı zamanda oyunun daha açık görünmesini sağlar! + clearCursorOnDeleteWhilePlacing: + title: Sağ Tık İnşa İptalİ + description: Varsayılan olarak açık. Özellik açıksa, inşa modundayken sağ yık + yapıldığında inşa modundan çıkar. Eğer özellik kapalıysa, inşa + modundan çıkmadan var olan yapıları sağ tık ile silebilirsiniz. + lowQualityTextures: + title: Düşük Kalİte Görüntü (Çirkin) + description: Performans için düşük kalite görüntü kullanır. Bu oyunun daha + çirkin görünmesine sebep olur! + displayChunkBorders: + title: Harİta Alan Sınırlarını Göster + description: Oyun 16'ya 16 alanlardan oluşur. Bu seçenek aktif olduğunda alan + sınırları görüntülenir. + pickMinerOnPatch: + title: Kaynak Üzerinde Üretİcİ Seç + description: Varsayılan olarak açık. Eğer pipet bir kaynağın üzerinde + kullanılırsa, üreteç yapısı inşa için seçilir. + simplifiedBelts: + title: Sadeleştİrİlmİş Bantlar (Çirkin) + description: Taşıma bandı üzerindeki eşyalar fare imleci üzerinde değilse + görüntülenmez. Eğer gerçekten performansa ihtiyacınız yoksa bu + ayarla oynamanız tavsiye edilmez. + enableMousePan: + title: Fare Kaydırarak Hareket Etme + description: Fareyi ekranın köşelerine getirerek hareket ettirmeyi sağlar. + zoomToCursor: + title: Farenin Konumuna Yakınlaştırma + description: Eğer etkinleştirilirse zaman ekran yakınlaştırılması fare imlecinin + bulunduğu yere doğru olur. Etkinleştirilmezse yakınlaştırma + ekranın ortasına doğru olur. + mapResourcesScale: + title: Uzak Bakışta Kaynakların Büyüklüğü + description: Haritaya uzaktan bakıldığında, haritadaki şekillerin büyüklüğünü + ayarlar. keybindings: - title: Keybindings - hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - - resetKeybindings: Reset Keyinbindings - + title: Tuş Atamaları + hint: "İpucu: CTRL, SHIFT ve ALT tuşlarından yararlanın! Farklı yerleştirme + seçeneklerini kullanmanızı sağlarlar." + 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 - - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker - - menuOpenShop: Upgrades - menuOpenStats: Statistics - - toggleHud: Toggle HUD - toggleFPSInfo: Toggle FPS and Debug Info - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - - rotateWhilePlacing: Rotate - rotateInverseModifier: >- - Modifier: Rotate CCW instead - cycleBuildingVariants: Cycle Variants - confirmMassDelete: Confirm Mass Delete - cycleBuildings: Cycle Buildings - - massSelectStart: Hold and drag to start - massSelectSelectMultiple: Select multiple areas - massSelectCopy: Copy 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 - + confirm: Kabul + back: Geri + mapMoveUp: Yukarı Git + mapMoveRight: Sağa Git + mapMoveDown: Aşagı Git + mapMoveLeft: Sola Git + centerMap: Haritayı Ortala + mapZoomIn: Yakınlaş + mapZoomOut: Uzaklaş + createMarker: Yer İmi Oluştur + menuOpenShop: Geliştirmeler + menuOpenStats: İstatistikler + toggleHud: Arayüzü Aç/Kapat + toggleFPSInfo: FPS ve Debug Bilgisini Aç/Kapat + belt: Taşıma Bandı + underground_belt: Tünel + miner: Üretİcİ + cutter: Kesİcİ + rotater: Döndürücü + stacker: Kaynaştırıcı + mixer: Renk Karıştırıcısı + painter: Boyayıcı + trash: Çöp + rotateWhilePlacing: Döndür + rotateInverseModifier: "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: Basılı tutup seçme + massSelectSelectMultiple: Birden fazla alanı seçme + massSelectCopy: Alanı kopyala + 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 + wire: Enerji Kablosu + balancer: Dengeleyici + storage: Depo + constant_signal: Sabit Sinyal + logic_gate: Mantık Kapısı + lever: Anahtar (normal) + filter: Filtre + wire_tunnel: Kablo Köprüsü + display: Ekran + reader: Bant Okuyucu + virtual_processor: Sanal Kesici + transistor: Transistor + analyzer: Şekil Analizcisi + comparator: Karşılaştırıcı + item_producer: Eşya Üretici (Kum Kutusu) + copyWireValue: "Kablo: Fare altındaki değeri kopyala" about: - title: About this Game + title: Oyun Hakkında body: >- - This game is open source and developed by Tobias Springer (this is me).

+ Bu oyun açık kaynaklıdır ve Tobias Springer (bu benim) tarafından + geliştirilmektedir.

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

+ Eğer katkıda bulunmak istiyorsanız, shapez.io Github sayfasına göz atın.

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

+ Bu oyunu yapmak, oyunlarımın etrafındaki büyük Discord topluluğu olmasaydı mümkün olmayacaktı - Gerçekten Discord sunucusuna katılmalısın!

- 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. + Oyun müzikleri Peppsen tarafından yapıldı - Harika biri.

+ Son olarak, en iyi arkadaşım Niklas'a büyük teşekkürler. Factorio oyunlarımız olmasaydı bu oyun hiç var olmamış olacaktı. 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 - - settingNotAvailable: Not available in the demo. + 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: Demo sürümünde mevcut değil +tips: + - Merkez, sadece mevcut şekli değil, her türlü girişi kabul eder! + - Fabrikalarınızın modüler olduğundan emin olun - karşılığını alırsınız! + - Merkeze çok yakın inşa etmeyin, yoksa büyük bir karmaşa yaratır! + - Kaynaştırma çalışmazsa, girişleri değiştirmeyi deneyin. + - R'ye basarak bant planlayıcı yönünü değiştirebilirsiniz. + - CTRL tuşunun basılı tutulması bantların otomatik yönlendirme + olmadan sürüklenmesine izin verir. + - Tüm yükseltmeler aynı seviyede olduğu sürece oranlar aynı kalır. + - Seri işlem, paralelden daha verimlidir. + - Oyunun ilerleyen bölümlerinde daha fazla yapı çeşidinin kilidini + açacaksınız! + - Farklı yapı çeşitleri arasında geçiş yapmak için T'yi + kullanabilirsiniz. + - Simetri işin püf noktasıdır! + - Farklı tünel çeşitlerini içiçe kullanabilirsiniz. + - Düzenli fabrikalar kurmaya çalışın - karşılığını alırsınız! + - Boyayıcının, T ile seçebileceğiniz aynaya göre ters bir çeşidi + vardır. + - Doğru yapı oranlarına sahip olmak verimliliği en üst düzeye çıkaracaktır. + - En üst seviyeye geliştirilmiş 5 üretici tek bir bandı dolduracaktır. + - Tünelleri unutma! + - Tam verimlilik için öğeleri eşit olarak bölmenize gerek yoktur. + - SHIFT tuşunu basılı tutmak bant planlayıcıyı etkinleştirir ve uzun + taşıma hatlarını kolayca yerleştirmenize izin verir. + - Kesiciler, kendi yönlerinden bağımsız olarak daima dikey olarak keserler. + - Beyaz renk elde etmek için üç rengi birbiriyle karıştırın. + - Depolama yapısı ilk çıktıya öncelik verir. + - Tekrarlanabilir tasarımlar oluşturmak için zaman ayırın - buna değer! + - CTRL tuşunu basılı tutmak, birden çok yapı yerleştirmeye izin verir. + - Yerleştirilen bantların yönünü ters çevirmek için ALT tuşunu basılı + tutabilirsiniz. + - Verimlilik işin püf noktasıdır! + - Merkezden daha uzaktaki şekil kaynakları daha karmaşıktır. + - Makinelerin sınırlı bir hızı vardır, bunları maksimum verimlilik için + bölün. + - Verimliliğinizi en üst düzeye çıkarmak için dengeleyiciler kullanın. + - Organizasyon önemlidir. Bantları çok fazla birbirlerine dik geçirmemeye + çalışın. + - Yapacaklarınızı önceden planlayın, yoksa büyük bir kaos olur! + - Eski fabrikalarınızı kaldırmayın! Yükseltmelerin kilidini açmak için + onlara ihtiyacınız olacak. + - Yardım aramadan önce 20. seviyeyi kendi başına geçmeyi dene! + - İşleri karıştırmayın, basit kalmaya çalışın. Sonrasında çok + ilerleyeceksiniz. + - Fabrikaları oyunun ilerleyen bölümlerinde yeniden kullanmanız gerekebilir. + Fabrikalarınızı yeniden kullanılabilecek şekilde planlayın. + - Bazen gerekli bir şekli oluşturmadan, haritada kaynak olarak + bulabilirsiniz. + - Tam yel değirmenleri / fırıldaklar asla doğal olarak ortaya çıkamaz. + - Maksimum verimlilik için şekillerinizi kesmeden önce renklendirin. + - Modülleri ile uzay yalnızca bir algıdır; ölümlü insanlar için bir endişe + kaynağı. + - Ayrı bir taslak fabrikası yapın. Modüller için önemlidirler. + - Renk karıştırıcısına daha yakından bakın, sorularınız cevaplanacaktır. + - Bir alan seçmek için CTRL tuşuna basılı olarak tıklayın. + - Merkeze çok yakın inşa etmek sonraki projelerin önüne geçebilir. + - Geliştirme listesindeki her şeklin yanındaki iğne simgesi, onu ekrana + sabitler. + - Beyaz yapmak için tüm ana renkleri karıştırın! + - Sonsuz bir haritanız var, fabrikanızı sıkıştırmayın, genişletin! + - Ayrıca Factorio'yu deneyin! Bu benim en sevdiğim oyun. + - Dörtlü kesici, sağ üstten başlayarak saat yönünde keser! + - Kayıtlı oyunlarınızı ana menüden indirebilirsiniz! + - Bu oyunda kullanışlı birçok tuş bağlantısı var! Ayarlar sayfasını kontrol + ettiğinizden emin olun. + - Bu oyunun birçok ayarı var, kontrol ettiğinizden emin olun! + - Merkezin yer imi, yönünü belirtmek için küçük bir pusulaya sahiptir! + - Bantları temizlemek için onları kesin ve ardından aynı yere yapıştırın. + - FPS'nizi (oyun kare hızı) ve Tik Oranınızı (oyun hızı) göstermek için F4'e + basın. + - Farenizin ve kameranızın sınırlarını göstermek için F4'e iki kez basın. + - Sol tarafta sabitlenmiş bir şekle tıklayarak sabitlemesini + kaldırabilirsiniz. diff --git a/translations/base-uk.yaml b/translations/base-uk.yaml index 9d02bc0c..79de8572 100644 --- a/translations/base-uk.yaml +++ b/translations/base-uk.yaml @@ -1,128 +1,75 @@ -# -# 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 is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. + shortText: shapez.io — це гра про будування фабрик для автоматизації створення + та обробки все більш складних форм на нескінченно розширюваній мапі. + discordLinkShort: Official Discord + intro: >- + Shapez.io is a relaxed game in which you have to build factories for the + automated production of geometric shapes. - # This is the text shown above the discord link - discordLink: Official Discord - Chat with me! + As the level increases, the shapes become more and more complex, and you have to spread out on the infinite map. - # 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] + And as if that wasn't enough, you also have to produce exponentially more to satisfy the demands - the only thing that helps is scaling! - 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. + While you only process shapes at the beginning, you have to color them later - for this you have to extract and mix colors! - 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]! + Buying the game on Steam gives you access to the full version, but you can also play a demo on shapez.io first and decide later! + title_advantages: Standalone Advantages + advantages: + - 12 New Level for a total of 26 levels + - 18 New Buildings for a fully automated factory! + - 20 Upgrade Tiers for many hours of fun! + - Wires Update for an entirely new dimension! + - Dark Mode! + - Unlimited Savegames + - Unlimited Markers + - Support me! ❤️ + title_future: Planned Content + planned: + - Blueprint Library (Standalone Exclusive) + - Steam Achievements + - Puzzle Mode + - Minimap + - Mods + - Sandbox mode + - ... and a lot more! + title_open_source: This game is open source! + title_links: Links + links: + discord: Official Discord + roadmap: Roadmap + subreddit: Subreddit + source_code: Source code (GitHub) + translate: Help translate + text_open_source: >- + Anybody can contribute, I'm actively involved in the community and + attempt to review all suggestions and take feedback into consideration + where possible. - 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. - - [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 ❤️ - [/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! - - [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] - [/list] - global: - loading: Loading - error: Error - - # 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. + loading: Завантаження + error: Помилка + thousandsDivider: " " + decimalSeparator: "," suffix: - thousands: k - millions: M - billions: B - trillions: T - - # Shown for infinitely big numbers - infinite: inf - + thousands: тис. + millions: млн + billions: млрд + trillions: трлн + 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 - - # Short formats for times, e.g. '5h 23m' - secondsShort: s - minutesAndSecondsShort: m s - hoursAndMinutesShort: h m - - xMinutes: minutes - + oneSecondAgo: одну секунду тому + xSecondsAgo: секунд тому + oneMinuteAgo: 1 хвилину тому + xMinutesAgo: хвилин тому + oneHourAgo: одну годину тому + xHoursAgo: годин тому + oneDayAgo: один день тому + xDaysAgo: днів тому + secondsShort: сек. + minutesAndSecondsShort: хв. сек. + hoursAndMinutesShort: год. хв. + xMinutes: хв. keys: tab: TAB control: CTRL @@ -130,748 +77,1000 @@ global: escape: ESC shift: SHIFT space: SPACE - 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! - + title: Демоверсія + intro: Завантажте окрему версію, щоб розблокувати всі функції! 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 - - # 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 - - - + importSavegame: Імпортувати + openSourceHint: Ця гра з відкритим вихідним кодом! + discordLink: Офіційний Discord сервер + helpTranslate: Допоможіть з перекладом! + madeBy: Зробив + browserWarning: Вибачте, але гра, як відомо, працює повільно у вашому браузері! + Завантажте окрему версію чи хром, щоб отримати більше задоволення від + гри. + savegameLevel: Рівень + savegameLevelUnknown: Невідомий рівень + savegameUnnamed: Unnamed 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 - text: >- - Failed to import your savegame: - + title: Помилка при імпортуванні + text: "Не вдалося імпортувати вашу збережену гру:" importSavegameSuccess: - title: Savegame Imported - text: >- - Your savegame has been successfully imported. - + title: Збереження імпортовано + text: Вашу збережену гру успішно імпортовано. gameLoadFailure: - title: Game is broken - text: >- - Failed to load your savegame: - + title: Гра поламана + text: Не вдалося завантажити вашу збережену гру. confirmSavegameDelete: - title: Confirm deletion - text: >- - Are you sure you want to delete the game? - + title: Підтвердження + text: Are you sure you want to delete the following game?

+ '' at level

This can not be + undone! savegameDeletionError: - title: Failed to delete - text: >- - Failed to delete the savegame: - + title: Виникла помилка при видаленні + text: Не вдалося видалити збережену гру. restartRequired: - title: Restart required - text: >- - You need to restart the game to apply the settings. - + title: Потрібне перезавантаження + text: Перезавантажте гру, щоб налаштування вступили в дію. 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! - desc: >- - Here are the changes since you last played: - + title: Нове оновлення! + desc: "Ось зміни з вашої останньої гри:" upgradesIntroduction: - title: Unlock Upgrades - 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. - + title: Розблокування поліпшень + desc: Усі форми, що ви виробляєте, можуть використовуватися для розблокування + поліпшення - Не зруйнуйте свої старі фабрики! + Вкладку з поліпшеннями можна знайти в правому верхньому куті екрана. massDeleteConfirm: - title: Confirm delete - desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? - + title: Підтвердження видалення + desc: Ви видаляєте багато будівль (, якщо бути точним)! Ви справді хочете + зробити це? massCutConfirm: - title: Confirm cut - desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you want to do this? - + 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: Ви не можете дозволити собі вставити цю область! Ви справді хочете + вирізати це? blueprintsNotUnlocked: - title: Not unlocked yet - desc: >- - Complete level 12 to unlock Blueprints! - + title: Ще не розблоковано + desc: Досягніть 13-го рівня, щоб розблокувати креслення! keybindingsIntroduction: - title: Useful 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.
- + title: Корисні гарячі клавіши + desc: "Гра має багато гарячих клавіш, що полегшують будівництво великих фабрик. + Ось декілька, але обов’язково ознайомтеся з прив’язками + клавіш!

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: 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! - + 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: Ви просили експортувати свою базу як знімок екрана. Зверніть увагу, що для + великої бази це може бути досить повільним процесом і може навіть + зруйнувати вашу гру! + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: Rename Savegame + desc: You can rename your savegame here. + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? 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 - - # Names of the colors, used for the color blind mode + moveMap: Рухатися + selectBuildings: Виділити будівлі + stopPlacement: Зупинити розміщення + rotateBuilding: Повернути будівлю + placeMultiple: Розмістити декілька + reverseOrientation: Змінити орієнтацію + disableAutoOrientation: Вимкнути автоматичну орієнтацію + toggleHud: Перемкнути інтерфейс + placeBuilding: Розмістити будівлю + createMarker: Створити позначку + delete: Видалити + pasteLastBlueprint: Вставити останнє креслення + lockBeltDirection: Увімкнути стрічковий планувальник + plannerSwitchSide: Змінити сторону планувальника + cutSelection: Вирізати + copySelection: Скопіювати + clearSelection: Очистити виділене + pipette: Піпетка + switchLayers: Змінити шари colors: - red: Red - green: Green - blue: Blue - yellow: Yellow - purple: Purple - cyan: Cyan - white: White - black: Black - uncolored: No color - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + red: Червоний + green: Зелений + blue: Синій + yellow: Жовтий + purple: Фіолетовий + cyan: Блакитний + white: Білий + black: Чорний + uncolored: Без кольору 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. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - Hotkey: - + cycleBuildingVariants: Натисніть для циклу варіантів. + 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 - - # The notification when completing a level + tiles: плиток levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: Level - completed: Completed - unlockText: Unlocked ! - buttonNextLevel: Next Level - - # Notifications on the lower right + levelTitle: Рівень + completed: Завершено + unlockText: Розблоковано «»! + buttonNextLevel: Наступний рівень notifications: - newUpgrade: A new upgrade is available! - gameSaved: Your game has been saved. - - # The "Upgrades" window + newUpgrade: Нове оновлення розблоковано! + gameSaved: Вашу гру збережено. + freeplayLevelComplete: Level has been completed! shop: - title: Upgrades - buttonUnlock: Upgrade - - # Gets replaced to e.g. "Tier IX" - tier: Tier - - # The roman number for each tier - tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - - maximumLevel: MAXIMUM LEVEL (Speed x) - - # The "Statistics" window + title: Поліпшення + buttonUnlock: Поліпшення + tier: Ранг + maximumLevel: МАКСИМАЛЬНИЙ РІВЕНЬ (Швидкість x) 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. - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: / m - - # Settings menu, when you press "ESC" + title: Доставлено + description: Відображає форми, що доставляються до центру. + noShapesProduced: Жодної форми поки не випускається. + shapesDisplayUnits: + second: / s + minute: / m + hour: / h settingsMenu: - playtime: Playtime - - buildingsPlaced: Buildings - beltsPlaced: Belts - - buttons: - continue: Continue - settings: Settings - menu: Return to menu - - # Bottom left tutorial hints + playtime: У грі + buildingsPlaced: Будівлі + beltsPlaced: Стрічки tutorialHints: - title: Need help? - showHint: Show hint - hideHint: Close - - # When placing a blueprint + title: Потрібна допомога? + showHint: Показати підказку + hideHint: Закрити blueprintPlacer: - cost: Cost - - # Map markers + cost: Вартість 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. - - # Shape viewer + waypoints: Позначки + hub: Центр + description: ЛКМ на позначку, щоб перейти до неї, ПКМ для + видалення

Натисніть для створення позначки з + поточного виду або ПКМ, щоб створити позначку в + обраному місці. + creationSuccessNotification: Позначку створено. shapeViewer: - title: Layers - empty: Empty - copyKey: Copy Key - - # Interactive tutorial + title: Шари + empty: Пустий + copyKey: Копіювати ключ interactiveTutorial: - title: Tutorial + title: Навчання hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! - 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. - -# All shop upgrades + 1_1_extractor: Розмістіть екстрактор поверх фігури + кола, щоб отримати її! + 1_2_conveyor: "З’єднайте екстрактор з вашим центром за допомогою + конвеєрної стрічки!

Підказка: + Натисніть і протягніть стрічку вашою мишею." + 1_3_expand: "У цій грі ВАМ НЕ ПОТРІБНО БЕЗДІЯТИ! Будуйте більше + екстракторів і стрічок, щоб виконати свою мету + швидше.

Підказка: Утримуйте SHIFT, щоб + розмістити багато екстракторів, і використовуйте + R, щоб обертати їх." + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." + connectedMiners: + one_miner: 1 Miner + n_miners: Miners + limited_items: Limited to + watermark: + title: Demo version + desc: Click here to see the Steam version advantages! + get_on_steam: Get on steam + standaloneAdvantages: + title: Get the full version! + no_thanks: No, thanks! + points: + levels: + title: 12 New Levels + desc: For a total of 26 levels! + buildings: + title: 18 New Buildings + desc: Fully automate your factory! + savegames: + title: ∞ Savegames + desc: As many as your heart desires! + upgrades: + title: 20 Upgrade Tiers + desc: This demo version has only 5! + markers: + title: ∞ Markers + desc: Never get lost in your factory! + wires: + title: Wires + desc: An entirely new dimension! + darkmode: + title: Dark Mode + desc: Stop hurting your eyes! + support: + title: Support me + desc: I develop it in my spare time! 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 - -# Buildings and their name / description + name: Змішування і малювання + description: Швидкість x → x buildings: hub: - deliver: Deliver - toUnlock: to unlock - levelShortcut: LVL - + deliver: Доставте, + toUnlock: щоб розблокувати + levelShortcut: РІВ + endOfDemo: End of Demo belt: default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. - + name: Конвеєрна стрічка + description: Транспортує предмети, утримуйте і перетягуйте для розміщення + декількох. wire: default: - name: &wire Wire - description: Allows you to transport energy - - miner: # Internal name for the Extractor + name: Дріт + description: Дозволяє передавати енергію + second: + name: Wire + description: Transfers signals, which can be items, colors or booleans (1 / 0). + Different colored wires do not connect. + miner: default: - name: &miner Extractor - description: Place over a shape or color to extract it. - + name: Екстрактор + description: Розмістіть над формою чи кольором, який хочете видобути. chainable: - name: Extractor (Chain) - description: Place over a shape or color to extract it. Can be chained. - - underground_belt: # Internal name for the Tunnel + name: Екстрактор (Ланц.) + description: Розмістіть над формою чи кольором, який хочете видобути. Можна + об’єднати в ланцюг. + underground_belt: default: - name: &underground_belt Tunnel - description: Allows you to tunnel resources under buildings and belts. - + name: Тунель + description: Дозволяє транспортувати ресурси під будівлями та стрічками. tier2: - name: Tunnel Tier II - description: Allows you 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. - + name: Тунель, ранг II + 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: Різчик + 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! - - advanced_processor: - default: - name: &advanced_processor Advanced Processor - description: Advanced shape processing - + name: Різчик (4 вих.) + description: Розрізає форми на 4 частини. Якщо ви використовуєте лише + одну частину, не забудьте знищити інші, інакше вони застрягнуть + в механізмі! rotater: default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. + name: Обертач + description: Обертає форми за годинниковою стрілкою на 90 градусів. ccw: - name: Rotate (CCW) - description: Rotates shapes counter-clockwise by 90 degrees. - + name: Обертач (-90) + description: Обертає форми проти годинникової стрілки на 90 градусів. + rotate180: + name: Rotate (180) + description: Rotates shapes by 180 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. - + name: Укладальник + description: Складає обидва елементи. Якщо їх неможливо об’єднати, правий + елемент розміщується над лівим елементом. mixer: default: - name: &mixer Color Mixer - description: Mixes two colors using additive blending. - + name: Змішувач кольорів + 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: Фарбувач + description: Забирає форму з лівого входу, а колір з верхнього. mirrored: - name: *painter - description: *painter_desc - + name: Фарбувач + description: Забирає форму з лівого входу, а колір з верхнього. 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: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! 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. - - energy_generator: - deliver: Deliver - - # This will be shown before the amount, so for example 'For 123 Energy' - toGenerateEnergy: For - + name: Смітник + description: Приймає форми зі всіх сторін і руйнує їх. Назавжди. + balancer: default: - name: &energy_generator Energy Generator - description: Generates energy by consuming shapes. Each energy generator requires a different shape. - - wire_crossings: - default: - name: &wire_crossings Wire Splitter - description: Splits a wire into two - + name: Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. merger: - name: Wire Merger - description: Merges two wires into one - + name: Merger (compact) + description: Merges two conveyor belts into one. + merger-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + storage: + default: + name: Storage + description: Stores excess items, up to a given capacity. Prioritizes the left + output and can be used as an overflow gate. + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: Switch + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means + shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. + (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means + shape, color or boolean "1") + transistor: + default: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + mirrored: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: Belt Reader + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: Virtual Cutter + description: Virtually cuts the shape into two halves. + rotater: + name: Virtual Rotater + description: Virtually rotates the shape, both clockwise and counter-clockwise. + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the + remaining ones to the left. + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the shape on + the right input. + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the + wires layer on the regular layer. 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: You just unlocked the cutter, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! reward_rotater: - title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. - + title: Обертання + desc: Обертач розблоковано! Він повертає форми за годинниковою + стрілкою на 90 градусів. 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 colorblind mode in the settings! - + title: Фарбування + desc: Фарбувач розблоковано. Видобудьте трохи кольорів з + відповідних жилок (як ви зробили це з формами) і об’єднуйте їх з + формами у фарбувачі, щоб розфарбувати форми!

До речі, якщо ви + дальтонік, то в увімкніть режим високої + контрастності в налаштуваннях! reward_mixer: - title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! - + title: Змішування кольорів + desc: The mixer has been unlocked - It mixes two colors using + additive blending! 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: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! 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: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" 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! - - 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 belt! - + title: Тунель II + desc: Ви розблокували новий варіант тунеля. Він має + більшу дальність, і ви можете також змішувати і + зіставляти ці тунелі! 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! - - 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: You have unlocked the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! 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: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. 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). - - # Special reward, which is shown when there is no reward actually + title: Креслення + desc: Ви вже можете копіювати і вставляти частини вашої + фабрики. Виберіть зону (утримуйте CTRL, а тоді тягніть мишою), і + натисніть «C», щоб скопіювати.

Вставляти креслення — + річ не безкоштовна, спочатку вам потрібно створити + форми креслень, щоб собі це дозволити! (ті, що ви + щойно доставили). 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! - - - + title: Наступний рівень + desc: "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 - desc: >- - Congratulations! By the way, more content is planned for the standalone! - + title: Наступний рівень + desc: Вітаємо! До речі, більше контенту планується в окремій версії! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: End of Demo + desc: You have reached the end of the demo version! settings: - title: Settings + title: Налаштування categories: - game: Game - app: Application - + general: Загальне + userInterface: Користувацький інтерфейс + advanced: Передове + performance: Performance versionBadges: - dev: Development - staging: Staging - prod: Production - buildDate: Built - + dev: Розробка + staging: Тестування + prod: Виробництво + buildDate: Створено labels: uiScale: - title: Interface scale - 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. + title: Масштаб інтерфейсу + description: Змінює розмір користувацього інтерфейсу. Інтерфейс усе ще буде + масштабуватися залежно від роздільної здатності вашого пристрою, + але цей параметр контролює масштаб масштабування. scales: - super_small: Super small - small: Small - regular: Regular - large: Large - huge: Huge - + super_small: Надзвичайно малий + small: Малий + regular: Звичайний + large: Великий + huge: Величезний autosaveInterval: - title: Autosave Interval - description: >- - Controls how often the game saves automatically. You can also disable it entirely here. - + title: Проміжок між автозбереженнями + description: Контролює, як часто гра автоматично зберігатиметься. Ви також + можете повністю вимкнути його тут. 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 - description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + title: Чутливість масштабування + description: Змінює наскільки чутливе масштабування (колесо миші або трекпад). 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 - description: >- - Changes how fast the view moves when using the keyboard. + title: Швидкість руху + description: Змінює Змінює швидкість руху бачення при використанні клавіатури. 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 - description: >- - Change the language. All translations are user-contributed and might be incomplete! - + title: Мова + description: Зміна мови. Усі переклади зроблені користувачами і можуть бути + незавершеними! enableColorBlindHelper: - title: Color Blind Mode - description: >- - Enables various tools which allow you to play the game if you are color blind. - + title: Режим високої контрастності + description: Дозволяє використовувати різні інструменти, які дозволяють грати в + гру, якщо ви є дальтоніком. fullscreen: - title: Fullscreen - description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. - + title: Повноекранний режим + description: Щоб повністю насолодитися грою, рекомендується грати у + повноекранному режимі. Не доступно тільки в демоверсії. soundsMuted: - title: Mute Sounds - description: >- - If enabled, mutes all sound effects. - + title: Заглушити звуки + description: Якщо увімкнено, то вимикає всі звукові ефекти. musicMuted: - title: Mute Music - description: >- - If enabled, mutes all music. - + title: Заглушити музику + description: Якщо увімкнено, то вимикає всю музику. theme: - title: Game theme - description: >- - Choose the game theme (light / dark). + title: Тема гри + description: Оберіть тему гри (світлу чи темну). themes: - dark: Dark - light: Light - + dark: Темна + light: Світла refreshRate: - title: Simulation Target - 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. - + title: Частота оновлення + description: Якщо ви маєте 144-герцовий монітор, то змініть частоту оновлення + тут, щоб гра правильно працювала при більшій швидкості + оновлення. Це може фактично знизити FPS, якщо ваш комп’ютер + занадто повільний. alwaysMultiplace: - title: Multiplace - description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. - + title: Мультирозміщення + description: Якщо ввімкнено, всі будівлі залишатимуться вибраними після + розміщення, доки ви не скасуєте це. Це еквівалентно постійному + утримуванню SHIFT. offerHints: - title: Hints & Tutorials - 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. - + title: Підказки & посібники + description: Якщо увімкнено, то пропонує підказки та посібники під час гри. + Також приховує певні елементи інтерфейсу до заданого рівня, щоб + полегшити потрапляння в гру. enableTunnelSmartplace: - title: Smart Tunnels - description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. This also enables you to drag tunnels and excess tunnels will get removed. - + title: Розумні тунелі + description: Якщо увімкнено, то розміщення тунелів видалить непотрібні стрічки. + Це також дозволяє вам перетягувати тунелі і видаляти автоматично + зайві тунелі. vignette: - title: Vignette - description: >- - Enables the vignette, which darkens the screen corners and makes text easier to read. - + title: Віньєтка + description: Вмикає віньєтку, яка затемнює кути екрану і робить текст легшим для + читання. 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. - + title: Обертання за типом будівлі + description: Кожний тип будівлі запам’ятовує обертання, яке ви встановили. Це + може бути зручнішим, якщо ви часто перемикаєтесь між розміщенням + різних типів будівель. compactBuildingInfo: - title: Compact Building Infos - description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. - + title: Компактна інформація про будівлі + description: Скорочує інформаційні поля для будівель, лише показуючи їх + співвідношення. В іншому випадку відображається опис та + зображення. disableCutDeleteWarnings: - title: Disable Cut/Delete Warnings - description: >- - Disables the warning dialogs brought up when cutting/deleting more than 100 entities. - + title: Вимкнути попердження про вирізання та видалення + description: Вимикає діалогові вікна попередження, що з’являються під час + вирізання/видалення більше 100 об’єктів. + soundVolume: + title: Sound Volume + description: Set the volume for sound effects + musicVolume: + title: Music Volume + description: Set the volume for music + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: - title: Keybindings - hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - - resetKeybindings: Reset Keybindings - + title: Гарячі клавіши + hint: "Tip: Упевніться, що ви можете використовувати CTRL, SHIFT і ALT! Вони + дозволяють різні варіанти розміщення." + 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 - - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker - - 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: Delete area - pasteLastBlueprint: Paste last blueprint - cycleBuildings: Cycle Buildings - lockBeltDirection: Enable belt planner - switchDirectionLockSide: >- - Planner: Switch side - - massSelectStart: Hold and drag to start + confirm: Підтвердити + back: Назад + mapMoveUp: Угору + mapMoveRight: Праворуч + mapMoveDown: Униз + mapMoveLeft: Ліворуч + mapMoveFaster: Пришвидшитися + centerMap: Центрувати мапу + mapZoomIn: Приблизити + mapZoomOut: Віддалити + createMarker: Створити позначку + menuOpenShop: Поліпшення + menuOpenStats: Статистика + menuClose: Закрити меню + toggleHud: Перемкнути користувацький інтерфейс + toggleFPSInfo: Перемкнути інформацію про FPS та зневадження + switchLayers: Перемкнути шари + exportScreenshot: Експортувати цілу базу у вигляді зображення + belt: Конвеєрна стрічка + underground_belt: Тунель + miner: Екстрактор + cutter: Різчик + rotater: Обертач + stacker: Укладальник + mixer: Змішувач кольорів + painter: Фарбувач + trash: Смітник + wire: Дріт + pipette: Піпетка + rotateWhilePlacing: Повернути + rotateInverseModifier: "Modifier: Повернути проти годинникової стрілки натомість" + cycleBuildingVariants: Повторювати варіанти циклічно + confirmMassDelete: Видалити ділянку + pasteLastBlueprint: Вставити останнє креслення + cycleBuildings: Перемикання будівль + lockBeltDirection: Увімкнути планувальник конвеєрних стрічок + switchDirectionLockSide: "Planner: Змінити сторону" + massSelectStart: Утримуйте і перетягуйте, щоб розпочати massSelectSelectMultiple: Select multiple areas - massSelectCopy: Copy area - massSelectCut: Cut area - - placementDisableAutoOrientation: Disable automatic orientation - placeMultiple: Stay in placement mode - placeInverse: Invert automatic belt orientation - + massSelectCopy: Копіювати ділянку + massSelectCut: Вирізати ділянку + placementDisableAutoOrientation: Вимкнути автоматичну орієнтацію + placeMultiple: Залишатися у режимі розміщення + placeInverse: Перевернути автоматичну орієнтацію стрічки + balancer: Balancer + storage: Storage + constant_signal: Constant Signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" 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.

- - Finally, huge thanks to my best friend Niklas - Without our factorio sessions, this game would never have existed. + Звуковий трек був зроблений гравцем Peppsen — він просто приголомшливий.

+ І нарешті, величезна подяка моєму найкращому другу 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 - - settingNotAvailable: Not available in the demo. + restoringGames: Відновлення збережень + importingGames: Імпортування збережень + oneGameLimit: Обмежено одним збереженням + customizeKeybindings: Налаштування гарячих клавіш + exportingBase: Експортування цілої бази у вигляді зображення + settingNotAvailable: Недоступно в демоверсії. +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-zh-CN.yaml b/translations/base-zh-CN.yaml index e99d1132..9be641ea 100644 --- a/translations/base-zh-CN.yaml +++ b/translations/base-zh-CN.yaml @@ -1,140 +1,54 @@ -# -# 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. -# - -# Chinese translation dictionary. TODO: better names for the buildings. -# Standalone:独立版 -# Demo:演示版 -# Level:关/关卡 -# Shape:图形 -# tile:格子/格 -# Keybind:按键设置 -# Menu:主界面 -# Center/Hub:基地 -# Upgrade:建筑升级/升级 -# Efficiency:效率 -# Building:建筑 -# Variant:建筑变体 -# Belt: 传送带 -# Balancer:平衡机 -# Compact Balancer:小型合流机 -# Merger:合并机 -# Tunnel:隧道 -# Extractor:开采机 -# Cutter:切割机 -# Rotate:旋转机 -# Stacker:堆叠机 -# Color Mixer:混色机 -# Painter:上色机 -# Trash:垃圾桶 - steamPage: - # This is the short text appearing on the steam page shortText: shapez.io 是一款在无边际的地图上建造工厂、自动化生产与组合愈加复杂的图形的游戏。 - # shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. - - # 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 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]! - - 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] - - [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 ❤️ - [/list] - - [b]Future Updates[/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] - - 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://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] - - discordLink: Official Discord - Chat with me! - + discordLinkShort: 官方 Discord 服务器 + intro: |- + Shapez.io 是一个休闲游戏,在其中,您将建造工厂以生产各种各样的几何图形。 + 随着等级提升,您需要生产的图形将会越来越复杂,您需要在无尽的地图中不断的扩建您的工厂。 + 如果这些还不够的话,您的生产目标是指数性增长的 - 您需要持续的增大工厂的规模! + 虽然您刚开始只需要生产图形,但您之后还可以给这些图形上色 - 您需要开采并混合颜料! + 您可以在 Steam 游戏商城购买此游戏的完整版, 但您可以先游玩试玩版并体验游戏! + title_advantages: 完整版内容 + advantages: + - 12 个全新关卡 总共 26 个不同关卡 + - 18 个全新建筑 用于建造全自动工厂! + - 20 个等级升级 不停的愉快游玩! + - 导线更新包 解锁更多可能 + - 暗色模式! + - 无限数量存档 + - 无限数量地图标记 + - 支持作者! ❤️ + title_future: 预计更新 + planned: + - 建筑蓝图库 + - Steam 成就 + - 解密模式 + - 小地图 + - 模组 + - 沙盒模式 + - ... 以及更多! + title_open_source: 这个游戏是开源的! + title_links: 链接 + links: + discord: 官方 Discord 服务器 + roadmap: Roadmap + subreddit: Subreddit + source_code: 源代码 (GitHub) + translate: 帮助汉化(翻译)组! + text_open_source: |- + 任何人都可以对这个游戏做出贡献,我会活跃在游戏社区中并 尽最大可能积极参考大家对这个游戏的的全部建议和反馈。 + 请关注我的 trello board 以获取 the full roadmap! global: loading: 加载中 error: 错误 - - # Chinese translation: There is typically no divider used for numbers. - # 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. + thousandsDivider: "," + decimalSeparator: . suffix: thousands: K millions: M billions: B trillions: T - - # Shown for infinitely big numbers infinite: 无限 - time: - # Used for formatting past time dates oneSecondAgo: 1秒前 xSecondsAgo: 秒前 oneMinuteAgo: 1分钟前 @@ -143,14 +57,10 @@ global: xHoursAgo: 小时前 oneDayAgo: 1天前 xDaysAgo: 天前 - - # Short formats for times, e.g. '5h 23m' secondsShort: 秒 minutesAndSecondsShort: 秒 - hoursAndMinutesShort: 小时 秒 - + hoursAndMinutesShort: 秒 xMinutes: 分钟 - keys: tab: TAB control: CTRL @@ -158,13 +68,9 @@ global: escape: ESC shift: SHIFT space: 空格 - demoBanners: - # This is the "advertisement" shown in the main menu and other various places - title: 演示版 - intro: >- - 获取独立版以解锁所有功能! - + title: 试玩版 + intro: 获取独立版以解锁所有游戏内容! mainMenu: play: 开始游戏 changelog: 更新日志 @@ -172,27 +78,20 @@ mainMenu: openSourceHint: 本游戏已开源! discordLink: 官方Discord服务器 helpTranslate: 帮助我们翻译! - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - 很抱歉, 本游戏在当前浏览器上可能运行缓慢! 使用chrome或者获取独立版以得到更好的体验。 - + browserWarning: 很抱歉, 本游戏在当前浏览器上可能运行缓慢! 使用 Chrome 或者获取独立版以得到更好的体验。 savegameLevel: 第关 savegameLevelUnknown: 未知关卡 - - - # contestOver: This contest has ended - Join the discord to get noticed about new contests! continue: 继续游戏 newGame: 新游戏 madeBy: 作者: subreddit: Reddit - + savegameUnnamed: 未命名 dialogs: buttons: - ok: 确认 # 好 完成 - delete: 删除 # Delete - cancel: 取消 # Cancel - later: 以后 # Later + ok: 确认 + delete: 删除 + cancel: 取消 + later: 以后 restart: 重启游戏 reset: 重置 getStandalone: 获取独立版 @@ -200,113 +99,92 @@ dialogs: viewUpdate: 查看更新 showUpgrades: 显示建筑升级 showKeybindings: 显示按键设置 - importSavegameError: title: 导入错误 - text: >- - 未能导入你的存档: - + text: 未能导入你的存档: importSavegameSuccess: title: 导入成功 - text: >- - 存档被成功导入 - + text: 存档被成功导入 gameLoadFailure: title: 存档损坏 - text: >- - 未能导入你的存档: - + text: 未能导入你的存档: confirmSavegameDelete: title: 确认删除 - text: >- - 你确定要删除这个存档吗? - + text: Are you sure you want to delete the following game?

+ '' at level

This can not be + undone! savegameDeletionError: title: 删除错误 - text: >- - 未能删除你的存档 - + text: 未能删除你的存档 restartRequired: title: 需要重启游戏 - text: >- - 你需要重启游戏以应用变更的设置。 - + text: 你需要重启游戏以应用变更的设置。 editKeybinding: title: 更改按键设置 - desc: 请按下你想要使用的按键,或者按下ESC键来取消设置。 - + desc: 请按下你想要使用的按键,或者按下 ESC 键来取消设置。 resetKeybindingsConfirmation: title: 重置所有按键 desc: 你将要重置所有按键,请确认。 - keybindingsResetOk: title: 重置所有按键 desc: 成功重置所有按键! - featureRestriction: - title: 演示版 - desc: 你尝试使用了 功能。该功能在演示版中不可用。请考虑购买独立版以获得更好的体验。 - + title: 试玩版 + desc: 你尝试使用了功能。该功能在试玩版中不可用。请考虑购买独立版以获得更好的体验。 oneSavegameLimit: title: 存档数量限制 - desc: 演示版中只能保存一份存档。 请删除旧存档或者获取独立版! - + desc: 试玩版中只能保存一份存档。请删除旧存档或者获取独立版! updateSummary: title: 更新啦! - desc: >- - 以下为自上次游戏以来更新的内容: - + desc: "以下为自上次游戏以来更新的内容:" upgradesIntroduction: 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. - + desc: 不要销毁你之前建造的工厂!你生产过的所有图形都会被用来升级建筑。 升级菜单在屏幕右上角。 massDeleteConfirm: title: 确认删除 - desc: >- - 你将要删除很多建筑,准确来说有幢! 你确定要这么做吗? - + desc: 你将要删除很多建筑,准确来说有幢! 你确定要这么做吗? blueprintsNotUnlocked: title: 未解锁 - desc: >- - 你还没有解锁蓝图功能!完成更多的关卡来解锁蓝图。 - + desc: 你还没有解锁蓝图功能!完成更多的关卡来解锁蓝图。 keybindingsIntroduction: title: 实用按键 - desc: >- - 这个游戏有很多能帮助搭建工厂的使用按键。 - 以下是其中的一些,记得在按键设置中查看其他的!

- CTRL + 拖动:选择区域以复制或删除。
- SHIFT: 按住以放置多个。
- ALT: 反向放置传送带。
- + desc: "这个游戏有很多能帮助搭建工厂的使用按键。 以下是其中的一些,记得在按键设置中查看其他的!

+ CTRL + 拖动:选择区域以复制或删除。
SHIFT: 按住以放置多个。
ALT: 反向放置传送带。
" createMarker: title: 创建地图标记 - desc: 给地图标记起一个的名字。你可以在名字中加入一个短代码以加入图形。(你可以在这里生成短代码。) - titleEdit: Edit Marker - + desc: Give it a meaningful name, you can also include a short + key of a shape (Which you can generate here) + titleEdit: 编辑地图标记 markerDemoLimit: - desc: 在演示版中你只能创建两个地图标记。请获取独立版以创建更多标记。 + desc: 在试玩版中你只能创建两个地图标记。请获取独立版以创建更多标记。 massCutConfirm: title: 确认剪切 - desc: >- - 你将要剪切很多建筑,准确来说有幢! 你确定要这么做吗? - + desc: 你将要剪切很多建筑,准确来说有幢! 你确定要这么做吗? exportScreenshotWarning: title: 工厂截图 - desc: >- - 你将要导出你的工厂的截图。如果你的基地很大,截图过程将会很慢,且有可能导致游戏崩溃! - + desc: 你将要导出你的工厂的截图。如果你的基地很大,截图过程将会很慢,且有可能导致游戏崩溃! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? - + title: 确认剪切 + desc: 你没有足够的图形来粘贴这个区域!你确定要剪切吗? + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: 重命名存档 + desc: 您可以在此重命名存档。 + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: 移动地图 selectBuildings: 选择区域 @@ -315,7 +193,7 @@ ingame: placeMultiple: 放置多个 reverseOrientation: 反向放置 disableAutoOrientation: 关闭自动定向 - toggleHud: 开关HUD + toggleHud: 开关 HUD placeBuilding: 放置建筑 createMarker: 创建地图标记 delete: 销毁 @@ -327,18 +205,9 @@ ingame: clearSelection: 取消选择 pipette: 选取器 switchLayers: Switch layers - - # 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: 按键以选择建筑变体. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - 快捷键: - + cycleBuildingVariants: 按 键以选择建筑变体. + hotkeyLabel: "快捷键: " infoTexts: speed: 效率 range: 范围 @@ -346,37 +215,21 @@ ingame: oneItemPerSecond: 1个/秒 itemsPerSecond: 个/秒 itemsPerSecondDouble: (2倍) - tiles: 格 - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: 第关 completed: 完成 unlockText: 解锁! buttonNextLevel: 下一关 - - # Notifications on the lower right notifications: newUpgrade: 有新更新啦! gameSaved: 游戏已保存。 - - # The "Upgrades" window + freeplayLevelComplete: Level has been completed! shop: title: 建筑升级 buttonUnlock: 升级 - - # Gets replaced to e.g. "Tier IX" tier: 级 - - # The roman number for each tier - # Chinese translation: Chinese characters for each tier - tierLabels: [一, 二, 三, 四, 五, 六, 七, 八, 九, 十] - maximumLevel: 最高级(倍效率) - - # The "Statistics" window statistics: title: 统计信息 dataSources: @@ -390,51 +243,57 @@ ingame: title: 送达 description: 显示图形送达基地并交付的速度。 noShapesProduced: 你还没有生产任何图形。 - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: 个/分钟 - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / 秒 + minute: / 分 + hour: / 时 settingsMenu: playtime: 游戏时间 - buildingsPlaced: 建筑数量 beltsPlaced: 传送带数量 - - buttons: - continue: 继续 - settings: 设置 - menu: 回到主界面 - - # Bottom left tutorial hints tutorialHints: title: 需要帮助? showHint: 显示帮助 hideHint: 关闭 - - # When placing a blueprint blueprintPlacer: cost: 需要 - - # Map markers waypoints: waypoints: 地图标记 hub: 基地 - description: 左键跳转到地图标记,右键删除地图标记。

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

+ 在当前地点创建地图标记,或者在选定位置上右键创建地图标记. creationSuccessNotification: 成功创建地图标记。 - - # Interactive tutorial interactiveTutorial: title: 教程 hints: 1_1_extractor: 在圆形矿脉上放一个开采机来获取圆形! - 1_2_conveyor: >- - 用传送带将你的开采机连接到基地上!

提示:用你的鼠标按下并拖动传送带! - - 1_3_expand: >- - 这不是一个挂机游戏!建造更多的开采机和传送带来更快地完成目标。

- 提示:按住SHIFT键来放置多个开采机,用R键旋转它们。 - + 1_2_conveyor: 用传送带将你的开采机连接到基地上!

提示:用你的鼠标按下并拖动传送带! + 1_3_expand: 这不是一个挂机游戏!建造更多的开采机和传送带来更快地完成目标。

提示:按住 + SHIFT 键来放置多个开采机,用 R 键旋转它们。 + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." colors: red: 红色 green: 绿色 @@ -444,13 +303,47 @@ ingame: cyan: 青色 white: 白色 uncolored: 无色 - black: Black + black: 黑色 shapeViewer: - title: 层 # TODO: find better translation + title: 层 empty: 空 - copyKey: Copy Key - -# All shop upgrades + copyKey: 复制短代码 + connectedMiners: + one_miner: 1 个开采机 + n_miners: 个开采机 + limited_items: 限制在 + watermark: + title: 试玩版 + desc: 点击这里 了解完整版内容 + get_on_steam: 在 steam 商城购买 + standaloneAdvantages: + title: 购买完整版! + no_thanks: 不需要,谢谢 + points: + levels: + title: 12 个全新关卡! + desc: 总共 26 个不同关卡! + buildings: + title: 18 个全新建筑 + desc: 用于建造全自动工厂! + savegames: + title: 无限数量存档 + desc: 存档功能可以尽情使用 + upgrades: + title: 20 个等级升级 + desc: 试玩版只有 5 个等级! + markers: + title: 无限数量地图标记 + desc: 再也不会找不到自己的工厂了 + wires: + title: 导线更新包 + desc: 解锁更多可能! + darkmode: + title: 暗色模式 + desc: 优雅且护眼的配色 + support: + title: 支持作者 + desc: 我使用闲暇时间开发游戏! shopUpgrades: belt: name: 传送带、平衡机、隧道 @@ -464,286 +357,389 @@ shopUpgrades: painting: name: 混色、上色 description: 效率 倍 → 倍 - -# Buildings and their name / description buildings: belt: default: - name: &belt 传送带 + name: 传送带 description: 运送物品,按住并拖动来放置多个传送带。 - - miner: # Internal name for the Extractor + miner: default: - name: &miner 开采机 + name: 开采机 description: 在图形或者颜色上放置来开采他们。 - chainable: name: 链式开采机 description: 在图形或者颜色上放置来开采他们。可以被链接在一起。 - - underground_belt: # Internal name for the Tunnel + underground_belt: default: - name: &underground_belt 隧道 + name: 隧道 description: 可以从其他传送带或建筑底下方运送物品。 - tier2: name: 二级隧道 description: 可以从其他传送带或建筑底下方运送物品。 - - splitter: # Internal name for the Balancer - default: - name: &splitter 平衡机 - description: 多功能——将所有输入平均分配到所有输出。 - - compact: - name: 小型合流机 - description: 把两个输入合并到一个输出上。 - - compact-inverse: - name: 小型合流机 - description: 把两个输入合并到一个输出上。 - cutter: default: - name: &cutter 切割机 - description: 将图形从上到下切开并输出。 如果你只需要其中一半,记得把另一半销毁掉,否则切割机会停止工作! + name: 切割机 + description: 将图形从上到下切开并输出。如果你只需要其中一半,记得把另一半销毁掉,否则切割机会停止工作! quad: name: 切割机(四向) - description: 将输入的图形切成四块。 如果你只需要其中一块,记得把其他的销毁掉,否则切割机会停止工作! - + description: 将输入的图形切成四块。如果你只需要其中一块,记得把其他的销毁掉,否则切割机会停止工作! rotater: default: - name: &rotater 旋转机 + name: 旋转机 description: 将图形顺时针旋转90度。 ccw: name: 旋转机(逆时针) description: 将图形逆时针旋转90度。 - + rotate180: + name: 旋转机 (180度) + description: 将图形旋转180度。 stacker: default: - name: &stacker 堆叠机 + name: 堆叠机 description: 将输入的图形拼贴在一起。如果不能被直接拼贴,右边的图形会被堆叠在左边的图形上面. - mixer: default: - name: &mixer 混色机 - description: 将两个颜色混合在一起。(加法混合) - + name: 混色机 + description: 用加法混色将两个颜色混合起来 painter: default: - name: &painter 上色机 - description: &painter_desc 将整个图形涂上输入的颜色。 + name: 上色机 + description: 将整个图形涂上输入的颜色。 double: name: 上色机(双倍) description: 同时为两个输入的图形上色,每次上色只消耗一份颜色。 quad: name: 上色机(四向) - description: 为图形的四个角涂上不同的颜色。 + description: Allows you to color each quadrant of the shape individually. Only + slots with a truthy signal on the wires layer + will be painted! mirrored: - name: *painter - description: *painter_desc - + name: 上色机 (镜像) + description: 将整个图形涂上输入的颜色。 trash: default: - name: &trash 垃圾桶 + name: 垃圾桶 description: 从所有四个方向上输入物品并销毁它们。永远。 - - storage: - name: 仓库 - description: 储存多余的物品,有一定储存上限。可以被用来作为溢流门。 hub: deliver: 交付 toUnlock: 来解锁 levelShortcut: LVL + endOfDemo: 试玩版结束 wire: default: - name: Energy Wire - description: Allows you to transport energy. - advanced_processor: + name: 能量导线 + description: 用于传输能量。 + second: + name: 导线 + description: 传输信号,信号可以是物品,颜色或者布尔值。 不同颜色的导线不会互相连接。 + balancer: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For - default: - name: Energy Generator - description: Generates energy by consuming shapes. - wire_crossings: - default: - name: Wire Splitter - description: Splits a energy wire into two. + name: Balancer + description: Multifunctional - Evenly distributes all inputs onto all outputs. merger: - name: Wire Merger - description: Merges two energy wires into one. - + name: Merger (compact) + description: Merges two conveyor belts into one. + merger-inverse: + name: Merger (compact) + description: Merges two conveyor belts into one. + splitter: + name: Splitter (compact) + description: Splits one conveyor belt into two. + splitter-inverse: + name: Splitter (compact) + description: Splits one conveyor belt into two. + storage: + default: + name: Storage + description: Stores excess items, up to a given capacity. Prioritizes the left + output and can be used as an overflow gate. + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: Switch + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND Gate + description: Emits a boolean "1" if both inputs are truthy. (Truthy means shape, + color or boolean "1") + not: + name: NOT Gate + description: Emits a boolean "1" if the input is not truthy. (Truthy means + shape, color or boolean "1") + xor: + name: XOR Gate + description: Emits a boolean "1" if one of the inputs is truthy, but not both. + (Truthy means shape, color or boolean "1") + or: + name: OR Gate + description: Emits a boolean "1" if one of the inputs is truthy. (Truthy means + shape, color or boolean "1") + transistor: + default: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + mirrored: + name: Transistor + description: Forwards the bottom input if the side input is truthy (a shape, + color or "1"). + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: Belt Reader + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: Shape Analyzer + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: Compare + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: Virtual Cutter + description: Virtually cuts the shape into two halves. + rotater: + name: Virtual Rotater + description: Virtually rotates the shape, both clockwise and counter-clockwise. + unstacker: + name: Virtual Unstacker + description: Virtually extracts the topmost layer to the right output and the + remaining ones to the left. + stacker: + name: Virtual Stacker + description: Virtually stacks the right shape onto the left. + painter: + name: Virtual Painter + description: Virtually paints the shape from the bottom input with the shape on + the right input. + item_producer: + default: + name: Item Producer + description: Available in sandbox mode only, outputs the given signal from the + wires layer on the regular layer. storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: 切割图形 - desc: 恭喜!你解锁了切割机。切割机会把图形从上到下切成两半。注意切割的方向和切割机的朝向无关。

记得把不需要的部分处理掉,否则这个这个建筑会停止工作。为此我给你准备了垃圾桶,它会把所有放进去的物品销毁掉。 - + desc: You just unlocked the cutter, which cuts shapes in half + from top to bottom regardless of its + orientation!

Be sure to get rid of the waste, or + otherwise it will clog and stall - For this purpose + I have given you the trash, which destroys + everything you put into it! reward_rotater: title: 顺时针旋转 desc: 恭喜!你解锁了旋转机。它会顺时针旋转输入的图形90度。 - 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! - + desc: 恭喜!你解锁了上色机。开采一些颜色 (就像你开采图形一样) + 将其在上色机中与图形结合来将图形上色!

PS:如果你患有色盲,可以在设置中启用色盲模式! reward_mixer: title: 混合颜色 - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! - + desc: 恭喜!你解锁了混色机。这个建筑使用加法混色将两种颜色混合起来。 reward_stacker: title: 堆叠 desc: 恭喜!你解锁了堆叠机。堆叠机会尝试把两个输入的图形拼贴在一起。如果有重叠的部分,右边的输入会被堆叠在左边的输入上方! - reward_splitter: title: 分离与合并 - desc: 恭喜!你解锁了平衡机。在大型工厂中,平衡机负责合并或分离多个传送带上的物品。

- + desc: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! reward_tunnel: title: 隧道 desc: 恭喜!你解锁了隧道。你现在可以从其他传送带或建筑底下运送物品了! - 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: "You have unlocked the chained extractor! It can + forward its resources to other extractors so you + can more efficiently extract resources!

PS: The old + extractor has been replaced in your toolbar now!" reward_underground_belt_tier_2: title: 二级隧道 desc: 恭喜!你解锁了二级隧道。这是隧道的一个变体。二级隧道有更长的传输距离。你还可以混用不同的隧道变体! - - reward_splitter_compact: - title: 小型合流机 - desc: You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one! - reward_cutter_quad: title: 四向切割机 desc: 恭喜!你解锁了切割机四向变体。它可以将输入的图形切成四块而不只是左右两块! - reward_painter_double: title: 双倍上色机 desc: 恭喜!你解锁了上色机双倍变体。它可以同时为两个图形上色,每次只消耗一份颜色! - - reward_painter_quad: - title: 四向上色机 - desc: 恭喜!你解锁了上色机四向变体。它可以在一个图形的四个角上涂不同的颜色! - reward_storage: title: 仓库 - desc: You have unlocked a variant of the trash - It allows to store items up to a given capacity! - + desc: You have unlocked the storage building - It allows you to + store items up to a given capacity!

It priorities the left + output, so you can also use it as an overflow gate! reward_freeplay: title: 自由模式 - desc: 恭喜你!你解锁了自由模式。现在图形将会是随机生成的!(不用担心,我计划在独立版本中加入更多内容!) - + desc: You did it! You unlocked the free-play mode! This means + that shapes are now randomly generated!

+ Since the hub will require a throughput from now + on, I highly recommend to build a machine which automatically + delivers the requested shape!

The HUB outputs the requested + shape on the wires layer, so all you have to do is to analyze it and + automatically configure your factory based on that. reward_blueprints: title: 蓝图 - desc: 你现在可以复制粘贴你的工厂的一部分了!按住CTRL键并拖动鼠标来选择一块区域,然后按C键复制。

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

粘贴并不是免费的,你需要使用蓝图图形来粘贴你的蓝图。蓝图图形是你刚刚交付的图形。 no_reward: title: 下一关 - desc: >- - 这一关没有奖励,但是下一关有!

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

+ PS:你生产过的所有图形都会被用来升级建筑。 no_reward_freeplay: title: 下一关 - desc: >- - 恭喜你!另外,我们已经计划在独立版中加入更多内容! - + desc: 恭喜你!另外,我们已经计划在独立版中加入更多内容! + reward_balancer: + title: Balancer + desc: The multifunctional balancer has been unlocked - It can + be used to build bigger factories by splitting and merging + items onto multiple belts! + reward_merger: + title: Compact Merger + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: End of Demo + desc: You have reached the end of the demo version! settings: title: 设置 categories: - game: 游戏内容 - app: 应用 - + general: 通用 + userInterface: 用户界面 + advanced: 高级 + performance: Performance versionBadges: - dev: 开发版本 # Development - staging: 预览版本 # Staging - prod: 正式版本 # Production + dev: 开发版本 + staging: 预览版本 + prod: 正式版本 buildDate: 于编译 - labels: uiScale: title: 用户界面大小 - description: >- - 改变用户界面大小。用户界面会随着设备分辨率缩放,这个设置决定缩放比例。 + description: 改变用户界面大小。用户界面会随着设备分辨率缩放,这个设置决定缩放比例。 scales: super_small: 最小 small: 较小 regular: 正常 large: 较大 huge: 最大 - scrollWheelSensitivity: title: 缩放灵敏度 - description: >- - 改变缩放灵敏度(鼠标滚轮或者触控板)。 + description: 改变缩放灵敏度(鼠标滚轮或者触控板)。 sensitivity: super_slow: 最低 slow: 较低 regular: 正常 fast: 较高 super_fast: 最高 - language: title: 语言 - description: >- - 改变语言。所有的翻译皆由玩家提供,且有可能正在施工中! - + description: 改变语言。所有的翻译皆由玩家提供,且有可能正在施工中! fullscreen: title: 全屏 - description: >- - 全屏以获得更好的游戏体验。仅在独立版中可用。 - + description: 全屏以获得更好的游戏体验。仅在独立版中可用。 soundsMuted: title: 关闭音效 - description: >- - 关闭所有音效。 - + description: 关闭所有音效。 musicMuted: title: 关闭音乐 - description: >- - 关闭所有音乐。 - + description: 关闭所有音乐。 theme: title: 界面主题 - description: >- - 选择界面主题(深色或浅色)。 - + description: 选择界面主题(深色或浅色)。 themes: dark: 深色 light: 浅色 - refreshRate: title: 模拟频率、刷新频率 - description: >- - 如果你的显示器是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. - + description: 如果你的显示器是 144Hz + 的,请在这里更改刷新频率,这样游戏可以正确地根据你的屏幕进行模拟。但是如果你的电脑性能不佳,提高刷新频率可能降低帧数。 alwaysMultiplace: title: 多重放置 - description: >- - 开启这个选项之后放下建筑将不会取消建筑选择。等同于一直按下SHIFT键。 - # description: >- - # If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. - + description: 开启这个选项之后放下建筑将不会取消建筑选择。等同于一直按下 SHIFT 键。 offerHints: title: 提示与教程 - description: >- - 是否显示提示、教程以及一些其他的帮助理解游戏的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. - + description: 是否显示提示、教程以及一些其他的帮助理解游戏的 UI 元素。 movementSpeed: title: 移动速度 description: 改变摄像头移动速度 @@ -754,21 +750,15 @@ settings: fast: 较快 super_fast: 非常快 extremely_fast: 最快 - enableTunnelSmartplace: title: 智能隧道放置 - description: >- - 启用后,放置隧道时会将多余的传送带移除。 - 此外,拖动隧道可以快速铺设隧道,以及移除不必要的隧道。 + description: 启用后,放置隧道时会将多余的传送带移除。 此外,拖动隧道可以快速铺设隧道,以及移除不必要的隧道。 vignette: title: 晕映 - description: >- - 启用晕映,将屏幕角落里的颜色变深,更容易阅读文本。 - + description: 启用晕映,将屏幕角落里的颜色变深,更容易阅读文本。 autosaveInterval: title: 自动保存间隔 - description: >- - 在这里控制你的游戏多长时间保存一次,或者完全关闭这个功能。 + description: 在这里控制你的游戏多长时间保存一次,或者完全关闭这个功能。 intervals: one_minute: 1分钟 two_minutes: 2分钟 @@ -778,32 +768,71 @@ settings: disabled: 关闭 compactBuildingInfo: title: 精简建筑信息 - description: >- - 缩小建筑信息展示框。如果打开,放置建筑时建筑将不再显示建筑说明和图片,只显示建筑速度或其他数据。 + description: 缩小建筑信息展示框。如果打开,放置建筑时建筑将不再显示建筑说明和图片,只显示建筑速度或其他数据。 disableCutDeleteWarnings: title: 关闭剪切/删除警告 - description: >- - 如果打开,将不再在剪切或者删除100+建筑时显示警告信息。 - + description: 如果打开,将不再在剪切或者删除100+建筑时显示警告信息。 enableColorBlindHelper: title: 色盲模式 description: 提供一些分辨颜色的工具。目前当鼠标移至颜色资源上方时,屏幕上方会显示颜色名称。 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. - + title: 记忆建筑方向 + description: 每一类建筑都会记住各自上一次的旋转方向。如果你经常在不同建筑类型之间切换,这个设置会让游戏更加舒适。 + soundVolume: + title: Sound Volume + description: Set the volume for sound effects + musicVolume: + title: Music Volume + description: Set the volume for music + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: 按键设置 - hint: >- - 提示:使用CTRL、SHIFT、ALT! 这些建在放置建筑时有不同的效果。 - # hint: >- - # Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. - + hint: 提示:使用 CTRL、SHIFT、ALT!这些建在放置建筑时有不同的效果。 resetKeybindings: 重置按键设置 - categoryLabels: general: 通用 ingame: 游戏 @@ -812,7 +841,6 @@ keybindings: massSelect: 批量选择 buildings: 建筑快捷键 placementModifiers: 放置建筑修饰键 - mappings: confirm: 确认 back: 返回 @@ -821,44 +849,30 @@ keybindings: mapMoveDown: 下 mapMoveLeft: 左 centerMap: 回到基地 - # confirm: Confirm - # back: Back - # mapMoveUp: Move Up - # mapMoveRight: Move Right - # mapMoveDown: Move Down - # mapMoveLeft: Move Left - # centerMap: Center Map - mapZoomIn: 放大 mapZoomOut: 缩小 createMarker: 创建地图标记 - menuOpenShop: 升级菜单 menuOpenStats: 统计菜单 - toggleHud: 开关HUD toggleFPSInfo: 开关帧数与调试信息 - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + belt: 传送带 + underground_belt: 隧道 + miner: 开采机 + cutter: 切割机 + rotater: 旋转机 + stacker: 堆叠机 + mixer: 混色机 + painter: 上色机 + trash: 垃圾桶 rotateWhilePlacing: 顺时针旋转 - rotateInverseModifier: >- - 修饰键: 改为逆时针旋转 + rotateInverseModifier: "修饰键: 改为逆时针旋转" cycleBuildingVariants: 选择建筑变体 confirmMassDelete: 确认批量删除 cycleBuildings: 选择建筑 massSelectStart: 开始批量选择 massSelectSelectMultiple: 选择多个区域 massSelectCopy: 复制 - placementDisableAutoOrientation: 取消自动定向 placeMultiple: 继续放置 placeInverse: 反向放置传送带 @@ -866,44 +880,108 @@ keybindings: massSelectCut: 剪切 exportScreenshot: 导出截图 mapMoveFaster: 快速移动 - lockBeltDirection: 启用传送带规划 - switchDirectionLockSide: "规划器:换边" + switchDirectionLockSide: 规划器:换边 pipette: 选取器 menuClose: Close Menu switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator wire: Energy Wire - + balancer: Balancer + storage: Storage + constant_signal: Constant Signal + logic_gate: Logic Gate + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: Shape Analyzer + comparator: Compare + item_producer: Item Producer (Sandbox) + copyWireValue: "Wires: Copy value below cursor" about: title: 关于游戏 - # title: About this Game body: >- - 本游戏由Tobias Springer(我)开发,并且已经开源。

+ 本游戏由 Tobias + Springer(我)开发,并且已经开源。

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

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

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

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

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

- - 最后,我想感谢我最好的朋友Niklas——如果没有与他的异星工厂(factorio)的游戏体验,shapez.io将不会存在。 + 本游戏的音乐由 Peppsen 制作——他是个很棒的伙伴。

+ 最后,我想感谢我最好的朋友 Niklas ——如果没有与他的异星工厂(factorio)的游戏体验,shapez.io将不会存在。 changelog: title: 版本日志 - demo: features: - restoringGames: 恢复存档 #中? - importingGames: 倒入存档 #中? + restoringGames: 恢复存档 + importingGames: 倒入存档 oneGameLimit: 最多一个存档 customizeKeybindings: 按键设置 - # customizeKeybindings: Customizing Keybindings exportingBase: 导出工厂截图 - settingNotAvailable: 在演示版中不可用。 + settingNotAvailable: 在试玩版中不可用。 +tips: + - The hub accepts input of any kind, not just the current shape! + - Make sure your factories are modular - it will pay out! + - Don't build too close to the hub, or it will be a huge chaos! + - If stacking does not work, try switching the inputs. + - You can toggle the belt planner direction by pressing R. + - Holding CTRL allows dragging of belts without auto-orientation. + - Ratios stay the same, as long as all upgrades are on the same Tier. + - Serial execution is more efficient than parallel. + - You will unlock more variants of buildings later in the game! + - You can use T to switch between different variants. + - Symmetry is key! + - You can weave different tiers of tunnels. + - Try to build compact factories - it will pay out! + - The painter has a mirrored variant which you can select with T + - Having the right building ratios will maximize efficiency. + - At maximum level, 5 extractors will fill a single belt. + - Don't forget about tunnels! + - You don't need to divide up items evenly for full efficiency. + - Holding SHIFT will activate the belt planner, letting you place + long lines of belts easily. + - Cutters always cut vertically, regardless of their orientation. + - To get white mix all three colors. + - The storage buffer priorities the first output. + - Invest time to build repeatable designs - it's worth it! + - Holding CTRL allows to place multiple buildings. + - You can hold ALT to invert the direction of placed belts. + - Efficiency is key! + - Shape patches that are further away from the hub are more complex. + - Machines have a limited speed, divide them up for maximum efficiency. + - Use balancers to maximize your efficiency. + - Organization is important. Try not to cross conveyors too much. + - Plan in advance, or it will be a huge chaos! + - Don't remove your old factories! You'll need them to unlock upgrades. + - Try beating level 20 on your own before seeking for help! + - Don't complicate things, try to stay simple and you'll go far. + - You may need to re-use factories later in the game. Plan your factories to + be re-usable. + - Sometimes, you can find a needed shape in the map without creating it with + stackers. + - Full windmills / pinwheels can never spawn naturally. + - Color your shapes before cutting for maximum efficiency. + - With modules, space is merely a perception; a concern for mortal men. + - Make a separate blueprint factory. They're important for modules. + - Have a closer look on the color mixer, and your questions will be answered. + - Use CTRL + Click to select an area. + - Building too close to the hub can get in the way of later projects. + - The pin icon next to each shape in the upgrade list pins it to the screen. + - Mix all primary colors together to make white! + - You have an infinite map, don't cramp your factory, expand! + - Also try Factorio! It's my favorite game. + - The quad cutter cuts clockwise starting from the top right! + - You can download your savegames in the main menu! + - This game has a lot of useful keybindings! Be sure to check out the + settings page. + - This game has a lot of settings, be sure to check them out! + - The marker to your hub has a small compass to indicate its direction! + - To clear belts, cut the area and then paste it at the same location. + - Press F4 to show your FPS and Tick Rate. + - Press F4 twice to show the tile of your mouse and camera. + - You can click a pinned shape on the left side to unpin it. diff --git a/translations/base-zh-TW.yaml b/translations/base-zh-TW.yaml index ab32dd6f..d5b5fd3d 100644 --- a/translations/base-zh-TW.yaml +++ b/translations/base-zh-TW.yaml @@ -1,138 +1,55 @@ -# -# 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. -# - -# Chinese (traditional) translation dictionary. TODO: better names for the buildings. -# Standalone:獨立版 -# Demo:演示版 -# Level:關 -# Shape:圖形 -# tile:格子 -# Keybind:按鍵設置 -# Menu:主選單 -# Center/Hub:基地 -# Upgrade:升級 -# Efficiency:效率 -# Building:建築 -# Variant:建築變體 -# Belt: 傳送帶 -# Balancer:平衡機 -# Compact Balancer:小型合流機 -# Merger:合併機 -# Tunnel:隧道 -# Extractor:開採機 -# Cutter:切割機 -# Rotate:旋轉機 -# Stacker:混合機 -# Color Mixer:混色機 -# Painter:上色機 -# Trash:垃圾桶 - steamPage: - # This is the short text appearing on the steam page shortText: shapez.io 是一款在一個無邊際的地圖上建造工廠、自動化生產與組合愈加複雜圖形的遊戲。 - # shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. - - # 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 是一款在一個無邊無際的地圖上建造工廠、將生產與組合愈加複雜圖形自動化的遊戲。 - - 在指定圖形送達基地後,你會晉級且解鎖能加速生產的新功能。 - - 當指定圖形的數量增加時,你必須擴充你的工廠才能應付訂單 -- 但別忘記資源,你需要在[b]無邊無際的地圖[/b]上擴充。 - - 不久後你將需要混色並為圖形上色 -- 混和紅、綠、藍以創造新顏色再將圖形上色來達成目標。 - - 遊戲目前有十八關(應該也夠你忙一陣子了),而我還有很多計畫,持續更新中! - - 購買獨立版的你即擁有額外內容,也會優先接觸新開發內容。 - - [b]獨立版的額外內容[/b] - - [list] - [*] 深色主題 - [*] 地圖標記數量無限制 - [*] 存檔數量無限制 - [*] 更多設定 - [*] 即將到來: 電線與能源! 目標在2020年七月底(左右)問世。 - [*] 即將到來: 更多新關卡 - [*] 幫助我繼續開發 shapez.io ❤️ - [/list] - - [b]未來更新[/b] - - 我時常更新遊戲,希望能周更! - - [list] - [*] 不同的地圖與挑戰(像是有障礙物的地圖) - [*] 迷宮(在地圖受限制或只能使用特定建築的情況下送達圖形) - [*] 一個蓋建築物需要成本的故事模式 - [*] 可調控的地圖生成器(資源/圖形/密度可調整、隨機生成種子等等) - [*] 更多圖形種類 - [*] 遊戲效能提升(即使目前已經不錯了) - [*] 還有更多更多! - [/list] - - [b]這個遊戲是開源的![/b] - - 任何人都可以貢獻,我在社群裡很活耀、嘗試回復所有的建議並盡量參考大家的意見。 - 欲知詳情,別忘了造訪我的 Trello 喔! - - [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] - [/list] - - discordLink: Official Discord - Chat with me! - + discordLinkShort: 官方 Discord 伺服器 + intro: |- + 你喜歡自動化生產的遊戲類型嗎?那你來對地方了! + Shapez.io 是一款建造工廠、自動化生產與組合圖形的休閒遊戲。 + 每當玩家不斷晉級,形狀會越來越複雜,你的工廠將在一個無邊際的地圖上不斷擴展。 + 除此之外,你也必須不斷累加你的生產量來達到升級的需求,達成目標的方法無他,只有不段地擴張! + 遊戲初期只需要組合特定圖形,接著玩家會被要求幫圖形上色,有時甚至需要先混色才能達到目標。 + 玩家可以在 Steam 購買本游戲的單機版,如果還在猶豫,也可以到 shapez.io 先免費試玩再決定! + title_advantages: 單機版優點 + advantages: + - 12 個新關卡 (總共有26關) + - 18 個新建築 幫助玩家自動化整個工廠! + - 20 個升級 讓遊玩時間更久! + - 電路更新 帶給玩家新次元體驗! + - 深色模式! + - 無限存檔 + - 無限標記 + - 支持我! ❤️ + title_future: 未來計劃 + planned: + - 藍圖圖庫(單機版獨有) + - Steam 成就 + - 拼圖模式 + - 迷你地圖 + - 模組 + - 沙盒模式 + - ... 還有更多! + title_open_source: 本遊戲已開源! + title_links: 連結 + links: + discord: 官方 Discord 伺服器 + roadmap: Roadmap + subreddit: Reddit + source_code: Source code (GitHub) + translate: 幫助我們翻譯! + text_open_source: |- + 任何人都可以幫助我開發遊戲或提供建議,我很活躍於各個社群媒體,也會讀所有的建議與回饋、並嘗試改善。 + 記得查看我的 trello board 以了解我的完整計畫! global: loading: 加載中 error: 錯誤 - - # 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. + decimalSeparator: . suffix: thousands: 千 millions: 百萬 billions: 十億 trillions: 兆 - - # Shown for infinitely big numbers infinite: 無限 - time: - # Used for formatting past time dates oneSecondAgo: 1秒前 xSecondsAgo: 秒前 oneMinuteAgo: 1分鐘前 @@ -141,14 +58,10 @@ global: xHoursAgo: 小時前 oneDayAgo: 1天前 xDaysAgo: 天前 - - # Short formats for times, e.g. '5h 23m' secondsShort: 秒 minutesAndSecondsShort: 秒 hoursAndMinutesShort: 小時 秒 - xMinutes: 分鐘 - keys: tab: TAB control: CTRL @@ -156,34 +69,24 @@ global: escape: ESC shift: SHIFT space: 空格 - demoBanners: - # This is the "advertisement" shown in the main menu and other various places title: 演示版 - intro: >- - 獲取獨立版以解鎖所有功能! - + intro: 獲取單機版以解鎖所有功能! mainMenu: play: 開始遊戲 changelog: 更新日誌 importSavegame: 導入 openSourceHint: 本遊戲已開源! - discordLink: 官方Discord伺服器 + discordLink: 官方 Discord 伺服器 helpTranslate: 幫助我們翻譯! - - # This is shown when using firefox and other browsers which are not supported. - browserWarning: >- - 很抱歉, 本遊戲在當前瀏覽器上可能運行緩慢! 使用chrome或者獲取獨立版以得到更好的體驗。 - - savegameLevel: Level + browserWarning: 很抱歉, 本遊戲在當前瀏覽器上可能運行緩慢! 使用chrome或者獲取單機版以得到更好的體驗。 + savegameLevel: 級 savegameLevelUnknown: 未知關卡 - - continue: 繼續 newGame: 新遊戲 madeBy: 作者: subreddit: Reddit - + savegameUnnamed: 未命名 dialogs: buttons: ok: 確認 @@ -192,116 +95,95 @@ dialogs: later: 之後 restart: 重啟 reset: 重置 - getStandalone: 獲得獨立版 + getStandalone: 獲得單機版 deleteGame: 我知道我在做什麼 viewUpdate: 查看更新 showUpgrades: 顯示建築升級 showKeybindings: 顯示按鍵設置 - importSavegameError: title: 匯入錯誤 - text: >- - 存檔匯入失敗: - + text: 存檔匯入失敗: importSavegameSuccess: title: 匯入成功 - text: >- - 存檔匯入成功 - + text: 存檔匯入成功 gameLoadFailure: title: 存檔損毀 - text: >- - 存檔載入失敗: - + text: 存檔載入失敗: confirmSavegameDelete: title: 確認刪除 - text: >- - 你確定要刪除這存檔嗎? - + text: 你確定要刪除這個存檔?

'' 在第

級 不能反悔喔! savegameDeletionError: title: 刪除錯誤 - text: >- - 存檔刪除失敗 - + text: 存檔刪除失敗 restartRequired: title: 需要重啟 - text: >- - 你需要重啟遊戲以套用變更的設置。 - + text: 你需要重啟遊戲以套用變更的設置。 editKeybinding: title: 更改按鍵設置 desc: 請按下你想要使用的按鍵,或者按下ESC鍵來取消設置。 - resetKeybindingsConfirmation: title: 重置所有按鍵 desc: 這將會重置所有按鍵,請確認。 - keybindingsResetOk: title: 重置了所有按鍵 desc: 成功重置了所有按鍵! - featureRestriction: title: 演示版 - desc: 你嘗試使用了 功能。該功能在演示版中不可用。請考慮購買獨立版以獲得更好的體驗。 - + desc: 你嘗試使用了 功能。該功能在演示版中不可用。請考慮購買單機版以獲得更好的體驗。 oneSavegameLimit: title: 存檔數量限制 - desc: 演示版中只能保存一份存檔。請刪除舊存檔或者獲取獨立版! - + desc: 演示版中只能保存一份存檔。請刪除舊存檔或者獲取單機版! updateSummary: title: 更新了! - desc: >- - 以下為自上次遊戲以來更新的內容: - + desc: "以下為自上次遊戲以來更新的內容:" upgradesIntroduction: title: 解鎖建築升級 - desc: >- - 你生產過的所有圖形可以被用來升級建築。不要銷毀你之前建造的工廠! - 升級選單在屏幕右上角。 - + desc: 你生產過的所有圖形可以被用來升級建築。不要銷毀你之前建造的工廠! 升級選單在屏幕右上角。 massDeleteConfirm: title: 確認刪除 - desc: >- - 你將要刪除很多建築,準確來說有幢!你確定要這麼做嗎? - + desc: 你將要刪除很多建築,準確來說有幢!你確定要這麼做嗎? blueprintsNotUnlocked: title: 未解鎖 - desc: >- - 你還沒有解鎖藍圖功能!完成更多的關卡來解鎖藍圖。 - + desc: 你還沒有解鎖藍圖功能!完成更多的關卡來解鎖藍圖。 keybindingsIntroduction: title: 實用按鍵 - desc: >- - 這個遊戲有很多能幫助搭建工廠的使用按鍵。 - 以下是其中的一些,記得在按鍵設置中查看其他的!

- CTRL + 拖動:選擇區域以復製或刪除。
- SHIFT: 按住以放置多個。
- ALT: 反向放置傳送帶。
- + desc: "這個遊戲有很多能幫助搭建工廠的使用按鍵。 以下是其中的一些,記得在按鍵設置中查看其他的!

+ CTRL + 拖動:選擇區域以復製或刪除。
SHIFT: 按住以放置多個。
ALT: 反向放置傳送帶。
" createMarker: title: 創建標記 - desc: 給地圖標記起一個的名字。你可以在名字中加入一個短代碼以加入圖形。 (你可以在這裡生成短代碼。) - titleEdit: Edit Marker - + desc: 給地圖標記起一個的名字。 你可以在名字中加入一個短代碼以加入圖形。 (你可以在 here + 生成短代碼。) + titleEdit: 修改標記 markerDemoLimit: - desc: 在演示版中你只能創建兩個地圖標記。請獲取獨立版以創建更多標記。 + desc: 在演示版中你只能創建兩個地圖標記。請獲取單機版以創建更多標記。 massCutConfirm: title: 確認剪下 - desc: >- - 你將要剪下很多建築,準確來說有幢!你確定要這麼做嗎? - + desc: 你將要剪下很多建築,準確來說有幢!你確定要這麼做嗎? exportScreenshotWarning: title: 工廠截圖 - desc: >- - 你將要匯出你的工廠的截圖。如果你的基地很大,截圖過程將會很慢,甚至有可能導致遊戲當掉! - + desc: 你將要匯出你的工廠的截圖。如果你的基地很大,截圖過程將會很慢,甚至有可能導致遊戲當掉! massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? - + title: 確認剪下 + desc: 你的複製圖形不夠貼上!你確定要剪下嗎? + editSignal: + title: Set Signal + descItems: "Choose a pre-defined item:" + descShortKey: ... or enter the short key of a shape (Which you + can generate here) + renameSavegame: + title: 重新命名存檔 + desc: 你可以在這裡重新命名存檔 + tutorialVideoAvailable: + title: Tutorial Available + desc: There is a tutorial video available for this level! Would you like to + watch it? + tutorialVideoAvailableForeignLanguage: + title: Tutorial Available + desc: There is a tutorial video available for this level, but it is only + available in English. Would you like to watch it? ingame: - # This is shown in the top left corner and displays useful keybindings in - # every situation keybindingsOverlay: moveMap: 移動 selectBuildings: 選擇區域 @@ -321,19 +203,10 @@ ingame: copySelection: 複製選取 clearSelection: 清空選取 pipette: 吸附 - switchLayers: Switch layers - - # Everything related to placing buildings (I.e. as soon as you selected a building - # from the toolbar) + switchLayers: 切換層 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: 按鍵以選擇建築變體. - - # Shows the hotkey in the ui, e.g. "Hotkey: Q" - hotkeyLabel: >- - 快捷鍵: - + hotkeyLabel: "快捷鍵: " infoTexts: speed: 效率 range: 範圍 @@ -341,37 +214,21 @@ ingame: oneItemPerSecond: 1個/秒 itemsPerSecond: 個/秒 itemsPerSecondDouble: (2倍) - tiles: 格 - - # The notification when completing a level levelCompleteNotification: - # is replaced by the actual level, so this gets 'Level 03' for example. - levelTitle: Level + levelTitle: 第級 completed: 完成 unlockText: 解鎖! buttonNextLevel: 下一關 - - # Notifications on the lower right notifications: newUpgrade: 有新的更新啦! gameSaved: 遊戲已保存。 - - # The "Upgrades" window + freeplayLevelComplete: 已完成第級! shop: title: 建築升級 buttonUnlock: 升級 - - # Gets replaced to e.g. "Tier IX" tier: 級 - - # The roman number for each tier - # Chinese translation: Chinese characters for each tier - tierLabels: [壹, 貳, 叁, 肆, 伍, 陸, 柒, 捌, 玖, 拾] - maximumLevel: 最高級(倍效率) - - # The "Statistics" window statistics: title: 統計資訊 dataSources: @@ -385,51 +242,58 @@ ingame: title: 送達 description: 顯示圖形送達基地的速度。 noShapesProduced: 你還沒有生產任何圖形。 - - # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: 個/分鐘 - - # Settings menu, when you press "ESC" + shapesDisplayUnits: + second: / 秒 + minute: / 分 + hour: / 時 settingsMenu: playtime: 遊戲時間 - buildingsPlaced: 建築數量 beltsPlaced: 傳送帶數量 - - buttons: - continue: 繼續 - settings: 設置 - menu: 回到主選單 - - # Bottom left tutorial hints tutorialHints: title: 需要幫助? showHint: 顯示 hideHint: 關閉 - - # When placing a blueprint blueprintPlacer: cost: 需要 - - # Map markers waypoints: waypoints: 地圖標記 hub: 基地 - description: 滑鼠左鍵按標記跳轉到它,按右鍵將其刪除。

從當前視圖創建一個標記,或按右鍵創建一個標記。 所選位置的標記。 + description: 在標記上按左鍵以快速移動到標記區域,在標記上按右鍵以刪除該標記。

+ 為當前區域建立地圖標記或按 right-click 為選取區域建立地圖標記。 creationSuccessNotification: 成功創建地圖標記。 - - # Interactive tutorial interactiveTutorial: title: 教程 hints: 1_1_extractor: 在圓形礦脈上放一個開採機來獲取圓形! - 1_2_conveyor: >- - 用傳送帶將你的開採機連接到基地上!

提示:用你的游標按下並拖動傳送帶! - - 1_3_expand: >- - 這不是一個放置型遊戲!建造更多的開採機和傳送帶來更快地完成目標。

+ 1_2_conveyor: 用傳送帶將你的開採機連接到基地上! +

提示:用你的游標按下並拖動傳送帶! + 1_3_expand: 這不是一個放置型遊戲!建造更多的開採機和傳送帶來更快地完成目標。

提示:按住SHIFT鍵來放置多個開採機,用R鍵旋轉它們。 - + 2_1_place_cutter: "Now place a Cutter to cut the circles in two + halves!

PS: The cutter always cuts from top to + bottom regardless of its orientation." + 2_2_place_trash: The cutter can clog and stall!

Use a + trash to get rid of the currently (!) not + needed waste. + 2_3_more_cutters: "Good job! Now place 2 more cutters to speed + up this slow process!

PS: Use the 0-9 + hotkeys to access buildings faster!" + 3_1_rectangles: "Now let's extract some rectangles! Build 4 + extractors and connect them to the hub.

PS: + Hold SHIFT while dragging a belt to activate + the belt planner!" + 21_1_place_quad_painter: Place the quad painter and get some + circles, white and + red color! + 21_2_switch_to_wires: Switch to the wires layer by pressing + E!

Then connect all four + inputs of the painter with cables! + 21_3_place_button: Awesome! Now place a Switch and connect it + with wires! + 21_4_press_button: "Press the switch to make it emit a truthy + signal and thus activate the painter.

PS: You + don't have to connect all inputs! Try wiring only two." colors: red: 紅 green: 綠 @@ -444,8 +308,42 @@ ingame: title: 層 empty: 空 copyKey: Copy Key - -# All shop upgrades + connectedMiners: + one_miner: 1 個開採機 + n_miners: 個開採機 + limited_items: Limited to + watermark: + title: Demo version + desc: Click here to see the Steam version advantages! + get_on_steam: 在 Steam 上取得 + standaloneAdvantages: + title: 取得單機版! + no_thanks: 不用了,謝謝! + points: + levels: + title: 12 個新關卡 + desc: 總共26關! + buildings: + title: 18 個新建築 + desc: 邁向完全自動化! + savegames: + title: ∞ 個存檔 + desc: 隨心所欲! + upgrades: + title: 20 個等級 + desc: 試玩版只有 5 個。 + markers: + title: ∞ 個地圖標記 + desc: 再也不會迷失在一望無際的地圖裡! + wires: + title: 電路 + desc: 全新次元! + darkmode: + title: 深色模式 + desc: 要保養眼球~ + support: + title: 支持我 + desc: 遊戲使我利用閒暇時間做的! shopUpgrades: belt: name: 傳送帶、平衡機、隧道 @@ -459,287 +357,372 @@ shopUpgrades: painting: name: 混色、上色 description: 效率 倍 → 倍 - -# Buildings and their name / description buildings: belt: default: - name: &belt 傳送帶 + name: 傳送帶 description: 運送物品,按住並拖動來放置多個。 - - miner: # Internal name for the Extractor + miner: default: - name: &miner 開採機 + name: 開採機 description: 在圖形或者顏色上放置來開採他們。 - chainable: name: 鏈式開採機 description: 在圖形或者顏色上放置來開採他們。可以被鏈接在一起。 - - underground_belt: # Internal name for the Tunnel + underground_belt: default: - name: &underground_belt 隧道 + name: 隧道 description: 可以從其他傳送帶或建築底下方運送物品。 - tier2: name: 貳級隧道 description: 可以從其他傳送帶或建築底下方運送物品。 - - splitter: # Internal name for the Balancer - default: - name: &splitter 平衡機 - description: 多功能——將所有輸入平均分配到所有輸出。 - - compact: - name: 小型合流機 - description: 把兩個輸入合併到一個輸出上。 - - compact-inverse: - name: 小型合流機 (反轉) - description: 把兩個輸入合併到一個輸出上。 - cutter: default: - name: &cutter 切割機 + name: 切割機 description: 將圖形從上到下切開並輸出。 如果你只需要其中一半,記得把另一半銷毀掉,否則切割機會停止運作! quad: name: 切割機(四分) description: 將輸入的圖形切成四塊。 如果你只需要其中一塊,記得把其他的銷毀掉,否則切割機會停止運作! - rotater: default: - name: &rotater 旋轉機 + name: 旋轉機 description: 將圖形順時針旋轉90度。 ccw: name: 旋轉機(逆時針) description: 將圖形逆時針旋轉90度。 - + rotate180: + name: 旋轉機 (180度) + description: 將圖形旋轉180度。 stacker: default: - name: &stacker 混合機 + name: 混合機 description: 將輸入的圖形拼貼在一起。如果不能被直接拼貼,右邊的圖形會被疊在左邊的圖形上面. - mixer: default: - name: &mixer 混色機 + name: 混色機 description: 將兩個顏色加在一起。 - painter: default: - name: &painter 上色機 - description: &painter_desc 將整個圖形塗上輸入的顏色。 + name: 上色機 + description: 將整個圖形塗上輸入的顏色。 double: name: 上色機(雙倍) description: 同時為兩個輸入的圖形上色,每次上色只消耗一份顏色塗料。 quad: name: 上色機(四向) - description: 為圖形的四個角塗上不同的顏色。 + description: 分別為圖形的四個部分上色。 只有 truthy signal 的格子會被上色。 mirrored: - name: *painter - description: *painter_desc - + name: 上色機 + description: 將整個圖形塗上輸入的顏色。 trash: default: - name: &trash 垃圾桶 + name: 垃圾桶 description: 從所有四個方向上輸入物品並永遠銷毀它們。 - - storage: - name: 倉庫 - description: 儲存多餘的物品,有一定儲存上限。可以被用來作為溢流門。最多五千個。 hub: deliver: 交付 toUnlock: 來解鎖 levelShortcut: LVL + endOfDemo: 試玩結束 wire: default: - name: Energy Wire - description: Allows you to transport energy. - advanced_processor: + name: 能量電線 + description: 傳輸能量。 + second: + name: 電線 + description: 傳輸訊號,訊號可以是物件,顏色或布林值(0或1)。 不同顏色的電線無法互相連接。 + balancer: default: - name: Color Inverter - description: Accepts a color or shape and inverts it. - energy_generator: - deliver: Deliver - toGenerateEnergy: For - default: - name: Energy Generator - description: Generates energy by consuming shapes. - 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: 將兩個傳送帶整合成一個。 + merger-inverse: + name: 合流機(左) + description: 將兩個傳送帶整合成一個。 + splitter: + name: 分流機(右) + description: 將單個傳送帶分流成兩個。 + splitter-inverse: + name: 分流機(左) + description: 將單個傳送帶分流成兩個。 + storage: + default: + name: 倉庫 + description: 儲存多餘的物品,有一定儲存上限。優先從左側輸出,可以被用來作為溢流門。 + wire_tunnel: + default: + name: Wire Crossing + description: Allows to cross two wires without connecting them. + constant_signal: + default: + name: Constant Signal + description: Emits a constant signal, which can be either a shape, color or + boolean (1 / 0). + lever: + default: + name: 信號切換器 + description: Can be toggled to emit a boolean signal (1 / 0) on the wires layer, + which can then be used to control for example an item filter. + logic_gate: + default: + name: AND 邏輯閘 + description: 當輸入均為「真」時,輸出才為1。 (「真」值代表:形狀正確、顏色正確或布林值為1) + not: + name: NOT 邏輯閘 + description: 當輸入之ㄧ為「假」時,輸出才為1。 (「假」值代表:形狀不正確、顏色不正確或布林值為0) + xor: + name: XOR 邏輯閘 + description: 當輸入均為「假」時,輸出才為1。 (「假」值代表:形狀不正確、顏色不正確或布林值為0) + or: + name: OR 邏輯閘 + description: 當輸入之ㄧ為「真」時,輸出才為1。 (「真」值代表:形狀正確、顏色正確或布林值為1) + transistor: + default: + name: 電晶體 + description: 如果基極(側面)的輸入訊號為「真」,則把射極(底部)輸入的真假值複製到集極(頂部)的輸出。 + (「真」值代表:形狀正確、顏色正確或布林值為1) + mirrored: + name: 電晶體 + description: 如果基極(側面)的輸入訊號為「真」,則把射極(底部)輸入的真假值複製到集極(頂部)的輸出。 + (「真」值代表:形狀正確、顏色正確或布林值為1) + filter: + default: + name: Filter + description: Connect a signal to route all matching items to the top and the + remaining to the right. Can be controlled with boolean signals + too. + display: + default: + name: Display + description: Connect a signal to show it on the display - It can be a shape, + color or boolean. + reader: + default: + name: 傳送帶讀取機 + description: Allows to measure the average belt throughput. Outputs the last + read item on the wires layer (once unlocked). + analyzer: + default: + name: 形狀分析機 + description: Analyzes the top right quadrant of the lowest layer of the shape + and returns its shape and color. + comparator: + default: + name: 比較機 + description: Returns boolean "1" if both signals are exactly equal. Can compare + shapes, items and booleans. + virtual_processor: + default: + name: 虛擬切割機 + description: 虛擬地將圖形從上到下切開並輸出。 + rotater: + name: 虛擬旋轉機 + description: 虛擬地將圖形順時針或逆時針旋轉。 + unstacker: + name: 虛擬提取機 + description: 虛擬地提取最上層的圖形到右方輸出,剩下的圖形由左方輸出。 + stacker: + name: 虛擬堆疊機 + description: 虛擬地將輸入的圖形拼貼在一起。如果不能被直接拼貼,右邊的圖形會被疊在左邊的圖形上面。 + painter: + name: 虛擬上色機 + description: 虛擬地將整個圖形塗上輸入的顏色。 + item_producer: + default: + name: 物品製造機 + description: 沙盒模式專有,將電路層的輸入轉化成一般層的輸出。 storyRewards: - # Those are the rewards gained from completing the store reward_cutter_and_trash: title: 切割圖形 - desc: 切割機已解鎖。不論切割機的方向,它都會把圖形垂直地切成兩半。

記得把不需要的部分處理掉,否則這個這個建築會停止運作。為此我給你準備了垃圾桶,它會把所有放進去的物品銷毀掉。 - + desc: 切割機已解鎖。不論切割機的方向,它都會把圖形垂直地切成兩半。 +

記得把不需要的部分處理掉,否則這個這個建築會停止運作。 + 為此我給你準備了垃圾桶,它會把所有放進去的物品銷毀掉。 reward_rotater: title: 順時針旋轉 - desc: 旋轉機已解鎖。它會順時針旋轉輸入的圖形90度。 - + desc: 順時針旋轉機已解鎖。它會順時針旋轉輸入的圖形90度。 reward_painter: title: 上色 - desc: >- - 上色機已解鎖。開採一些顏色,用上色機把顏色和圖形混合,就可以為圖形著色。

備註:如果你是色盲,設置中有色盲模式可以選。 - + desc: 上色機已解鎖。開採一些顏色,用上色機把顏色和圖形混合,就可以為圖形著色。

備註:如果你是色盲,設置中有色盲模式可以選。 reward_mixer: title: 混色 desc: 混色器已解鎖-在此建築物中使用附加混合結合兩種顏色! - reward_stacker: title: 混合 desc: 混合機已解鎖。如果沒有重疊的部分,混合機會嘗試把兩個輸入的圖形拼貼在一起。如果有重疊的部分,右邊的輸入會被到左邊的輸入上方! - reward_splitter: - title: 分離/合併 - desc: 平衡機已解鎖。在大型工廠中,平衡機負責合併或分離多個傳送帶上的物品。

- + title: 分流 + desc: You have unlocked a splitter variant of the + balancer - It accepts one input and splits them + into two! reward_tunnel: title: 隧道 desc: 隧道已解鎖。你現在可以從其他傳送帶或建築底下運送物品了! - reward_rotater_ccw: title: 逆時針旋轉 - desc: 您已解鎖了旋轉器的變體-它可以逆時針旋轉! 要構建它,請選擇旋轉器,然後按“T”鍵切換其變種! - + desc: 逆時針旋轉機已解鎖。它會逆時針旋轉輸入的圖形90度。 + 逆時針旋轉機是順時針旋轉機的變體。選擇「順時針旋轉機」並按「T」來切換變體就能創建。 reward_miner_chainable: - title: 鏈式開採機 - desc: 鏈式開採機變體已解鎖。它是開採機的一個變體。它可以將開採出來的資源傳遞給其他的開採機,使得資源提取更加高效! - + title: 鏈式開採 + desc: "鏈式開採機變體已解鎖。它是開採機的一個變體。 + 它可以將開採出來的資源傳遞給其他的開採機,使得資源提取更加高效!

PS: + 工具列中舊的開採機已被取代。" reward_underground_belt_tier_2: title: 貳級隧道 desc: 貳級隧道變體已解鎖。這個隧道有更長的傳輸距離。你還可以混用不同的隧道變體! - - reward_splitter_compact: - title: 小型合流機 - desc: >- - 小型合流機變體已解鎖。它可以把兩個輸入合併到一個輸出上。 - reward_cutter_quad: - title: 四分切割機 - desc: 您已解鎖了四分切割機的變體-它允許您將形狀直接切割為四個部分,而不是兩個! - + title: 四分切割 + desc: 您已解鎖了切割機的變體:四分切割機。 + 它允許您將形狀直接切割為四個部分,而不是兩個! reward_painter_double: - title: 雙倍上色機 - desc: 您已經解鎖了雙倍上色機的變體-它可以作為常規畫家使用,但一次只能處理兩個形狀,而只消耗一種顏色而不是兩種顏色! - - reward_painter_quad: - title: 四向上色機 - desc: 上色機四向變體已解鎖。它可以在一個圖形的四個角上塗不同的顏色! - + title: 雙倍上色 + desc: 您已經解鎖了上色機的變體:雙倍上色機。 + 它的運作方式跟上色機類似,但一次能處理兩個形狀,而且只消耗一種顏色而不是兩種顏色! reward_storage: title: 倉庫 - desc: 倉庫變體已解鎖。它可以暫時儲存一些材料,有容量上限。 - + desc: 倉庫 已解鎖: + 可以儲存多餘的物品,有一定儲存上限。

優先從左側輸出,可以被用來作為溢流門。 reward_freeplay: title: 自由模式 - desc: 恭喜你!你解鎖了自由模式!現在圖形將會是隨機生成的! (不用擔心,我計劃在獨立版本中加入更多內容!) - + desc: 你做到了!你解鎖了自由模式!現在圖形將會是隨機生成的!

+ 從現在開始,基地會要求流量下限,因此我強烈建議你建造全自動化的生產線。

+ 基地會在電路層輸出他需要的形狀,你只需要分析這些訊號,然後依照需求自動調整你的工廠。 reward_blueprints: title: 藍圖 - desc: 現在,您可以複製並貼上工廠的各個部分! 選擇一個區域(按住CTRL,然後用游標拖動),然後按'C'將其複制。

複製不是免費的,您需要用藍圖 形狀來支付! (您剛交付的那些)。 - - # Special reward, which is shown when there is no reward actually + 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). no_reward: title: 下一關 - desc: >- - 這一關沒有獎勵,但是下一關有!

PS: 你生產過的所有圖形都會被用來升級建築。 - + desc: "這一關沒有獎勵,但是下一關有!

PS: + 你生產過的所有圖形都會被用來升級建築。" no_reward_freeplay: title: 下一關 - desc: >- - 恭喜你!另外,我們已經計劃在獨立版中加入更多內容! - + desc: 恭喜你!另外,我們已經計劃在單機版中加入更多內容! + reward_balancer: + title: 平衡物流 + desc: 平衡機已解鎖。在大型工廠中,平衡機負責合流或分流多個傳送帶上的物品。 + reward_merger: + title: 合流 + desc: You have unlocked a merger variant of the + balancer - It accepts two inputs and merges them + into one belt! + reward_belt_reader: + title: Belt reader + desc: You have now unlocked the belt reader! It allows you to + measure the throughput of a belt.

And wait until you unlock + wires - then it gets really useful! + reward_rotater_180: + title: Rotater (180 degrees) + desc: You just unlocked the 180 degress rotater! - It allows + you to rotate a shape by 180 degress (Surprise! :D) + reward_display: + title: Display + desc: "You have unlocked the Display - Connect a signal on the + wires layer to visualize it!

PS: Did you notice the belt + reader and storage output their last read item? Try showing it on a + display!" + reward_constant_signal: + title: Constant Signal + desc: You unlocked the constant signal building on the wires + layer! This is useful to connect it to item filters + for example.

The constant signal can emit a + shape, color or + boolean (1 / 0). + reward_logic_gates: + title: Logic Gates + desc: You unlocked logic gates! You don't have to be excited + about this, but it's actually super cool!

With those gates + you can now compute AND, OR, XOR and NOT operations.

As a + bonus on top I also just gave you a transistor! + reward_virtual_processing: + title: Virtual Processing + desc: I just gave a whole bunch of new buildings which allow you to + simulate the processing of shapes!

You can + now simulate a cutter, rotater, stacker and more on the wires layer! + With this you now have three options to continue the game:

- + Build an automated machine to create any possible + shape requested by the HUB (I recommend to try it!).

- Build + something cool with wires.

- Continue to play + regulary.

Whatever you choose, remember to have fun! + reward_wires_painter_and_levers: + title: Wires & Quad Painter + desc: "You just unlocked the Wires Layer: It is a separate + layer on top of the regular layer and introduces a lot of new + mechanics!

For the beginning I unlocked you the Quad + Painter - Connect the slots you would like to paint with on + the wires layer!

To switch to the wires layer, press + E.

PS: Enable hints in + the settings to activate the wires tutorial!" + reward_filter: + title: Item Filter + desc: You unlocked the Item Filter! It will route items either + to the top or the right output depending on whether they match the + signal from the wires layer or not.

You can also pass in a + boolean signal (1 / 0) to entirely activate or disable it. + reward_demo_end: + title: End of Demo + desc: You have reached the end of the demo version! settings: title: 設置 categories: - game: 遊戲內容 - app: 應用 - + general: General + userInterface: User Interface + advanced: Advanced + performance: Performance versionBadges: - dev: 開發版本 # Development - staging: 預覽版本 # Staging - prod: 正式版本 # Production + dev: 開發版本 + staging: 預覽版本 + prod: 正式版本 buildDate: 於創建 - labels: uiScale: title: 用戶界面大小 - description: >- - 改變用戶界面大小。用戶界面會隨著設備分辨率縮放,這個設置決定縮放比例。 + description: 改變用戶界面大小。用戶界面會隨著設備分辨率縮放,這個設置決定縮放比例。 scales: super_small: 最小 small: 較小 regular: 正常 large: 較大 huge: 最大 - scrollWheelSensitivity: title: 縮放靈敏度 - description: >- - 改變縮放靈敏度(鼠標滾輪或者觸控板)。 + description: 改變縮放靈敏度(鼠標滾輪或者觸控板)。 sensitivity: super_slow: 最低 slow: 較低 regular: 正常 fast: 較高 super_fast: 最高 - language: title: 語言 - description: >- - 改變語言。所有的翻譯皆由玩家提供,且有可能正在施工中! - + description: 改變語言。所有的翻譯皆由玩家提供,且有可能正在施工中! fullscreen: title: 全螢幕 - description: >- - 全螢幕以獲得更好的遊戲體驗。僅在獨立版中可用。 - + description: 全螢幕以獲得更好的遊戲體驗。僅在單機版中可用。 soundsMuted: title: 關閉音效 - description: >- - 關閉所有音效。 - + description: 關閉所有音效。 musicMuted: title: 關閉音樂 - description: >- - 關閉所有音樂。 - + description: 關閉所有音樂。 theme: title: 界面主題 - description: >- - 選擇界面主題(深色或淺色)。 - + description: 選擇界面主題(深色或淺色)。 themes: dark: 深色 light: 淺色 - refreshRate: title: 模擬頻率、刷新頻率 - description: >- - 如果你的顯示器是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. - + description: 如果你的顯示器是144hz的,請在這裡更改刷新頻率,這樣遊戲可以正確地根據你的螢幕進行模擬。但是如果你的電腦性能不佳,提高刷新頻率可能降低幀數。 alwaysMultiplace: title: 多重放置 - description: >- - 開啟這個選項之後放下建築將不會取消建築選擇。等同於一直按下SHIFT鍵。 - # description: >- - # If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. - + description: 開啟這個選項之後放下建築將不會取消建築選擇。等同於一直按下SHIFT鍵。 offerHints: title: 提示與教程 - description: >- - 是否顯示提示、教程以及一些其他的幫助理解遊戲的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. - + description: 是否顯示提示、教程以及一些其他的幫助理解遊戲的UI元素。 movementSpeed: title: 移動速度 description: 改變攝像頭移動速度 @@ -750,21 +733,15 @@ settings: fast: 較快 super_fast: 非常快 extremely_fast: 最快 - enableTunnelSmartplace: title: 智能隧道放置 - description: >- - 啟用後,放置隧道時會將多餘的傳送帶移除。 - 此外,拖動隧道可以快速鋪設隧道,以及移除不必要的隧道。 + description: 啟用後,放置隧道時會將多餘的傳送帶移除。 此外,拖動隧道可以快速鋪設隧道,以及移除不必要的隧道。 vignette: title: 暈映 - description: >- - 啟用暈映,將屏幕角落裡的顏色變深,更容易閱讀文字。 - + description: 啟用暈映,將屏幕角落裡的顏色變深,更容易閱讀文字。 autosaveInterval: title: 自動刷新時間 - description: >- - 控制遊戲自動刷新的頻率。 您也可以禁用它。 + description: 控制遊戲自動刷新的頻率。 您也可以禁用它。 intervals: one_minute: 1分鐘 two_minutes: 2分鐘 @@ -774,31 +751,73 @@ settings: disabled: 停用 compactBuildingInfo: title: 省略建築信息 - description: >- + description: |- 通過顯示建築物的比率來縮短建築物的資訊框。 否則 顯示所有說明+圖像。 disableCutDeleteWarnings: title: 停用剪下/刪除的警告 - description: >- - 剪下/刪除超過100幢建築物時不顯示警告。 - + description: 剪下/刪除超過100幢建築物時不顯示警告。 enableColorBlindHelper: title: 色盲模式 description: 如果您是色盲者,啟用了這設定,就可以玩遊戲了。 - rotationByBuilding: title: 依建築類型旋轉 - description: >- - 每個建築類型,將會分別記住您最後一次使用的旋轉方向。 - 如果您常常切換不同類型的建築,這樣可能會更方便。 - + description: 每個建築類型,將會分別記住您最後一次使用的旋轉方向。 如果您常常切換不同類型的建築,這樣可能會更方便。 + soundVolume: + title: 音效 + description: 音效設定 + musicVolume: + title: 音樂 + description: 音樂設定 + 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. + simplifiedBelts: + title: Simplified Belts (Ugly) + description: Does not render belt items except when hovering the belt to save + performance. I do not recommend to play with this setting if you + do not absolutely need the performance. + enableMousePan: + title: Enable Mouse Pan + description: Allows to move the map by moving the cursor to the edges of the + screen. The speed depends on the Movement Speed setting. + zoomToCursor: + title: Zoom towards Cursor + description: If activated the zoom will happen in the direction of your mouse + position, otherwise in the middle of the screen. + mapResourcesScale: + title: Map Resources Size + description: Controls the size of the shapes on the map overview (when zooming + out). + rangeSliderPercentage: % keybindings: title: 按鍵設置 - hint: >- - 提示:使用CTRL、SHIFT、ALT! 這些建在放置建築時有不同的效果。 - + hint: 提示:使用CTRL、SHIFT、ALT! 這些建在放置建築時有不同的效果。 resetKeybindings: 重置按鍵設置 - categoryLabels: general: 通用 ingame: 遊戲 @@ -807,7 +826,6 @@ keybindings: massSelect: 批量選擇 buildings: 建築快捷鍵 placementModifiers: 放置建築修飾鍵 - mappings: confirm: 確認 back: 返回 @@ -816,37 +834,30 @@ keybindings: mapMoveDown: 下 mapMoveLeft: 左 centerMap: 回到基地 - mapZoomIn: 放大 mapZoomOut: 縮小 createMarker: 創建地圖標記 - menuOpenShop: 升級選單 menuOpenStats: 統計選單 - toggleHud: 開關HUD toggleFPSInfo: 開關幀數與調試信息 - belt: *belt - splitter: *splitter - underground_belt: *underground_belt - miner: *miner - cutter: *cutter - rotater: *rotater - stacker: *stacker - mixer: *mixer - painter: *painter - trash: *trash - + belt: 傳送帶 + underground_belt: 隧道 + miner: 開採機 + cutter: 切割機 + rotater: 旋轉機 + stacker: 混合機 + mixer: 混色機 + painter: 上色機 + trash: 垃圾桶 rotateWhilePlacing: 順時針旋轉 - rotateInverseModifier: >- - 修飾鍵: 改為逆時針旋轉 + rotateInverseModifier: "修飾鍵: 改為逆時針旋轉" cycleBuildingVariants: 選擇建築變體 confirmMassDelete: 確認批量刪除 cycleBuildings: 選擇建築 massSelectStart: 開始批量選擇 massSelectSelectMultiple: 選擇多個區域 massSelectCopy: 複製 - placementDisableAutoOrientation: 取消自動定向 placeMultiple: 繼續放置 placeInverse: 反向放置傳送帶 @@ -854,44 +865,104 @@ keybindings: massSelectCut: 剪切 exportScreenshot: 匯出截圖 mapMoveFaster: 快速移動 - lockBeltDirection: 啟用傳送帶規劃 - switchDirectionLockSide: "規劃器:換邊" + switchDirectionLockSide: 規劃器:換邊 pipette: Pipette menuClose: Close Menu - switchLayers: Switch layers - advanced_processor: Color Inverter - energy_generator: Energy Generator - wire: Energy Wire - + switchLayers: 更換層 + wire: 電線 + balancer: 平衡機 + storage: Storage + constant_signal: Constant Signal + logic_gate: 邏輯閘 + lever: Switch (regular) + filter: Filter + wire_tunnel: Wire Crossing + display: Display + reader: Belt Reader + virtual_processor: Virtual Cutter + transistor: Transistor + analyzer: 形狀分析機 + comparator: 比對機 + item_producer: 物品生產機(沙盒模式) + copyWireValue: "Wires: Copy value below cursor" about: title: 關於遊戲 - # title: About this Game body: >- - 本遊戲由Tobias Springer(我)開發,並且已經開源。

+ 本遊戲由Tobias + Springer(我)開發,並且已經開源。

- 如果你想參與開發,請查看shapez.io on github

+ 如果你想參與開發,請查看shapez.io on github

- 這個遊戲的開發少不了熱情的Discord社區。請加入我們的Discord 服務器

+ 這個遊戲的開發少不了熱情的 Discord 社區。請加入我們的Discord 伺服器

- 本遊戲的音樂由Peppsen製作——他是個很棒的伙伴。

- - 最後,我想感謝我最好的朋友Niklas——如果沒有與他的異星工廠(factorio)的遊戲體驗,shapez.io將不會存在。 + 本遊戲的音樂由Peppsen製作——他是個很棒的伙伴。

+ 最後,我想感謝我最好的朋友Niklas——如果沒有與他的異星工廠(factorio)的遊戲體驗,shapez.io將不會存在。 changelog: title: 版本日誌 - demo: features: - restoringGames: 恢復存檔 #中? - importingGames: 匯入存檔 #中? + restoringGames: 恢復存檔 + importingGames: 匯入存檔 oneGameLimit: 最多一個存檔 customizeKeybindings: 按鍵設置 - # customizeKeybindings: Customizing Keybindings exportingBase: 匯出工廠截圖 settingNotAvailable: 在演示版中不可用。 +tips: + - 基地接受任何輸入,不只是當前要求的圖形! + - 盡量讓工廠模組化,會有回報的! + - 建築不要距離基地太近,否則容易混亂! + - 如果堆疊不如預期,嘗試將輸入端互換。 + - 輸送帶的方向可以按 R 更換。 + - 按住 CTRL 來防止輸送帶自動轉向。 + - 同等級的生產比例會是一樣的。 + - 串聯比並聯更有效率。 + - 遊戲後期可以解鎖更多建築變體! + - 玩家可以按 T 來選擇不同變體。 + - 對稱是關鍵! + - 不同等級的隧道可以相互交織。 + - 盡量讓工廠保持緊密,會有回報的! + - 上色機有對稱的變體。按 T 來選擇不同變體。 + - 正確的建築比例可以將效率最大化。 + - 最高級時,五個開採機可填滿一個輸送帶。 + - 別忘記使用隧道! + - 最高效率不一定來自均勻切割。 + - 按住 SHIFT 輕鬆規劃長距離輸送帶。 + - 不論擺放方向,切割機永遠做垂直切割。 + - 白 = 紅 + 綠 + 藍。 + - 倉庫優先從左側輸出。 + - 花點時間研究可以重複利用的設計,會有回報的! + - 按住 CTRL 可以一次放置多個建築。 + - 按住 ALT 以反轉輸送帶的放置方向。 + - 效率是關鍵! + - 離基地越遠得圖形叢越複雜。 + - 機器的運作速度有上限,多放幾個增加生產效率。 + - 用平衡機讓效率最大化。 + - 規劃很重要,盡量別讓輸送帶錯綜複雜。 + - 預先規劃,不然會混亂不堪! + - 不要刪除舊的工廠,解鎖更新能會需要它們。 + - 先試著靠自己破第20關再去尋求幫助。 + - 不要讓東西複雜化,保持簡單則行的遠。 + - 遊戲中有時需要重複利用工廠,設計時記得考量重複利用性。 + - 有些圖形地圖上就找的到,不必自行堆疊。 + - 地圖永遠部會自然生成完整的風車圖形。 + - 先上色再切割會比較有效率。 + - 有了模組,空間淪為假議題、凡夫俗子的憂思。 + - 創建一個藍圖工廠,這對模組化很有幫助。 + - 靠近一點看混色機,你會找到解答。 + - 按 CTRL + 點選想選取的區域。 + - 離基地太近的建築可能在未來會礙事。 + - 更新目錄的每個圖形旁都有圖釘,點選即可把圖形釘在螢幕上(目標圖形旁)。 + - 混合所有基本色就會得到白色! + - 地圖是無限延展的,別執著,擴張吧! + - Factorio 是我最喜歡的遊戲,非常推薦! + - 四分切割機從右上角順時鐘地輸出圖形的四個區塊。 + - 你可以從主畫面下載存檔。 + - 去設定頁看看,有很多有用的按鍵組合! + - 有很多東西都可以設定,有空的話去設定頁看看。 + - 看不見基地時,基地的標示左側有個小指南針會提醒你它的方位。 + - 清除輸送帶有個方法:複製它再原地貼上。 + - 按 F4 來顯示螢幕的幀數(FPS)與刷新率(Tick Rate)。 + - 按 F4 兩次來顯示相機和游標的絕對位置。 + - 在已標記的圖形上按左鍵去除標記。 diff --git a/version b/version index 867e5243..cb174d58 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.2.0 \ No newline at end of file +1.2.1 \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index b00004a0..da9d4625 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,9895 +1,8765 @@ -# 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" + +"@octokit/auth-token@^2.4.0": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.2.tgz#10d0ae979b100fa6b72fa0e8e63e27e6d0dbff8a" + integrity sha512-jE/lE/IKIz2v1+/P0u4fJqv0kYwXOTujKemJMFr6FeopsxlIK3+wKDCJGnysg81XID5TgZQbIfuJ5J0lnTiuyQ== + dependencies: + "@octokit/types" "^5.0.0" + +"@octokit/core@^3.0.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.1.2.tgz#c937d5f9621b764573068fcd2e5defcc872fd9cc" + integrity sha512-AInOFULmwOa7+NFi9F8DlDkm5qtZVmDQayi7TUgChE3yeIGPq0Y+6cAEXPexQ3Ea+uZy66hKEazR7DJyU+4wfw== + dependencies: + "@octokit/auth-token" "^2.4.0" + "@octokit/graphql" "^4.3.1" + "@octokit/request" "^5.4.0" + "@octokit/types" "^5.0.0" + before-after-hook "^2.1.0" + universal-user-agent "^6.0.0" + +"@octokit/endpoint@^6.0.1": + version "6.0.6" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.6.tgz#4f09f2b468976b444742a1d5069f6fa45826d999" + integrity sha512-7Cc8olaCoL/mtquB7j/HTbPM+sY6Ebr4k2X2y4JoXpVKQ7r5xB4iGQE0IoO58wIPsUk4AzoT65AMEpymSbWTgQ== + dependencies: + "@octokit/types" "^5.0.0" + is-plain-object "^5.0.0" + universal-user-agent "^6.0.0" + +"@octokit/graphql@^4.3.1": + version "4.5.6" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.5.6.tgz#708143ba15cf7c1879ed6188266e7f270be805d4" + integrity sha512-Rry+unqKTa3svswT2ZAuqenpLrzJd+JTv89LTeVa5UM/5OX8o4KTkPL7/1ABq4f/ZkELb0XEK/2IEoYwykcLXg== + dependencies: + "@octokit/request" "^5.3.0" + "@octokit/types" "^5.0.0" + universal-user-agent "^6.0.0" + +"@octokit/plugin-paginate-rest@^2.2.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.4.0.tgz#92f951ddc8a1cd505353fa07650752ca25ed7e93" + integrity sha512-YT6Klz3LLH6/nNgi0pheJnUmTFW4kVnxGft+v8Itc41IIcjl7y1C8TatmKQBbCSuTSNFXO5pCENnqg6sjwpJhg== + dependencies: + "@octokit/types" "^5.5.0" + +"@octokit/plugin-request-log@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz#eef87a431300f6148c39a7f75f8cfeb218b2547e" + integrity sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw== + +"@octokit/plugin-rest-endpoint-methods@4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.2.0.tgz#c5a0691b3aba5d8b4ef5dffd6af3649608f167ba" + integrity sha512-1/qn1q1C1hGz6W/iEDm9DoyNoG/xdFDt78E3eZ5hHeUfJTLJgyAMdj9chL/cNBHjcjd+FH5aO1x0VCqR2RE0mw== + dependencies: + "@octokit/types" "^5.5.0" + deprecation "^2.3.1" + +"@octokit/request-error@^2.0.0": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.2.tgz#0e76b83f5d8fdda1db99027ea5f617c2e6ba9ed0" + integrity sha512-2BrmnvVSV1MXQvEkrb9zwzP0wXFNbPJij922kYBTLIlIafukrGOb+ABBT2+c6wZiuyWDH1K1zmjGQ0toN/wMWw== + dependencies: + "@octokit/types" "^5.0.1" + deprecation "^2.0.0" + once "^1.4.0" + +"@octokit/request@^5.3.0", "@octokit/request@^5.4.0": + version "5.4.9" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.9.tgz#0a46f11b82351b3416d3157261ad9b1558c43365" + integrity sha512-CzwVvRyimIM1h2n9pLVYfTDmX9m+KHSgCpqPsY8F1NdEK8IaWqXhSBXsdjOBFZSpEcxNEeg4p0UO9cQ8EnOCLA== + dependencies: + "@octokit/endpoint" "^6.0.1" + "@octokit/request-error" "^2.0.0" + "@octokit/types" "^5.0.0" + deprecation "^2.0.0" + is-plain-object "^5.0.0" + node-fetch "^2.6.1" + once "^1.4.0" + universal-user-agent "^6.0.0" + +"@octokit/rest@^18.0.6": + version "18.0.6" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.0.6.tgz#76c274f1a68f40741a131768ef483f041e7b98b6" + integrity sha512-ES4lZBKPJMX/yUoQjAZiyFjei9pJ4lTTfb9k7OtYoUzKPDLl/M8jiHqt6qeSauyU4eZGLw0sgP1WiQl9FYeM5w== + dependencies: + "@octokit/core" "^3.0.0" + "@octokit/plugin-paginate-rest" "^2.2.0" + "@octokit/plugin-request-log" "^1.0.0" + "@octokit/plugin-rest-endpoint-methods" "4.2.0" + +"@octokit/types@^5.0.0", "@octokit/types@^5.0.1", "@octokit/types@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b" + integrity sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ== + dependencies: + "@types/node" ">= 8" + +"@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/node@>= 8": + version "14.11.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.2.tgz#2de1ed6670439387da1c9f549a2ade2b0a799256" + integrity sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA== + +"@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" + +before-after-hook@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635" + integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A== + +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= + +deprecation@^2.0.0, deprecation@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" + integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== + +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-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + +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-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +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" + +universal-user-agent@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" + integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== + +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"