1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-12-13 18:21:51 +00:00

Merge pull request #2 from tobspr/master

a
This commit is contained in:
mse-k 2020-05-27 17:23:12 -04:00 committed by GitHub
commit 6ab95c5d02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
66 changed files with 1887 additions and 350 deletions

11
.eslintignore Normal file
View File

@ -0,0 +1,11 @@
artwork/*
build/*
electron/*
gulp/*
node_modules/*
res/*
res_built/*
res_raw/*
tmp_standalone_files/*
tools/*
translations/*

25
.eslintrc.yml Normal file
View File

@ -0,0 +1,25 @@
env:
browser: true
es6: true
extends:
- 'eslint:recommended'
- 'plugin:@typescript-eslint/eslint-recommended'
- 'prettier'
globals:
Atomics: readonly
SharedArrayBuffer: readonly
parser: '@typescript-eslint/parser'
parserOptions:
ecmaVersion: 6
sourceType: 'module'
ecmaFeatures:
- modules: true
plugins:
- '@typescript-eslint'
- 'prettier'
rules:
prettier/prettier: error
no-undef: off
no-unused-vars: off
no-prototype-builtins: off

42
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,42 @@
name: CI
on:
push:
branches:
- master
- ModdedGamers-GH-Actions
pull_request:
branches:
- master
jobs:
setup:
name: CI
runs-on: ubuntu-latest
steps:
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install ffmpeg
- name: Setup Node
uses: actions/setup-node@v2-beta
with:
node-version: 10.x
- name: Checkout repo
uses: actions/checkout@v2
- name: Install Yarn Dependencies
run: |
yarn
cd gulp/
yarn
cd ..
- name: Lint
run: |
npx eslint src/js

View File

@ -12,6 +12,8 @@ You can already play it [here](https://shapez.io).
## 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 Yarn and Node.js 10
- Run `yarn` in the root folder, then run `yarn` in the `gulp/` folder

View File

@ -142,6 +142,11 @@ function gulptasksStandalone($, gulp, buildFolder) {
return;
}
fs.writeFileSync(
path.join(appPath, "LICENSE"),
fs.readFileSync(path.join(__dirname, "..", "LICENSE"))
);
const playablePath = appPath + "_playable";
fse.copySync(appPath, playablePath);
fs.writeFileSync(path.join(playablePath, "steam_appid.txt"), "1134480");
@ -174,8 +179,8 @@ function gulptasksStandalone($, gulp, buildFolder) {
"standalone.package.prod",
$.sequence("standalone.prepare", [
"standalone.package.prod.win64",
// "standalone.package.prod.win32",
// "standalone.package.prod.linux64",
// "standalone.package.prod.win32",
// "standalone.package.prod.linux32",
// "standalone.package.prod.darwin64"
])

View File

@ -29,7 +29,7 @@
"core-js": "3",
"cssnano-preset-advanced": "^4.0.7",
"email-validator": "^2.0.4",
"eslint": "^5.9.0",
"eslint": "7.1.0",
"fastdom": "^1.0.8",
"flatted": "^2.0.1",
"howler": "^2.1.2",
@ -47,6 +47,7 @@
"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",
@ -59,12 +60,16 @@
"worker-loader": "^2.0.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",

View File

@ -8,6 +8,7 @@
"files.exclude": {
"**/build": true,
"**/node_modules": true,
"**/tmp_standalone_files": true,
"**/typedefs_gen": true
},
"vetur.format.defaultFormatter.js": "vscode-typescript",

View File

@ -4,7 +4,6 @@
left: 50%;
transform: translateX(-50%);
$toolbarBg: rgba($accentColorBright, 0.9);
display: flex;
flex-direction: column;
background-color: rgb(255, 255, 255);
@ -12,8 +11,7 @@
border-bottom-width: 0;
transition: transform 0.12s ease-in-out;
background: uiResource("toolbar_bg.lossless.png") center center / 100% 100% no-repeat;
@include S(padding, 20px, 100px, 0);
background: rgba(mix(#ddd, $colorBlueBright, 80%), 0.89);
&:not(.visible) {
transform: translateX(-50%) translateY(#{D(100px)});
@ -59,7 +57,7 @@
@include S(border-radius, $globalBorderRadius);
&.selected {
background-color: rgba($colorBlueBright, 0.3) !important;
background-color: rgba($colorBlueBright, 0.6) !important;
transform: scale(1.05);
.keybinding {
color: #111;

View File

@ -17,11 +17,10 @@
}
.changes {
@include SuperSmallText;
@include PlainText;
@include S(padding-left, 20px);
strong {
background: $colorBlueBright;
color: #fff;
color: #aaa;
text-transform: uppercase;
@include S(padding, 1px, 2px);
@include S(margin-right, 3px);

View File

@ -27,7 +27,7 @@
}
.changes {
@include SuperSmallText;
@include PlainText;
@include S(padding-left, 15px);
strong {
background: $colorBlueBright;

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>shapez.io - Build your own shape factory!</title>
<title>shapez.io - Build automated factories to build, combine and color shapes!</title>
<!-- mobile stuff -->
<meta name="format-detection" content="telephone=no" />

View File

@ -1,43 +1,41 @@
import { AnimationFrame } from "./core/animation_frame";
import { performanceNow, Math_min } from "./core/builtins";
import { BackgroundResourcesLoader } from "./core/background_resources_loader";
import { performanceNow } from "./core/builtins";
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 { SavegameManager } from "./savegame/savegame_manager";
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 { ShapezGameAnalytics } from "./platform/browser/game_analytics";
import { GoogleAnalyticsImpl } from "./platform/browser/google_analytics";
import { SoundImplBrowser } from "./platform/browser/sound";
import { StorageImplBrowser } from "./platform/browser/storage";
import { StorageImplBrowserIndexedDB } from "./platform/browser/storage_indexed_db";
import { PlatformWrapperImplBrowser } from "./platform/browser/wrapper";
import { StorageImplElectron } from "./platform/electron/storage";
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 { Vector } from "./core/vector";
import { createLogger, logSection } from "./core/logging";
import { TrackedState } from "./core/tracked_state";
import { IS_MOBILE } from "./core/config";
import { BackgroundResourcesLoader } from "./core/background_resources_loader";
import { PreloadState } from "./states/preload";
import { MainMenuState } from "./states/main_menu";
import { InGameState } from "./states/ingame";
import { AnalyticsInterface } from "./platform/analytics";
import { GoogleAnalyticsImpl } from "./platform/browser/google_analytics";
import { Loader } from "./core/loader";
import { GameAnalyticsInterface } from "./platform/game_analytics";
import { ShapezGameAnalytics } from "./platform/browser/game_analytics";
import { queryParamOptions } from "./core/query_parameters";
import { NoGameAnalytics } from "./platform/browser/no_game_analytics";
import { StorageImplBrowserIndexedDB } from "./platform/browser/storage_indexed_db";
import { SettingsState } from "./states/settings";
import { KeybindingsState } from "./states/keybindings";
import { SavegameManager } from "./savegame/savegame_manager";
import { AboutState } from "./states/about";
import { PlatformWrapperImplElectron } from "./platform/electron/wrapper";
import { StorageImplElectron } from "./platform/electron/storage";
import { MobileWarningState } from "./states/mobile_warning";
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";
const logger = createLogger("application");

View File

@ -1,17 +1,32 @@
export const CHANGELOG = [
{
version: "1.0.4",
version: "1.1.0",
date: "unreleased",
entries: [
"<strong>Balancing</strong> Reduce cost of first painting upgrade, and change 'Shape Processing' to 'Cutting, Rotating & Stacking'",
"<strong>Tutorial</strong> Add dialog after completing level 2 to check out the upgrades tab.",
"BLUEPRINTS!",
"Allow holding SHIFT to rotate counter clockwise",
"Allow changing all keybindings, including CTRL, ALT and SHIFT (by Dimava)",
"Added confirmation when deleting more than 500 buildings at a time",
"Added background to toolbar to increase contrast",
"Allow placing extractors anywhere again, but they don't work at all if not placed on a resource",
"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: [
"<strong>Balancing</strong> Reduced the amount of shapes required for the first 5 levels to make it easier to get into the game.",
"Reduced the amount of shapes required for the first 5 levels to make it easier to get into the game.",
],
},
{

View File

@ -40,7 +40,7 @@ export const globalConfig = {
// Map
mapChunkSize: 16,
mapChunkPrerenderMinZoom: 1.3,
mapChunkPrerenderMinZoom: 1.15,
mapChunkOverviewMinZoom: 0.7,
// Belt speeds
@ -93,8 +93,8 @@ export const globalConfig = {
// disableZoomLimits: true,
// showChunkBorders: true,
// rewardsInstant: true,
// allBuildingsUnlocked: true,
upgradesNoCost: true,
allBuildingsUnlocked: true,
// upgradesNoCost: true,
// disableUnlockDialog: true,
// disableLogicTicks: true,
// testClipping: true,
@ -102,7 +102,9 @@ export const globalConfig = {
// testTranslations: true,
// enableEntityInspector: true,
// testAds: true,
disableMapOverview: true,
// disableMapOverview: true,
disableTutorialHints: true,
disableUpgradeNotification: true,
/* dev:end */
},

View File

@ -23,10 +23,6 @@ export class InputDistributor {
/** @type {Array<function(any) : boolean>} */
this.filters = [];
this.shiftIsDown = false;
this.altIsDown = false;
this.ctrlIsDown = false;
this.bindToEvents();
}
@ -176,27 +172,13 @@ export class InputDistributor {
* Handles when the page got blurred
*/
handleBlur() {
this.ctrlIsDown = false;
this.shiftIsDown = false;
this.altIsDown = false;
this.forwardToReceiver("pageBlur", {});
this.forwardToReceiver("shiftUp", {});
}
/**
* @param {KeyboardEvent} event
*/
handleKeydown(event) {
if (event.keyCode === 16) {
this.shiftIsDown = true;
}
if (event.keyCode === 17) {
this.ctrlIsDown = true;
}
if (event.keyCode === 18) {
this.altIsDown = true;
}
if (
// TAB
event.keyCode === 9 ||
@ -230,19 +212,6 @@ export class InputDistributor {
* @param {KeyboardEvent} event
*/
handleKeyup(event) {
if (event.keyCode === 16) {
this.shiftIsDown = false;
this.forwardToReceiver("shiftUp", {});
}
if (event.keyCode === 17) {
this.ctrlIsDown = false;
this.forwardToReceiver("ctrlUp", {});
}
if (event.keyCode === 18) {
this.altIsDown = false;
this.forwardToReceiver("altUp", {});
}
this.forwardToReceiver("keyup", {
keyCode: event.keyCode,
shift: event.shiftKey,

View File

@ -9,9 +9,6 @@ export class InputReceiver {
this.keydown = new Signal();
this.keyup = new Signal();
this.pageBlur = new Signal();
this.shiftUp = new Signal();
this.altUp = new Signal();
this.ctrlUp = new Signal();
// Dispatched on destroy
this.destroyed = new Signal();

View File

@ -131,21 +131,21 @@ export class ReadWriteProxy {
}
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.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);
}
}
// 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)

View File

@ -103,6 +103,17 @@ export class Vector {
return new Vector(this.x - other.x, this.y - other.y);
}
/**
* Subs a vector
* @param {Vector} other
* @returns {Vector}
*/
subInplace(other) {
this.x -= other.x;
this.y -= other.y;
return this;
}
/**
* Multiplies with a vector and return a new vector
* @param {Vector} other

View File

@ -24,6 +24,10 @@ export class MetaHubBuilding extends MetaBuilding {
return false;
}
getBlueprintSprite() {
return null;
}
/**
* Creates the entity at the given location
* @param {Entity} entity

View File

@ -41,23 +41,6 @@ export class MetaMinerBuilding extends MetaBuilding {
return super.getAvailableVariants(root);
}
/**
* @param {GameRoot} root
* @param {object} param0
* @param {Vector} param0.origin
* @param {number} param0.rotation
* @param {number} param0.rotationVariant
* @param {string} param0.variant
*/
performAdditionalPlacementChecks(root, { origin, rotation, rotationVariant, variant }) {
// Make sure its placed above a resource
const lowerLayer = root.map.getLowerLayerContentXY(origin.x, origin.y);
if (!lowerLayer) {
return false;
}
return true;
}
/**
* Creates the entity at the given location
* @param {Entity} entity

View File

@ -10,14 +10,13 @@ import {
import { clickDetectorGlobals } from "../core/click_detector";
import { globalConfig } from "../core/config";
import { createLogger } from "../core/logging";
import { queryParamOptions } from "../core/query_parameters";
import { Rectangle } from "../core/rectangle";
import { Signal, STOP_PROPAGATION } from "../core/signal";
import { clamp } from "../core/utils";
import { mixVector, Vector } from "../core/vector";
import { BasicSerializableObject, types } from "../savegame/serialization";
import { GameRoot } from "./root";
import { KEYMAPPINGS } from "./key_action_mapper";
import { GameRoot } from "./root";
const logger = createLogger("camera");

View File

@ -17,6 +17,14 @@ export class Component extends BasicSerializableObject {
return {};
}
/**
* Should duplicate the component but without its contents
* @returns {object}
*/
duplicateWithoutContents() {
abstract;
}
/* dev:start */
/**

View File

@ -18,6 +18,10 @@ export class BeltComponent extends Component {
};
}
duplicateWithoutContents() {
return new BeltComponent({ direction: this.direction });
}
/**
*
* @param {object} param0

View File

@ -54,6 +54,32 @@ export class ItemAcceptorComponent extends Component {
};
}
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(),
});
}
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,
});
}
return new ItemAcceptorComponent({
slots: slotsCopy,
beltUnderlays: beltUnderlaysCopy,
animated: this.animated,
});
}
/**
*
* @param {object} param0

View File

@ -32,6 +32,22 @@ export class ItemEjectorComponent extends Component {
};
}
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,
});
}
return new ItemEjectorComponent({
slots: slotsCopy,
instantEject: false,
});
}
/**
*
* @param {object} param0

View File

@ -48,6 +48,13 @@ export class ItemProcessorComponent extends Component {
};
}
duplicateWithoutContents() {
return new ItemProcessorComponent({
processorType: this.type,
inputsPerCharge: this.inputsPerCharge,
});
}
/**
*
* @param {object} param0

View File

@ -19,6 +19,12 @@ export class MinerComponent extends Component {
};
}
duplicateWithoutContents() {
return new MinerComponent({
chainable: this.chainable,
});
}
/**
*/
constructor({ chainable = false }) {

View File

@ -8,4 +8,8 @@ export class ReplaceableMapEntityComponent extends Component {
static getId() {
return "ReplaceableMapEntity";
}
duplicateWithoutContents() {
return new ReplaceableMapEntityComponent();
}
}

View File

@ -19,10 +19,23 @@ export class StaticMapEntityComponent extends Component {
rotation: types.float,
originalRotation: types.float,
spriteKey: types.nullable(types.string),
blueprintSpriteKey: types.string,
silhouetteColor: types.nullable(types.string),
};
}
duplicateWithoutContents() {
return new StaticMapEntityComponent({
origin: this.origin.copy(),
tileSize: this.tileSize.copy(),
rotation: this.rotation,
originalRotation: this.originalRotation,
spriteKey: this.spriteKey,
silhouetteColor: this.silhouetteColor,
blueprintSpriteKey: this.blueprintSpriteKey,
});
}
/**
*
* @param {object} param0
@ -31,6 +44,7 @@ export class StaticMapEntityComponent extends Component {
* @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
*/
constructor({
@ -40,6 +54,7 @@ export class StaticMapEntityComponent extends Component {
originalRotation = 0,
spriteKey = null,
silhouetteColor = null,
blueprintSpriteKey = null,
}) {
super();
assert(
@ -53,6 +68,7 @@ export class StaticMapEntityComponent extends Component {
this.rotation = rotation;
this.originalRotation = originalRotation;
this.silhouetteColor = silhouetteColor;
this.blueprintSpriteKey = blueprintSpriteKey;
}
/**
@ -202,14 +218,25 @@ export class StaticMapEntityComponent extends Component {
* @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) {
const worldX = this.origin.x * globalConfig.tileSize;
const worldY = this.origin.y * globalConfig.tileSize;
if (!this.shouldBeDrawn(parameters)) {
drawSpriteOnFullEntityBounds(
parameters,
sprite,
extrudePixels = 0,
clipping = true,
overridePosition = null
) {
if (!this.shouldBeDrawn(parameters) && !overridePosition) {
return;
}
let worldX = this.origin.x * globalConfig.tileSize;
let worldY = this.origin.y * globalConfig.tileSize;
if (overridePosition) {
worldX = overridePosition.x * globalConfig.tileSize;
worldY = overridePosition.y * globalConfig.tileSize;
}
if (this.rotation === 0) {
// Early out, is faster

View File

@ -19,6 +19,10 @@ export class StorageComponent extends Component {
};
}
duplicateWithoutContents() {
return new StorageComponent({ maximumStorage: this.maximumStorage });
}
/**
* @param {object} param0
* @param {number=} param0.maximumStorage How much this storage can hold

View File

@ -23,6 +23,13 @@ export class UndergroundBeltComponent extends Component {
};
}
duplicateWithoutContents() {
return new UndergroundBeltComponent({
mode: this.mode,
tier: this.tier,
});
}
/**
*
* @param {object} param0

View File

@ -8,4 +8,8 @@ export class UnremovableComponent extends Component {
static getSchema() {
return {};
}
duplicateWithoutContents() {
return new UnremovableComponent();
}
}

View File

@ -77,11 +77,14 @@ export class Entity extends BasicSerializableObject {
}
/**
* Returns whether the entity is still alive
* @returns {boolean}
* Returns a clone of this entity without contents
*/
isAlive() {
return !this.destroyed && !this.queuedForDestroy;
duplicateWithoutContents() {
const clone = new Entity(this.root);
for (const key in this.components) {
clone.components[key] = this.components[key].duplicateWithoutContents();
}
return clone;
}
/**

View File

@ -34,6 +34,7 @@ export class GameSystemWithFilter extends GameSystem {
this.root.signals.entityQueuedForDestroy.add(this.internalPopEntityIfMatching, this);
this.root.signals.postLoadHook.add(this.internalPostLoadHook, this);
this.root.signals.bulkOperationFinished.add(this.refreshCaches, this);
}
/**
@ -159,6 +160,14 @@ export class GameSystemWithFilter extends GameSystem {
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);
}
}
}
/**
@ -175,7 +184,7 @@ export class GameSystemWithFilter extends GameSystem {
internalRegisterEntity(entity) {
this.allEntities.push(entity);
if (this.root.gameInitialized) {
if (this.root.gameInitialized && !this.root.bulkOperationRunning) {
// Sort entities by uid so behaviour is predictable
this.allEntities.sort((a, b) => a.uid - b.uid);
}
@ -186,6 +195,10 @@ export class GameSystemWithFilter extends GameSystem {
* @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);

View File

@ -97,8 +97,8 @@ export class HubGoals extends BasicSerializableObject {
// Allow quickly switching goals in dev mode with key "C"
if (G_IS_DEV) {
this.root.gameState.inputReciever.keydown.add(key => {
if (key.keyCode === 67) {
// Key: c
if (key.keyCode === 66) {
// Key: b
this.onGoalCompleted();
}
});

View File

@ -8,6 +8,7 @@ import { HUDProcessingOverlay } from "./parts/processing_overlay";
import { HUDBuildingsToolbar } from "./parts/buildings_toolbar";
import { HUDBuildingPlacer } from "./parts/building_placer";
import { HUDBetaOverlay } from "./parts/beta_overlay";
import { HUDBlueprintPlacer } from "./parts/blueprint_placer";
import { HUDKeybindingOverlay } from "./parts/keybinding_overlay";
import { HUDUnlockNotification } from "./parts/unlock_notification";
import { HUDGameMenu } from "./parts/game_menu";
@ -45,6 +46,7 @@ export class GameHUD {
buildingsToolbar: new HUDBuildingsToolbar(this.root),
buildingPlacer: new HUDBuildingPlacer(this.root),
blueprintPlacer: new HUDBlueprintPlacer(this.root),
unlockNotification: new HUDUnlockNotification(this.root),
@ -72,6 +74,7 @@ export class GameHUD {
selectedPlacementBuildingChanged: /** @type {TypedSignal<[MetaBuilding|null]>} */ (new Signal()),
shapePinRequested: /** @type {TypedSignal<[ShapeDefinition, number]>} */ (new Signal()),
notification: /** @type {TypedSignal<[string, enumNotificationType]>} */ (new Signal()),
buildingsSelectedForCopy: /** @type {TypedSignal<[Array<number>]>} */ (new Signal()),
};
if (!IS_MOBILE) {
@ -185,7 +188,7 @@ export class GameHUD {
* @param {DrawParameters} parameters
*/
draw(parameters) {
const partsOrder = ["massSelector", "buildingPlacer"];
const partsOrder = ["massSelector", "buildingPlacer", "blueprintPlacer"];
for (let i = 0; i < partsOrder.length; ++i) {
if (this.parts[partsOrder[i]]) {

View File

@ -0,0 +1,204 @@
import { DrawParameters } from "../../../core/draw_parameters";
import { Loader } from "../../../core/loader";
import { createLogger } from "../../../core/logging";
import { Vector } from "../../../core/vector";
import { Entity } from "../../entity";
import { GameRoot } from "../../root";
const logger = createLogger("blueprint");
export class Blueprint {
/**
* @param {Array<Entity>} entities
*/
constructor(entities) {
this.entities = entities;
}
/**
* Creates a new blueprint from the given entity uids
* @param {GameRoot} root
* @param {Array<number>} uids
*/
static fromUids(root, uids) {
const newEntities = [];
let averagePosition = new Vector();
// First, create a copy
for (let i = 0; i < uids.length; ++i) {
const entity = root.entityMgr.findByUid(uids[i]);
assert(entity, "Entity for blueprint not found:" + uids[i]);
const clone = entity.duplicateWithoutContents();
newEntities.push(clone);
const pos = entity.components.StaticMapEntity.getTileSpaceBounds().getCenter();
averagePosition.addInplace(pos);
}
averagePosition.divideScalarInplace(uids.length);
const blueprintOrigin = averagePosition.floor();
for (let i = 0; i < uids.length; ++i) {
newEntities[i].components.StaticMapEntity.origin.subInplace(blueprintOrigin);
}
// Now, make sure the origin is 0,0
return new Blueprint(newEntities);
}
/**
* Draws the blueprint at the given origin
* @param {DrawParameters} parameters
*/
draw(parameters, tile) {
parameters.context.globalAlpha = 0.8;
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();
rect.moveBy(tile.x, tile.y);
let placeable = true;
placementCheck: for (let x = rect.x; x < rect.right(); ++x) {
for (let y = rect.y; y < rect.bottom(); ++y) {
if (parameters.root.map.isTileUsedXY(x, y)) {
placeable = false;
break placementCheck;
}
}
}
if (!placeable) {
parameters.context.globalAlpha = 0.3;
} else {
parameters.context.globalAlpha = 1;
}
staticComp.drawSpriteOnFullEntityBounds(
parameters,
Loader.getSprite(staticComp.blueprintSpriteKey),
0,
true,
newPos
);
}
parameters.context.globalAlpha = 1;
}
/**
* Rotates the blueprint clockwise
*/
rotateCw() {
for (let i = 0; i < this.entities.length; ++i) {
const entity = this.entities[i];
const staticComp = entity.components.StaticMapEntity;
staticComp.rotation = (staticComp.rotation + 90) % 360;
staticComp.originalRotation = (staticComp.originalRotation + 90) % 360;
staticComp.origin = staticComp.origin.rotateFastMultipleOf90(90);
}
}
/**
* Rotates the blueprint counter clock wise
*/
rotateCcw() {
// Well ...
for (let i = 0; i < 3; ++i) {
this.rotateCw();
}
}
/**
* Checks if the blueprint can be placed at the given tile
* @param {GameRoot} root
* @param {Vector} tile
*/
canPlace(root, tile) {
let anyPlaceable = false;
for (let i = 0; i < this.entities.length; ++i) {
let placeable = true;
const entity = this.entities[i];
const staticComp = entity.components.StaticMapEntity;
const rect = staticComp.getTileSpaceBounds();
rect.moveBy(tile.x, tile.y);
placementCheck: for (let x = rect.x; x < rect.right(); ++x) {
for (let y = rect.y; y < rect.bottom(); ++y) {
if (root.map.isTileUsedXY(x, y)) {
placeable = false;
break placementCheck;
}
}
}
if (placeable) {
anyPlaceable = true;
}
}
return anyPlaceable;
}
/**
* Attempts to place the blueprint at the given tile
* @param {GameRoot} root
* @param {Vector} tile
*/
tryPlace(root, tile) {
return root.logic.performBulkOperation(() => {
let anyPlaced = false;
for (let i = 0; i < this.entities.length; ++i) {
let placeable = true;
const entity = this.entities[i];
const staticComp = entity.components.StaticMapEntity;
const rect = staticComp.getTileSpaceBounds();
rect.moveBy(tile.x, tile.y);
placementCheck: for (let x = rect.x; x < rect.right(); ++x) {
for (let y = rect.y; y < rect.bottom(); ++y) {
const contents = root.map.getTileContentXY(x, y);
if (contents && !contents.components.ReplaceableMapEntity) {
placeable = false;
break placementCheck;
}
}
}
if (placeable) {
for (let x = rect.x; x < rect.right(); ++x) {
for (let y = rect.y; y < rect.bottom(); ++y) {
const contents = root.map.getTileContentXY(x, y);
if (contents) {
assert(
contents.components.ReplaceableMapEntity,
"Can not delete entity for blueprint"
);
if (!root.logic.tryDeleteBuilding(contents)) {
logger.error(
"Building has replaceable component but is also unremovable in blueprint"
);
return false;
}
}
}
}
const clone = entity.duplicateWithoutContents();
clone.components.StaticMapEntity.origin.addInplace(tile);
root.map.placeStaticEntity(clone);
root.entityMgr.registerEntity(clone);
anyPlaced = true;
}
}
return anyPlaced;
});
}
}

View File

@ -0,0 +1,114 @@
import { DrawParameters } from "../../../core/draw_parameters";
import { STOP_PROPAGATION } from "../../../core/signal";
import { TrackedState } from "../../../core/tracked_state";
import { Vector } from "../../../core/vector";
import { enumMouseButton } from "../../camera";
import { KEYMAPPINGS } from "../../key_action_mapper";
import { BaseHUDPart } from "../base_hud_part";
import { Blueprint } from "./blueprint";
export class HUDBlueprintPlacer extends BaseHUDPart {
createElements(parent) {}
initialize() {
this.root.hud.signals.buildingsSelectedForCopy.add(this.onBuildingsSelected, this);
/** @type {TypedTrackedState<Blueprint?>} */
this.currentBlueprint = new TrackedState(this.onBlueprintChanged, this);
const keyActionMapper = this.root.keyMapper;
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
keyActionMapper
.getBinding(KEYMAPPINGS.placement.abortBuildingPlacement)
.add(this.abortPlacement, this);
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, 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);
}
abortPlacement() {
if (this.currentBlueprint.get()) {
this.currentBlueprint.set(null);
return STOP_PROPAGATION;
}
}
onBlueprintChanged(blueprint) {}
/**
* mouse down pre handler
* @param {Vector} pos
* @param {enumMouseButton} button
*/
onMouseDown(pos, button) {
if (button === enumMouseButton.right) {
this.abortPlacement();
return STOP_PROPAGATION;
}
const blueprint = this.currentBlueprint.get();
if (!blueprint) {
return;
}
const worldPos = this.root.camera.screenToWorld(pos);
const tile = worldPos.toTileSpace();
if (blueprint.tryPlace(this.root, tile)) {
// This actually feels weird
// if (!this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeMultiple).currentlyDown) {
// this.currentBlueprint.set(null);
// }
}
}
onMouseMove() {
// Prevent movement while blueprint is selected
if (this.currentBlueprint.get()) {
return STOP_PROPAGATION;
}
}
/**
* @param {Array<number>} uids
*/
onBuildingsSelected(uids) {
if (uids.length === 0) {
return;
}
this.currentBlueprint.set(Blueprint.fromUids(this.root, uids));
}
rotateBlueprint() {
if (this.currentBlueprint.get()) {
if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).currentlyDown) {
this.currentBlueprint.get().rotateCcw();
} else {
this.currentBlueprint.get().rotateCw();
}
}
}
/**
*
* @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);
}
}

View File

@ -39,6 +39,8 @@ export class HUDBuildingPlacer extends BaseHUDPart {
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.tryRotate, this);
keyActionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildingVariants).add(this.cycleVariants, this);
this.root.hud.signals.buildingsSelectedForCopy.add(this.abortPlacement, this);
this.domAttach = new DynamicDomAttach(this.root, this.element, {});
this.root.camera.downPreHandler.add(this.onMouseDown, this);
@ -159,14 +161,19 @@ export class HUDBuildingPlacer extends BaseHUDPart {
if (
metaBuilding &&
metaBuilding.getRotateAutomaticallyWhilePlacing(this.currentVariant.get()) &&
!this.root.app.inputMgr.ctrlIsDown
!this.root.keyMapper.getBinding(
KEYMAPPINGS.placementModifiers.placementDisableAutoOrientation
).currentlyDown
) {
const delta = newPos.sub(oldPos);
const angleDeg = Math_degrees(delta.angle());
this.currentBaseRotation = (Math.round(angleDeg / 90) * 90 + 360) % 360;
// Holding alt inverts the placement
if (this.root.app.inputMgr.altIsDown) {
if (
this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeInverse)
.currentlyDown
) {
this.currentBaseRotation = (180 + this.currentBaseRotation) % 360;
}
}
@ -255,6 +262,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
origin: new Vector(0, 0),
rotation: 0,
tileSize: metaBuilding.getDimensions(this.currentVariant.get()).copy(),
blueprintSpriteKey: "",
})
);
metaBuilding.updateVariants(this.fakeEntity, 0, this.currentVariant.get());
@ -386,7 +394,12 @@ export class HUDBuildingPlacer extends BaseHUDPart {
tryRotate() {
const selectedBuilding = this.currentMetaBuilding.get();
if (selectedBuilding) {
this.currentBaseRotation = (this.currentBaseRotation + 90) % 360;
if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).currentlyDown) {
this.currentBaseRotation = (this.currentBaseRotation + 270) % 360;
} else {
this.currentBaseRotation = (this.currentBaseRotation + 90) % 360;
}
const staticComp = this.fakeEntity.components.StaticMapEntity;
staticComp.rotation = this.currentBaseRotation;
}
@ -464,13 +477,18 @@ export class HUDBuildingPlacer extends BaseHUDPart {
) {
// Succesfully placed
if (metaBuilding.getFlipOrientationAfterPlacement() && !this.root.app.inputMgr.ctrlIsDown) {
if (
metaBuilding.getFlipOrientationAfterPlacement() &&
!this.root.keyMapper.getBinding(
KEYMAPPINGS.placementModifiers.placementDisableAutoOrientation
).currentlyDown
) {
this.currentBaseRotation = (180 + this.currentBaseRotation) % 360;
}
if (
!metaBuilding.getStayInPlacementMode() &&
!this.root.app.inputMgr.shiftIsDown &&
!this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeMultiple).currentlyDown &&
!this.root.app.settings.getAllSettings().alwaysMultiplace
) {
// Stop placement

View File

@ -109,7 +109,15 @@ export class HUDBuildingsToolbar extends BaseHUDPart {
}
cycleBuildings() {
const newIndex = (this.lastSelectedIndex + 1) % toolbarBuildings.length;
let newIndex = this.lastSelectedIndex;
for (let i = 0; i < toolbarBuildings.length; ++i, ++newIndex) {
newIndex %= toolbarBuildings.length;
const metaBuilding = gMetaBuildingRegistry.findByClass(toolbarBuildings[newIndex]);
const handle = this.buildingHandles[metaBuilding.id];
if (!handle.selected && handle.unlocked) {
break;
}
}
const metaBuildingClass = toolbarBuildings[newIndex];
const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass);
this.selectBuildingForPlacement(metaBuilding);

View File

@ -1,24 +1,16 @@
import { BaseHUDPart } from "../base_hud_part";
import { makeDiv } from "../../../core/utils";
import { getStringForKeyCode, KEYMAPPINGS } from "../../key_action_mapper";
import { TrackedState } from "../../../core/tracked_state";
import { queryParamOptions } from "../../../core/query_parameters";
import { T } from "../../../translations";
import { getStringForKeyCode, KEYMAPPINGS } from "../../key_action_mapper";
import { BaseHUDPart } from "../base_hud_part";
export class HUDKeybindingOverlay extends BaseHUDPart {
initialize() {
this.shiftDownTracker = new TrackedState(this.onShiftStateChanged, this);
this.root.hud.signals.selectedPlacementBuildingChanged.add(
this.onSelectedBuildingForPlacementChanged,
this
);
}
onShiftStateChanged(shiftDown) {
this.element.classList.toggle("shiftDown", shiftDown);
}
createElements(parent) {
const mapper = this.root.keyMapper;
@ -70,7 +62,9 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
</div>
<div class="binding placementOnly">
<code class="keybinding builtinKey shift"> ${T.global.keys.shift}</code>
<code class="keybinding builtinKey shift"> ${getKeycode(
KEYMAPPINGS.placementModifiers.placeMultiple
)}</code>
<label>${T.ingame.keybindingsOverlay.placeMultiple}</label>
</div>
`
@ -81,7 +75,5 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
this.element.classList.toggle("placementActive", !!selectedMetaBuilding);
}
update() {
this.shiftDownTracker.set(this.root.app.inputMgr.shiftIsDown);
}
update() {}
}

View File

@ -5,12 +5,13 @@ import { DrawParameters } from "../../../core/draw_parameters";
import { Entity } from "../../entity";
import { Loader } from "../../../core/loader";
import { globalConfig } from "../../../core/config";
import { makeDiv } from "../../../core/utils";
import { makeDiv, formatBigNumber, formatBigNumberFull } from "../../../core/utils";
import { DynamicDomAttach } from "../dynamic_dom_attach";
import { createLogger } from "../../../core/logging";
import { enumMouseButton } from "../../camera";
import { T } from "../../../translations";
import { KEYMAPPINGS } from "../../key_action_mapper";
import { THEME } from "../../theme";
const logger = createLogger("hud/mass_selector");
@ -20,13 +21,17 @@ export class HUDMassSelector extends BaseHUDPart {
.getBinding(KEYMAPPINGS.massSelect.confirmMassDelete)
.getKeyCodeString();
const abortKeybinding = this.root.keyMapper.getBinding(KEYMAPPINGS.general.back).getKeyCodeString();
const copyKeybinding = this.root.keyMapper
.getBinding(KEYMAPPINGS.massSelect.massSelectCopy)
.getKeyCodeString();
this.element = makeDiv(
parent,
"ingame_HUD_MassSelector",
[],
T.ingame.massDelete.infoText
T.ingame.massSelect.infoText
.replace("<keyDelete>", removalKeybinding)
.replace("<keyCopy>", copyKeybinding)
.replace("<keyCancel>", abortKeybinding)
);
}
@ -36,7 +41,7 @@ export class HUDMassSelector extends BaseHUDPart {
this.currentSelectionStart = null;
this.currentSelectionEnd = null;
this.entityUidsMarkedForDeletion = new Set();
this.selectedUids = new Set();
this.root.signals.entityQueuedForDestroy.add(this.onEntityDestroyed, this);
@ -48,6 +53,7 @@ export class HUDMassSelector extends BaseHUDPart {
this.root.keyMapper
.getBinding(KEYMAPPINGS.massSelect.confirmMassDelete)
.add(this.confirmDelete, this);
this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectCopy).add(this.startCopy, this);
this.domAttach = new DynamicDomAttach(this.root, this.element);
}
@ -57,7 +63,7 @@ export class HUDMassSelector extends BaseHUDPart {
* @param {Entity} entity
*/
onEntityDestroyed(entity) {
this.entityUidsMarkedForDeletion.delete(entity.uid);
this.selectedUids.delete(entity.uid);
}
/**
@ -65,31 +71,57 @@ export class HUDMassSelector extends BaseHUDPart {
*/
onBack() {
// Clear entities on escape
if (this.entityUidsMarkedForDeletion.size > 0) {
this.entityUidsMarkedForDeletion = new Set();
if (this.selectedUids.size > 0) {
this.selectedUids = new Set();
return STOP_PROPAGATION;
}
}
confirmDelete() {
const entityUids = Array.from(this.entityUidsMarkedForDeletion);
if (this.selectedUids.size > 500) {
const { ok } = this.root.hud.parts.dialogs.showWarning(
T.dialogs.massDeleteConfirm.title,
T.dialogs.massDeleteConfirm.desc.replace(
"<count>",
"" + formatBigNumberFull(this.selectedUids.size)
),
["cancel:good", "ok:bad"]
);
ok.add(() => this.doDelete());
} else {
this.doDelete();
}
}
doDelete() {
const entityUids = Array.from(this.selectedUids);
for (let i = 0; i < entityUids.length; ++i) {
const uid = entityUids[i];
const entity = this.root.entityMgr.findByUid(uid);
if (!this.root.logic.tryDeleteBuilding(entity)) {
logger.error("Error in mass delete, could not remove building");
this.entityUidsMarkedForDeletion.delete(uid);
this.selectedUids.delete(uid);
}
}
}
startCopy() {
if (this.selectedUids.size > 0) {
this.root.hud.signals.buildingsSelectedForCopy.dispatch(Array.from(this.selectedUids));
this.selectedUids = new Set();
this.root.soundProxy.playUiClick();
} else {
this.root.soundProxy.playUiError();
}
}
/**
* mouse down pre handler
* @param {Vector} pos
* @param {enumMouseButton} mouseButton
*/
onMouseDown(pos, mouseButton) {
if (!this.root.app.inputMgr.ctrlIsDown) {
if (!this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectStart).currentlyDown) {
return;
}
@ -97,9 +129,9 @@ export class HUDMassSelector extends BaseHUDPart {
return;
}
if (!this.root.app.inputMgr.shiftIsDown) {
if (!this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectSelectMultiple).currentlyDown) {
// Start new selection
this.entityUidsMarkedForDeletion = new Set();
this.selectedUids = new Set();
}
this.currentSelectionStart = pos.copy();
@ -132,7 +164,7 @@ export class HUDMassSelector extends BaseHUDPart {
for (let y = realTileStart.y; y <= realTileEnd.y; ++y) {
const contents = this.root.map.getTileContentXY(x, y);
if (contents && this.root.logic.canDeleteBuilding(contents)) {
this.entityUidsMarkedForDeletion.add(contents.uid);
this.selectedUids.add(contents.uid);
}
}
}
@ -143,7 +175,7 @@ export class HUDMassSelector extends BaseHUDPart {
}
update() {
this.domAttach.update(this.entityUidsMarkedForDeletion.size > 0);
this.domAttach.update(this.selectedUids.size > 0);
}
/**
@ -151,6 +183,8 @@ export class HUDMassSelector extends BaseHUDPart {
* @param {DrawParameters} parameters
*/
draw(parameters) {
const boundsBorder = 2;
if (this.currentSelectionStart) {
const worldStart = this.root.camera.screenToWorld(this.currentSelectionStart);
const worldEnd = this.root.camera.screenToWorld(this.currentSelectionEnd);
@ -165,8 +199,8 @@ export class HUDMassSelector extends BaseHUDPart {
const realTileEnd = tileStart.max(tileEnd);
parameters.context.lineWidth = 1;
parameters.context.fillStyle = "rgba(255, 127, 127, 0.2)";
parameters.context.strokeStyle = "rgba(255, 127, 127, 0.5)";
parameters.context.fillStyle = THEME.map.selectionBackground;
parameters.context.strokeStyle = THEME.map.selectionOutline;
parameters.context.beginPath();
parameters.context.rect(
realWorldStart.x,
@ -177,34 +211,40 @@ export class HUDMassSelector extends BaseHUDPart {
parameters.context.fill();
parameters.context.stroke();
parameters.context.fillStyle = THEME.map.selectionOverlay;
for (let x = realTileStart.x; x <= realTileEnd.x; ++x) {
for (let y = realTileStart.y; y <= realTileEnd.y; ++y) {
const contents = this.root.map.getTileContentXY(x, y);
if (contents && this.root.logic.canDeleteBuilding(contents)) {
const staticComp = contents.components.StaticMapEntity;
const center = staticComp.getTileSpaceBounds().getCenter().toWorldSpace();
this.deletionMarker.drawCachedCentered(
parameters,
center.x,
center.y,
globalConfig.tileSize * 0.5
const bounds = staticComp.getTileSpaceBounds();
parameters.context.beginRoundedRect(
bounds.x * globalConfig.tileSize + boundsBorder,
bounds.y * globalConfig.tileSize + boundsBorder,
bounds.w * globalConfig.tileSize - 2 * boundsBorder,
bounds.h * globalConfig.tileSize - 2 * boundsBorder,
2
);
parameters.context.fill();
}
}
}
}
this.entityUidsMarkedForDeletion.forEach(uid => {
parameters.context.fillStyle = THEME.map.selectionOverlay;
this.selectedUids.forEach(uid => {
const entity = this.root.entityMgr.findByUid(uid);
const staticComp = entity.components.StaticMapEntity;
const center = staticComp.getTileSpaceBounds().getCenter().toWorldSpace();
this.deletionMarker.drawCachedCentered(
parameters,
center.x,
center.y,
globalConfig.tileSize * 0.5
const bounds = staticComp.getTileSpaceBounds();
parameters.context.beginRoundedRect(
bounds.x * globalConfig.tileSize + boundsBorder,
bounds.y * globalConfig.tileSize + boundsBorder,
bounds.w * globalConfig.tileSize - 2 * boundsBorder,
bounds.h * globalConfig.tileSize - 2 * boundsBorder,
2
);
parameters.context.fill();
});
}
}

View File

@ -6,6 +6,7 @@ import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper";
import { BaseHUDPart } from "../base_hud_part";
import { DynamicDomAttach } from "../dynamic_dom_attach";
import { T } from "../../../translations";
import { globalConfig } from "../../../core/config";
const tutorialVideos = [1, 2, 3, 4, 5, 6, 7, 9, 10, 11];
@ -56,7 +57,7 @@ export class HUDPartTutorialHints extends BaseHUDPart {
this.currentShownLevel = new TrackedState(this.updateVideoUrl, this);
this.root.signals.postLoadHook.add(() => {
if (this.root.hubGoals.level === 1) {
if (this.root.hubGoals.level === 1 && !(G_IS_DEV && globalConfig.debug.disableTutorialHints)) {
this.root.hud.parts.dialogs.showInfo(
T.dialogs.hintDescription.title,
T.dialogs.hintDescription.desc

View File

@ -53,20 +53,22 @@ export const KEYMAPPINGS = {
placement: {
abortBuildingPlacement: { keyCode: key("Q") },
rotateWhilePlacing: { keyCode: key("R") },
rotateInverseModifier: { keyCode: 16 }, // SHIFT
cycleBuildingVariants: { keyCode: key("T") },
cycleBuildings: { keyCode: 9 }, // TAB
},
massSelect: {
massSelectStart: { keyCode: 17, builtin: true }, // CTRL
massSelectSelectMultiple: { keyCode: 16, builtin: true }, // SHIFT
massSelectStart: { keyCode: 17 }, // CTRL
massSelectSelectMultiple: { keyCode: 16 }, // SHIFT
massSelectCopy: { keyCode: key("C") },
confirmMassDelete: { keyCode: key("X") },
},
placementModifiers: {
placementDisableAutoOrientation: { keyCode: 17, builtin: true }, // CTRL
placeMultiple: { keyCode: 16, builtin: true }, // SHIFT
placeInverse: { keyCode: 18, builtin: true }, // ALT
placementDisableAutoOrientation: { keyCode: 17 }, // CTRL
placeMultiple: { keyCode: 16 }, // SHIFT
placeInverse: { keyCode: 18 }, // ALT
},
};

View File

@ -3,10 +3,11 @@ import { Entity } from "./entity";
import { Vector, enumDirectionToVector, enumDirection } from "../core/vector";
import { MetaBuilding } from "./meta_building";
import { StaticMapEntityComponent } from "./components/static_map_entity";
import { Math_abs } from "../core/builtins";
import { Math_abs, performanceNow } from "../core/builtins";
import { createLogger } from "../core/logging";
import { MetaBeltBaseBuilding, arrayBeltVariantToRotation } from "./buildings/belt_base";
import { SOUNDS } from "../platform/sound";
import { round2Digits } from "../core/utils";
const logger = createLogger("ingame/logic");
@ -60,6 +61,7 @@ export class GameLogic {
origin,
tileSize: building.getDimensions(variant),
rotation,
blueprintSpriteKey: "",
});
const rect = checker.getTileSpaceBounds();
@ -131,17 +133,6 @@ export class GameLogic {
return false;
}
if (
!building.performAdditionalPlacementChecks(this.root, {
origin,
rotation,
rotationVariant,
variant,
})
) {
return false;
}
return this.isAreaFreeToBuild({
origin,
rotation,
@ -168,6 +159,7 @@ export class GameLogic {
origin,
tileSize: building.getDimensions(variant),
rotation,
blueprintSpriteKey: "",
});
const rect = checker.getTileSpaceBounds();
@ -200,6 +192,24 @@ export class GameLogic {
return false;
}
/**
* Performs a bulk operation, not updating caches in the meantime
* @param {function} operation
*/
performBulkOperation(operation) {
logger.log("Running bulk operation ...");
assert(!this.root.bulkOperationRunning, "Can not run two bulk operations twice");
this.root.bulkOperationRunning = true;
const now = performanceNow();
const returnValue = operation();
const duration = performanceNow() - now;
logger.log("Done in", round2Digits(duration), "ms");
assert(this.root.bulkOperationRunning, "Bulk operation = false while bulk operation was running");
this.root.bulkOperationRunning = false;
this.root.signals.bulkOperationFinished.dispatch();
return returnValue;
}
/**
* Returns whether the given building can get removed
* @param {Entity} building

View File

@ -147,6 +147,17 @@ export class BaseMap extends BasicSerializableObject {
return chunk && chunk.getTileContentFromWorldCoords(tile.x, tile.y) != null;
}
/**
* Checks if the tile is used
* @param {number} x
* @param {number} y
* @returns {boolean}
*/
isTileUsedXY(x, y) {
const chunk = this.getChunkAtTileOrNull(x, y);
return chunk && chunk.getTileContentFromWorldCoords(x, y) != null;
}
/**
* Sets the tiles content
* @param {Vector} tile

View File

@ -129,19 +129,6 @@ export class MetaBuilding {
return null;
}
/**
* Should perform additional placement checks
* @param {GameRoot} root
* @param {object} param0
* @param {Vector} param0.origin
* @param {number} param0.rotation
* @param {number} param0.rotationVariant
* @param {string} param0.variant
*/
performAdditionalPlacementChecks(root, { origin, rotation, rotationVariant, variant }) {
return true;
}
/**
* Creates the entity at the given location
* @param {object} param0
@ -154,6 +141,9 @@ export class MetaBuilding {
*/
createAndPlaceEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) {
const entity = new Entity(root);
const blueprintSprite = this.getBlueprintSprite(rotationVariant, variant);
entity.addComponent(
new StaticMapEntityComponent({
spriteKey:
@ -166,6 +156,7 @@ export class MetaBuilding {
originalRotation,
tileSize: this.getDimensions(variant).copy(),
silhouetteColor: this.getSilhouetteColor(),
blueprintSpriteKey: blueprintSprite ? blueprintSprite.spriteName : "",
})
);

View File

@ -70,6 +70,11 @@ export class GameRoot {
/** @type {boolean} */
this.gameInitialized = false;
/**
* Whether a bulk operation is running
*/
this.bulkOperationRunning = false;
//////// Other properties ///////
/** @type {Camera} */
@ -151,6 +156,8 @@ export class GameRoot {
shapeDelivered: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()),
itemProduced: /** @type {TypedSignal<[BaseItem]>} */ (new Signal()),
bulkOperationFinished: /** @type {TypedSignal<[]>} */ (new Signal()),
};
// RNG's

View File

@ -17,9 +17,16 @@ export class MinerSystem extends GameSystemWithFilter {
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;
const staticComp = entity.components.StaticMapEntity;
const tileBelow = this.root.map.getLowerLayerContentXY(staticComp.origin.x, staticComp.origin.y);
if (!tileBelow) {
continue;
}
// First, try to get rid of chained items
if (minerComp.itemChainBuffer.length > 0) {
if (this.tryPerformMinerEject(entity, minerComp.itemChainBuffer[0])) {

View File

@ -4,7 +4,7 @@
"background": "#2e2f37",
"grid": "rgba(255, 255, 255, 0.02)",
"gridLineWidth": 0.5,
"selectionColor": "rgba(127, 127, 255, 0.5)",
"resources": {
"shape": "#3d3f4a",
"red": "#4a3d3f",

View File

@ -5,6 +5,10 @@
"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)",
"resources": {
"shape": "#eaebec",
"red": "#ffbfc1",

View File

@ -11,8 +11,7 @@ import { createLogger } from "../core/logging";
import { globalConfig } from "../core/config";
import { SavegameInterface_V1000 } from "./schemas/1000";
import { getSavegameInterface } from "./savegame_interface_registry";
import { compressObject } from "./savegame_compressor";
import { compressX64 } from "../core/lzstring";
import { SavegameInterface_V1001 } from "./schemas/1001";
const logger = createLogger("savegame");
@ -29,7 +28,7 @@ export class Savegame extends ReadWriteProxy {
this.internalId = internalId;
this.metaDataRef = metaDataRef;
/** @type {SavegameData} */
/** @type {import("./savegame_typedefs").SavegameData} */
this.currentData = this.getDefaultData();
}
@ -39,14 +38,14 @@ export class Savegame extends ReadWriteProxy {
* @returns {number}
*/
static getCurrentVersion() {
return 1000;
return 1001;
}
/**
* @returns {typeof BaseSavegameInterface}
*/
static getReaderClass() {
return SavegameInterface_V1000;
return SavegameInterface_V1001;
}
/**
@ -58,7 +57,7 @@ export class Savegame extends ReadWriteProxy {
/**
* Returns the savegames default data
* @returns {SavegameData}
* @returns {import("./savegame_typedefs").SavegameData}
*/
getDefaultData() {
return {
@ -73,18 +72,25 @@ export class Savegame extends ReadWriteProxy {
/**
* Migrates the savegames data
* @param {SavegameData} data
* @param {import("./savegame_typedefs").SavegameData} data
*/
migrate(data) {
if (data.version < 1000) {
return ExplainedResult.bad("Can not migrate savegame, too old");
}
console.log("TODO: Migrate from", data.version);
if (data.version === 1000) {
SavegameInterface_V1001.migrate1000to1001(data);
data.version = 1001;
}
return ExplainedResult.good();
}
/**
* Verifies the savegames data
* @param {SavegameData} data
* @param {import("./savegame_typedefs").SavegameData} data
*/
verify(data) {
if (!data.dump) {
@ -109,7 +115,7 @@ export class Savegame extends ReadWriteProxy {
}
/**
* Returns the statistics of the savegame
* @returns {SavegameStats}
* @returns {import("./savegame_typedefs").SavegameStats}
*/
getStatistics() {
return this.currentData.stats;
@ -132,7 +138,7 @@ export class Savegame extends ReadWriteProxy {
/**
* Returns the current game dump
* @returns {SerializedGame}
* @returns {import("./savegame_typedefs").SerializedGame}
*/
getCurrentDump() {
return this.currentData.dump;

View File

@ -1,10 +1,12 @@
import { BaseSavegameInterface } from "./savegame_interface";
import { SavegameInterface_V1000 } from "./schemas/1000";
import { createLogger } from "../core/logging";
import { SavegameInterface_V1001 } from "./schemas/1001";
/** @type {Object.<number, typeof BaseSavegameInterface>} */
const interfaces = {
1000: SavegameInterface_V1000,
1001: SavegameInterface_V1001,
};
const logger = createLogger("savegame_interface_registry");

View File

@ -4,14 +4,7 @@
* }} SavegameStats
*/
/**
* @typedef {{
* x: number,
* y: number,
* uid: number,
* key: string
* }} SerializedMapResource
*/
import { Entity } from "../game/entity";
/**
* @typedef {{
@ -20,7 +13,7 @@
* entityMgr: any,
* map: any,
* hubGoals: any,
* entities: Array<any>
* entities: Array<Entity>
* }} SerializedGame
*/

View File

@ -0,0 +1,52 @@
import { SavegameInterface_V1000 } from "./1000.js";
import { createLogger } from "../../core/logging.js";
const schema = require("./1001.json");
const logger = createLogger("savegame_interface/1001");
export class SavegameInterface_V1001 extends SavegameInterface_V1000 {
getVersion() {
return 1001;
}
getSchemaUncached() {
return schema;
}
/**
* @param {import("../savegame_typedefs.js").SavegameData} data
*/
static migrate1000to1001(data) {
logger.log("Migrating 1000 to 1001");
const dump = data.dump;
if (!dump) {
return true;
}
const entities = dump.entities;
for (let i = 0; i < entities.length; ++i) {
const entity = entities[i];
const staticComp = entity.components.StaticMapEntity;
const beltComp = entity.components.Belt;
if (staticComp) {
if (staticComp.spriteKey) {
staticComp.blueprintSpriteKey = staticComp.spriteKey.replace(
"sprites/buildings",
"sprites/blueprints"
);
} else {
if (entity.components.Hub) {
staticComp.blueprintSpriteKey = "";
} else if (beltComp) {
const direction = beltComp.direction;
staticComp.blueprintSpriteKey = "sprites/blueprints/belt_" + direction + ".png";
} else {
assertAlways(false, "Could not deduct entity type for migrating 1000 -> 1001");
}
}
}
}
}
}

View File

@ -0,0 +1,5 @@
{
"type": "object",
"required": [],
"additionalProperties": true
}

View File

@ -43,7 +43,7 @@ export class SerializerInternal {
* @param {Entity} payload
*/
deserializeEntity(root, payload) {
const entity = new Entity(null);
const entity = new Entity(root);
this.deserializeComponents(entity, payload.components);
root.entityMgr.registerEntity(entity, payload.uid);

View File

@ -95,18 +95,18 @@ export class InGameState extends GameState {
}
onBeforeExit() {
logger.log("Saving before quitting");
return this.doSave().then(() => {
logger.log(this, "Successfully saved");
// this.stageDestroyed();
});
// 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();
}
// if (this.stage === stages.s10_gameRunning) {
// logger.log("Saving because app got paused");
// this.doSave();
// }
}
getHasFadeIn() {

View File

@ -82,10 +82,10 @@ export class KeybindingsState extends TextualGameState {
}
editKeybinding(id) {
if (IS_DEMO) {
this.dialogs.showFeatureRestrictionInfo(T.demo.features.customizeKeybindings);
return;
}
// if (IS_DEMO) {
// this.dialogs.showFeatureRestrictionInfo(T.demo.features.customizeKeybindings);
// return;
// }
const dialog = new Dialog({
app: this.app,

View File

@ -198,12 +198,12 @@ export class MainMenuState extends GameState {
this.trackClicks(qs(".mainContainer .importButton"), this.requestImportSavegame);
if (G_IS_DEV && globalConfig.debug.fastGameEnter) {
// // const games = this.app.savegameMgr.getSavegamesMetaData();
// if (games.length > 0) {
// this.resumeGame(games[0]);
// } else {
this.onPlayButtonClicked();
// }
const games = this.app.savegameMgr.getSavegamesMetaData();
if (games.length > 0) {
this.resumeGame(games[0]);
} else {
this.onPlayButtonClicked();
}
}
// Initialize video

View File

@ -6,6 +6,7 @@ import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper";
import { T } from "../translations";
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
import { CHANGELOG } from "../changelog";
import { globalConfig } from "../core/config";
const logger = createLogger("state/preload");
@ -179,6 +180,10 @@ export class PreloadState extends GameState {
.then(() => this.setStatus("Checking changelog"))
.then(() => {
if (G_IS_DEV && globalConfig.debug.disableUpgradeNotification) {
return;
}
return this.app.storage
.readFileAsync("lastversion.bin")
.catch(err => {

View File

@ -55,5 +55,4 @@
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
"resolveJsonModule": true
},
"exclude": ["backend/shared/gameserver_base_impl", "backend/shared/sentry_logger.js"]
}

View File

@ -172,6 +172,11 @@ dialogs:
All shapes you produce can be used to unlock upgrades - <strong>Don't destroy your old factories!</strong>
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 (<count> to be exact)! Are you sure you want to do this?
ingame:
# This is shown in the top left corner and displays useful keybindings in
# every situation
@ -221,10 +226,10 @@ ingame:
newUpgrade: A new upgrade is available!
gameSaved: Your game has been saved.
# Mass delete information, this is when you hold CTRL and then drag with your mouse
# to select multiple buildings to delete
massDelete:
infoText: Press <keyDelete> to remove selected buildings and <keyCancel> to cancel.
# Mass select information, this is when you hold CTRL and then drag with your mouse
# to select multiple buildings
massSelect:
infoText: Press <keyCopy> to copy, <keyDelete> to remove and <keyCancel> to cancel.
# The "Upgrades" window
shop:
@ -514,10 +519,10 @@ keybindings:
resetKeybindings: Reset Keyinbindings
categoryLabels:
general: Appplication
general: Application
ingame: Game
placement: Placement
massSelect: Mass Delete
massSelect: Mass Select
buildings: Building Shortcuts
placementModifiers: Placement Modifiers
@ -552,12 +557,15 @@ keybindings:
abortBuildingPlacement: Abort Placement
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

582
translations/base-fr.yaml Normal file
View File

@ -0,0 +1,582 @@
#
# 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: <key>`. They are encapsulated within angle brackets. The correct
# translation for this one in German for example would be: `Taste: <key>` (notice
# how the placeholder stayed '<key>' 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.
#
global:
loading: Chargement
error: Erreur
# How big numbers are rendered, e.g. "10,000"
thousandsDivider: "."
# Shown for infinitely big numbers
infinite: inf
time:
# Used for formatting past time dates
oneSecondAgo: il y a une seconde
xSecondsAgo: il y a <x> secondes
oneMinuteAgo: il y a une minute
xMinutesAgo: il y a <x> minutes
oneHourAgo: il y a une heure
xHoursAgo: il y a <x> heures
oneDayAgo: il y a un jour
xDaysAgo: il y a <x> jours
# Short formats for times, e.g. '5h 23m'
secondsShort: <seconds>s
minutesAndSecondsShort: <minutes>m <seconds>s
hoursAndMinutesShort: <hours>h <minutes>s
xMinutes: <x> minutes
keys:
tab: TAB
control: CTRL
alt: ALT
escape: ESC
shift: SHIFT
space: ESPACE
demoBanners:
# This is the "advertisement" shown in the main menu and other various places
title: Salut!
intro: >-
Si vous appreciez ce jeu, merci de penser à acheter la version complète!
advantages:
- Pas de publicité
- Sauvegardes illimitées
- Mode sombre & plus
- >-
Donnez-moi l'opportunité de développer shapez.io ❤️
mainMenu:
play: Jouer
changelog: Historique
importSavegame: Importer
openSourceHint: Ce jeu est open source!
discordLink: Serveur Discord officiel
# 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 browser! Procurez-vous la version autonome ou téléchargez Chrome pour une meilleure expérience.
dialogs:
buttons:
ok: OK
delete: Effacer
cancel: Annuler
later: Plus tard
restart: Relancer
reset: Réinitialiser
getStandalone: Se procurer la version autonome
deleteGame: Je sais ce que je fais
viewUpdate: Voir les mises-à-jour
showUpgrades: Montrer les améliorations
importSavegameError:
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.
gameLoadFailure:
title: Le jeu est cassé
text: >-
Impossible de charger votre sauvegarde:
confirmSavegameDelete:
title: Confirmez la suppression
text: >-
Etes-vous certains de vouloir supprimer votre partie?
savegameDeletionError:
title: Impossible de supprimer
text: >-
Impossible de supprimer votre sauvegarde:
restartRequired:
title: Redémarrage requis
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.
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 par leur état par défaut respectifs!
featureRestriction:
title: Version Démo
desc: Vous avez essayé d'accéder à la fonction (<feature>) qui n'est pas disponible dans la démo. Considérez l'achat de la version complète pour une expérience optimale!
saveNotPossibleInDemo:
desc: Votre partie a été sauvegardée, mais la charger n'est possible que dans la version complète. Considérez l'achat de la version complète pour une expérience optimale!
leaveNotPossibleInDemo:
title: Version Démo
desc: Votre partie a été sauvée mais nous ne pourrez pas la charger dans la démo. Charger les parties n'est disponible que dans la version complète. Etes-vous certain?
newUpdate:
title: Mise-à-jour disponible
desc: Une mise-à-jour est disponible pour ce jeu!
demoExplanation:
title: Note du développeur
desc: Je développe ce jeu pendant mon temps libre, et j'espère que vous l'appréciez! Si c'est le cas, merci de considérez l'achat de la version complète!
oneSavegameLimit:
title: Sauvegardes limitées
desc: Vous ne pouvez avoir qu'une seule sauvegarde en même temps dans la version démo. Merci de soit effacer l'actuelle ou de vous procurer la version complète!
updateSummary:
title: Nouvel mise-à-jour!
desc: >-
Voici les modifications depuis votre dernière session:
hintDescription:
title: Tutorial
desc: >-
Si vous avez besoin d'aide ou êtes coincé, vérifiez le bouton 'Aide' dans le coin inférieur gauche et j'essayerai de vous aider au mieux!
upgradesIntroduction:
title: Débloquer les améliorations
desc: >-
Toutes les formes que vous produisez peuvent être utilisées pour débloquer des améliorations - <strong>Ne détruisez pas vos anciennes usines!</strong>
L'onglet des améliorations se trouve dans le coin supérieur droit de l'écran.
ingame:
# This is shown in the top left corner and displays useful keybindings in
# every situation
keybindingsOverlay:
centerMap: Centrer
moveMap: Déplacer
removeBuildings: Effacer
stopPlacement: Arrêter le placement
rotateBuilding: Tourner le bâtiment
placeMultiple: Placement multiple
reverseOrientation: Changer l'orientation
disableAutoOrientation: Désactiver l'orientation automatique
toggleHud: Basculet l'ATH
placeBuilding: Placer un bâtiment
# 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: Appuyez sur <key> pour changer de variante.
# Shows the hotkey in the ui, e.g. "Hotkey: Q"
hotkeyLabel: >-
Raccourci: <key>
infoTexts:
speed: Vitesse
range: Portée
storage: Espace de stockage
oneItemPerSecond: 1 forme / seconde
itemsPerSecond: <x> formes / s
itemsPerSecondDouble: (x2)
tiles: <x> cases
# The notification when completing a level
levelCompleteNotification:
# <level> is replaced by the actual level, so this gets 'Level 03' for example.
levelTitle: Niveau <level>
completed: Terminé
unlockText: <reward> débloqué!
buttonNextLevel: Niveau suivant
# Notifications on the lower right
notifications:
newUpgrade: Une nouvelle amélioration est disponible!
gameSaved: Votre partie a été sauvegardée.
# Mass delete information, this is when you hold CTRL and then drag with your mouse
# to select multiple buildings to delete
massDelete:
infoText: Appuyez sur <keyDelete> pour effacer les bâtiments sélectionnés et <keyCancel> pour annuler.
# The "Upgrades" window
shop:
title: Améliorations
buttonUnlock: Améliorer
# Gets replaced to e.g. "Tier IX"
tier: Echelon <x>
# The roman number for each tier
tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X]
maximumLevel: Niveau maximum
# The "Statistics" window
statistics:
title: Statistiques
dataSources:
stored:
title: Stocké
description: Affiche le nombre de formes stockée 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.
delivered:
title: Délivré
description: Affiche les formes qui ont étés délivrées dans votres bâtiment central.
noShapesProduced: Aucune forme n'a été produite jusqu'à présent.
# Displays the shapes per minute, e.g. '523 / m'
shapesPerMinute: <shapes> / m
# Settings menu, when you press "ESC"
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?
showHint: Indice
hideHint: Fermer
# All shop upgrades
shopUpgrades:
belt:
name: Convoyeurs, Distributeurs et Tunnels
description: Vitesse +<gain>%
miner:
name: Extraction
description: Vitesse +<gain>%
processors:
name: Découpage, Rotation et Empilage
description: Vitesse +<gain>%
painting:
name: Mélange et Peinture
description: Vitesse +<gain>%
# Buildings and their name / description
buildings:
belt:
default:
name: &belt Convoyeurs
description: Transporte les objects, maintenez et fites glisser pour en placer plusieurs.
miner: # Internal name for the Extractor
default:
name: &miner Extracteurs
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 convoyeurs.
tier2:
name: Tunnel Echelon II
description: Permet de faire passer des ressources en dessous de bâtiment et convoyeurs.
splitter: # Internal name for the Balancer
default:
name: &splitter Balancier
description: Multifonctionnel - Distribue de manière égale 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. <strong>Si vous n'utilisez qu'une seule partie, assurez-vous de détruite l'autre ou cela coincera!</strong>
quad:
name: Découpeur (Quatre)
description: Coupe une forme en 4 parts. <strong>Si vous n'utilisez qu'une seule partie, assurez-vous de détruite les autres ou cela coincera!</strong>
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 Mixeur de couleur
description: Mixe deux couleurs en utilisant le mélange additif.
painter:
default:
name: &painter Peintre
description: Colorie la forme entière 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 (Quatre)
description: Permet de colorier chaque quadrant d'une forme avec une couleur différente.
trash:
default:
name: &trash Poubelle
description: Accepte des formes de n'importe quel côté et le détruit... pour toujours.
storage:
name: Stockage
description: Stocke les formes en trop jusqu'à une certaine capacité. Peut être utilisé comme tampon.
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 <strong>découpeur</strong> - il coupe des formes en deux <strong>de haut en bas</strong> regardless of its orientation!<br><br>Be sure to get rid of the waste, or otherwise <strong>it will stall</strong> - A cet effet, je vous donne la poubelle, qui détruit tout ce que vous y mettez!
reward_rotater:
title: Rotation
desc: Le <strong>pivoteur</strong> a été débloqué! Il pivote les formes de 90 degrés vers la droite.
reward_painter:
title: Peintre
desc: >-
Le <strong>peintre</strong> 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!<br><br>PS: Si vous êtes daltonien, je travaille déjà sur une solution!
reward_mixer:
title: Mixeur de couleurs
desc: Le <strong>mixeur</strong> a été débloqué - Combinez deux couleurs en utilisant <strong>le mélange additif</strong> avec ce bâtiment!
reward_stacker:
title: Combineur
desc: Vous pouvez maintenant combiner deux formes avec le <strong>combineur</strong>! Les deux entrées sont combinée et si elles peuvent êtres mises l'une à cpôté de l'autre, elles sont <strong>fusionnées</strong>. Sinon, la forme de droite est <strong>placée au dessus</strong> de la forme de gauche.
reward_splitter:
title: Découpeur/Fusionneur
desc: Le <strong>balancier</strong> multifonctionnel a été débloqué - Il peut être utilisé pour construire de plus grandes usines en <strong>découpant et fusionnant les formes</strong> sur plusieurs convoyeurs!<br><br>
reward_tunnel:
title: Tunnel
desc: Le <strong>tunnel</strong> a été débloqué - Vous pouvez maintenant faire passer des formes vous les convoyeurs et les bâtimentts avec ça!
reward_rotater_ccw:
title: Pivoteur inversé
desc: Vous avez débloqué une variante du <strong>pivoteur</strong> - Elle permet de faire pivoter vers la gauche! Pour le construite, sélectionnez le pivoteur et <strong>appuyez sur 'T' pour changer sa variante</strong>!
reward_miner_chainable:
title: Extracteur en série
desc: Vous avez débloqué <strong>l'extracteur en série</strong>! Il permet <strong>de transférer ses resources</strong> à d'autres extracteurs pour extraire les ressources plus efficacement!
reward_underground_belt_tier_2:
title: Tunnel échelon II
desc: Vous avez débloqué une nouvelle variante du <strong>tunnel</strong> - Elle a <strong>une portée plus grande</strong>, et vous pouvez également mixer ces tunnels maintenant!
reward_splitter_compact:
title: Balancier compacte
desc: >-
Vous avez débloqué une variante compacte du <strong>balancier</strong> - Elle accepte deux entrées et les rassemble en une sortie!
reward_cutter_quad:
title: Quadruple découpeur
desc: Vous avez débloqué une variante du <strong>découpeur</strong> - Elle permet de de découper les formes en <strong>quatres parties</strong> à la place de simplement deux!
reward_painter_double:
title: Double peintre
desc: Vous avez débloqué une variante du <strong>peintre</strong> - Elle fonctionne comme le peintre de base, mais elle permet de traiter <strong>deux formes à la fois</strong> en ne consommant qu'une couleur au lieu de deux!
reward_painter_quad:
title: Quadruple peintre
desc: Vous avez débloqué une variante du <strong>peintre</strong> - Elle permet de colorier chaque partie d'une forme individuellement!
reward_storage:
title: Tampon de stockage
desc: Vous avez débloqué une variante de <strong>la poubelle</strong> - Elle permet de stocker des formes jusqu'à une certaine limite!
reward_freeplay:
title: Mode libre
desc: Vous l'avez fait! Vous avez débloqué le <strong>mode libre</strong>! 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!)
# Special reward, which is shown when there is no reward actually
no_reward:
title: Niveau suivant
desc: >-
Ce niveau n'a pas de récompense, mais le prochain oui! <br><br> PS: Vous ne devriez pas détruires votre usine actuelle - Vous aurez besoin de <strong>toutes</strong> ces formes plus tard pour <strong>débloquer les améliorations</strong>!
no_reward_freeplay:
title: Niveau suivant
desc: >-
Bravo! D'ailleurs, plus de contenu est prévu pour la version complète!
settings:
title: Options
categories:
game: Jeu
app: Application
versionBadges:
dev: Developpement
staging: Test
prod: Production
buildDate: Créé le <at-date>
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.
fullscreen:
title: Plein écran
description: >-
Il est recommandé de jouer au jeu en plein écran pour obtenir la meilleur 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).
refreshRate:
title: Simulation Target
description: >-
Si vous avez un moniteur à 144hz, changez le taux de rafraichissement ici pour que le jeu fonctionne correctement à cette haute fréquence. Ceci pourrait diminuer vos IPS 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'avez pas annulé. Ceci revient à garder la touche SHIFT appuyée en permanence.
offerHints:
title: Indices
description: >-
ffiche ou non le bouton 'Afficher un indice' dans le coin inférieir gauche.
keybindings:
title: Contrôles
hint: >-
Astuce: Soyez sûr d'utiliser CTRL, SHIFT et ALT! Ces touches activent différentes options de placement.
resetKeybindings: Réinitialiser les contrôles
categoryLabels:
general: Application
ingame: Jeu
placement: Placement
massSelect: Suppression de masse
buildings: Raccourcis bâtiment
placementModifiers: Modificateurs de placement
mappings:
confirm: Confirmer
back: Retour
mapMoveUp: Aller en haut
mapMoveRight: Aller à droite
mapMoveDown: Aller en bas
mapMoveLeft: Aller à gauche
centerMap: Centrer la carte
mapZoomIn: Zoom avant
mapZoomOut: Zoom arrière
menuOpenShop: Améliorations
menuOpenStats: Statistiques
toggleHud: Basculer l'ATH
toggleFPSInfo: Basculer IPS et informations débogage
belt: *belt
splitter: *splitter
underground_belt: *underground_belt
miner: *miner
cutter: *cutter
rotater: *rotater
stacker: *stacker
mixer: *mixer
painter: *painter
trash: *trash
abortBuildingPlacement: Annuler le placement
rotateWhilePlacing: Pivoter
cycleBuildingVariants: Faire défiler les variantes
confirmMassDelete: Confirmer la suppression de masse
cycleBuildings: Faire défiler les bâtiments
massSelectStart: Cliquez et maintenez pour commencer
massSelectSelectMultiple: Séléctionner plusieurs zones
placementDisableAutoOrientation: Désactiver l'orientation automatique
placeMultiple: Rester en mode placement
placeInverse: Inverser le mode d'orientation automatique
about:
title: A propos de ce jeu
changelog:
title: Historique
demo:
features:
restoringGames: Charger des sauvegardes
importingGames: Importer des sauvegardes
oneGameLimit: Limité à une sauvegarde
customizeKeybindings: Personalisation des contrôles
settingNotAvailable: Indisponible dans la démo.
#
# French translation version v0.1 based on english v1.0.4 by Didier WEERTS 'The Corsaire'

View File

@ -1 +1 @@
1.0.4
1.1.0

478
yarn.lock
View File

@ -1023,6 +1023,11 @@
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"
@ -1035,11 +1040,60 @@
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"
@ -1210,7 +1264,7 @@ acorn-jsx@^3.0.0:
dependencies:
acorn "^3.0.4"
acorn-jsx@^5.0.0:
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==
@ -1230,7 +1284,7 @@ acorn@^5.5.0:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
acorn@^6.0.7, acorn@^6.2.1:
acorn@^6.2.1:
version "6.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
@ -1255,7 +1309,7 @@ ajv-keywords@^3.1.0, ajv-keywords@^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, ajv@^6.9.1:
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==
@ -1265,6 +1319,16 @@ ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.9.1:
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"
@ -1287,10 +1351,12 @@ ansi-escapes@^1.1.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-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"
@ -1331,7 +1397,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1:
dependencies:
color-convert "^1.9.0"
ansi-styles@^4.0.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==
@ -2216,7 +2282,7 @@ chalk@2.3.2:
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.4.1, chalk@^2.4.2:
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==
@ -2225,6 +2291,22 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.
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"
@ -2330,6 +2412,13 @@ cli-cursor@^2.1.0:
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"
@ -2709,7 +2798,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
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:
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==
@ -2729,6 +2818,15 @@ cross-spawn@^5.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"
@ -2965,7 +3063,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
dependencies:
ms "2.0.0"
debug@4.1.1, debug@^4.0.1, debug@^4.1.0, debug@~4.1.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==
@ -3049,7 +3147,7 @@ decompress@^4.0.0, decompress@^4.2.0:
pify "^2.3.0"
strip-dirs "^2.0.0"
deep-is@~0.1.3:
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=
@ -3480,6 +3578,20 @@ escodegen-wallaby@1.6.18:
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"
@ -3488,59 +3600,67 @@ eslint-scope@^4.0.3:
esrecurse "^4.1.0"
estraverse "^4.1.1"
eslint-utils@^1.3.1:
version "1.4.3"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f"
integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==
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.0.0, 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@^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==
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.9.1"
chalk "^2.1.0"
cross-spawn "^6.0.5"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
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"
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 "^7.1.2"
globals "^11.7.0"
glob-parent "^5.0.0"
globals "^12.1.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
inquirer "^6.2.2"
js-yaml "^3.13.0"
inquirer "^7.0.0"
is-glob "^4.0.0"
js-yaml "^3.13.1"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.3.0"
lodash "^4.17.11"
levn "^0.4.1"
lodash "^4.17.14"
minimatch "^3.0.4"
mkdirp "^0.5.1"
natural-compare "^1.4.0"
optionator "^0.8.2"
path-is-inside "^1.0.2"
optionator "^0.9.1"
progress "^2.0.0"
regexpp "^2.0.1"
semver "^5.5.1"
strip-ansi "^4.0.0"
strip-json-comments "^2.0.1"
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"
@ -3550,14 +3670,14 @@ espree@3.5.4:
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==
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 "^6.0.7"
acorn-jsx "^5.0.0"
eslint-visitor-keys "^1.0.0"
acorn "^7.1.1"
acorn-jsx "^5.2.0"
eslint-visitor-keys "^1.1.0"
esprima@^2.7.1:
version "2.7.3"
@ -3574,12 +3694,12 @@ esprima@~3.1.0:
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=
esquery@^1.0.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.2.1.tgz#105239e215c5aa480369c7794d74b8b5914c19d4"
integrity sha512-/IcAXa9GWOX9BUIb/Tz2QrrAWFWzWGrFIeLeMRwtiuwg9qTFhSYemsi9DixwrFFqVbhBZ47vGcxEnu5mbPqbig==
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.0.0"
estraverse "^5.1.0"
esrecurse@^4.1.0, esrecurse@^4.2.1:
version "4.2.1"
@ -3603,10 +3723,10 @@ estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
estraverse@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.0.0.tgz#ac81750b482c11cca26e4b07e83ed8f75fbcdc22"
integrity sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A==
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"
@ -3820,12 +3940,17 @@ fast-deep-equal@^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, 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=
@ -3874,6 +3999,13 @@ figures@^2.0.0:
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"
@ -4172,6 +4304,11 @@ get-stdin@^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"
@ -4213,7 +4350,14 @@ glob-parent@^3.1.0:
is-glob "^3.1.0"
path-dirname "^1.0.0"
glob@^7.0.5, glob@^7.0.6, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
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==
@ -4269,11 +4413,18 @@ global@~4.3.0:
min-document "^2.19.0"
process "~0.5.1"
globals@^11.1.0, globals@^11.7.0:
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"
@ -4371,6 +4522,11 @@ has-flag@^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"
@ -4727,23 +4883,23 @@ inquirer@3.0.6:
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==
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 "^3.2.0"
chalk "^2.4.2"
cli-cursor "^2.1.0"
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 "^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"
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:
@ -4942,7 +5098,7 @@ is-glob@^3.1.0:
dependencies:
is-extglob "^2.1.0"
is-glob@^4.0.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==
@ -5152,7 +5308,7 @@ js-string-escape@1.0.1:
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.13.1:
version "3.13.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
@ -5278,7 +5434,15 @@ levenary@^1.1.1:
dependencies:
leven "^3.1.0"
levn@^0.3.0, levn@~0.3.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=
@ -5427,7 +5591,7 @@ lodash.uniq@^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.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.3.0:
lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.10, 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==
@ -5700,7 +5864,7 @@ mimic-fn@^1.0.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.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==
@ -5843,6 +6007,11 @@ mute-stream@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"
@ -6134,6 +6303,13 @@ onetime@^2.0.0:
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"
@ -6171,7 +6347,7 @@ opn@5.3.0:
dependencies:
is-wsl "^1.1.0"
optionator@^0.8.1, optionator@^0.8.2:
optionator@^0.8.1:
version "0.8.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
@ -6183,6 +6359,18 @@ optionator@^0.8.1, optionator@^0.8.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"
@ -6482,16 +6670,16 @@ path-is-absolute@^1.0.0:
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.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.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"
@ -7293,6 +7481,11 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.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"
@ -7308,6 +7501,13 @@ prepend-http@^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"
@ -7621,10 +7821,10 @@ regex-not@^1.0.0, regex-not@^1.0.2:
extend-shallow "^3.0.2"
safe-regex "^1.1.0"
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==
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"
@ -7762,6 +7962,14 @@ restore-cursor@^2.0.0:
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"
@ -7806,6 +8014,11 @@ run-async@^2.2.0:
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"
@ -7830,7 +8043,7 @@ rxjs@^5.5.6:
dependencies:
symbol-observable "1.0.1"
rxjs@^6.4.0:
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==
@ -7916,7 +8129,7 @@ semver-truncate@^1.1.2:
dependencies:
semver "^5.3.0"
"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.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==
@ -7926,6 +8139,11 @@ semver@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"
@ -8057,11 +8275,23 @@ shebang-command@^1.2.0:
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"
@ -8454,7 +8684,7 @@ string-width@^1.0.1, string-width@^1.0.2:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
string-width@^2.0.0, string-width@^2.1.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==
@ -8582,12 +8812,7 @@ strip-indent@^1.0.1:
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=
strip-json-comments@^3.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==
@ -8641,6 +8866,13 @@ supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0:
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"
@ -8872,11 +9104,23 @@ tslib@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"
@ -8889,6 +9133,13 @@ tunnel-agent@^0.6.0:
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"
@ -8896,11 +9147,21 @@ type-check@~0.3.2:
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"
@ -8914,6 +9175,11 @@ typedarray@^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"
@ -9141,6 +9407,11 @@ v8-compile-cache@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"
@ -9326,12 +9597,19 @@ which@^1.2.14, which@^1.2.9, which@^1.3.1:
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, 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==