From e8d63ace828a866ad4ec4a4e8dfffd0c8df83cd9 Mon Sep 17 00:00:00 2001 From: Modded Gamers <35778371+ModdedGamers@users.noreply.github.com> Date: Sat, 23 May 2020 09:19:00 -0400 Subject: [PATCH 01/16] Update tsconfig.json --- src/js/tsconfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/js/tsconfig.json b/src/js/tsconfig.json index 57c0a852..e42edc98 100644 --- a/src/js/tsconfig.json +++ b/src/js/tsconfig.json @@ -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"] } From 59bc66a73a526ade621d8633581820141edb7496 Mon Sep 17 00:00:00 2001 From: Andriy Mykhaylyk Date: Tue, 26 May 2020 20:48:23 +0200 Subject: [PATCH 02/16] Make build setup clearer Add `git lfs pull` as an explicit step in build process --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7104404d..7e374175 100644 --- a/README.md +++ b/README.md @@ -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 From 0a9054670708a964e9754755560c6853041d00f4 Mon Sep 17 00:00:00 2001 From: "CI\\dwe" Date: Tue, 26 May 2020 20:50:10 +0200 Subject: [PATCH 03/16] - Corrected a typo in english file - Added french ranslation --- translations/base-en.yaml | 2 +- translations/base-fr.yaml | 582 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 583 insertions(+), 1 deletion(-) create mode 100644 translations/base-fr.yaml diff --git a/translations/base-en.yaml b/translations/base-en.yaml index 2e5cfd4c..2318c342 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -514,7 +514,7 @@ keybindings: resetKeybindings: Reset Keyinbindings categoryLabels: - general: Appplication + general: Application ingame: Game placement: Placement massSelect: Mass Delete diff --git a/translations/base-fr.yaml b/translations/base-fr.yaml new file mode 100644 index 00000000..a425d848 --- /dev/null +++ b/translations/base-fr.yaml @@ -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: `. They are encapsulated within angle brackets. The correct +# translation for this one in German for example would be: `Taste: ` (notice +# how the placeholder stayed '' and was not replaced!) +# +# Adding a new language: +# +# If you want to add a new language, ask me in the discord and I will setup +# the basic structure so the game also detects it. +# + +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 secondes + oneMinuteAgo: il y a une minute + xMinutesAgo: il y a minutes + oneHourAgo: il y a une heure + xHoursAgo: il y a heures + oneDayAgo: il y a un jour + xDaysAgo: il y a jours + + # Short formats for times, e.g. '5h 23m' + secondsShort: s + minutesAndSecondsShort: m s + hoursAndMinutesShort: h s + + xMinutes: 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 () 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 - Ne détruisez pas vos anciennes usines! + 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 pour changer de variante. + + # Shows the hotkey in the ui, e.g. "Hotkey: Q" + hotkeyLabel: >- + Raccourci: + + infoTexts: + speed: Vitesse + range: Portée + storage: Espace de stockage + oneItemPerSecond: 1 forme / seconde + itemsPerSecond: formes / s + itemsPerSecondDouble: (x2) + + tiles: cases + + # The notification when completing a level + levelCompleteNotification: + # is replaced by the actual level, so this gets 'Level 03' for example. + levelTitle: Niveau + completed: Terminé + unlockText: 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 pour effacer les bâtiments sélectionnés et pour annuler. + + # The "Upgrades" window + shop: + title: Améliorations + buttonUnlock: Améliorer + + # Gets replaced to e.g. "Tier IX" + tier: Echelon + + # 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: / 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 +% + miner: + name: Extraction + description: Vitesse +% + processors: + name: Découpage, Rotation et Empilage + description: Vitesse +% + painting: + name: Mélange et Peinture + description: Vitesse +% + +# 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. Si vous n'utilisez qu'une seule partie, assurez-vous de détruite l'autre ou cela coincera! + quad: + name: Découpeur (Quatre) + description: Coupe une forme en 4 parts. Si vous n'utilisez qu'une seule partie, assurez-vous de détruite les autres ou cela coincera! + + 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 découpeur - il coupe des formes en deux de haut en bas regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will stall - A cet effet, je vous donne la poubelle, qui détruit tout ce que vous y mettez! + + reward_rotater: + title: Rotation + desc: Le pivoteur a été débloqué! Il pivote les formes de 90 degrés vers la droite. + + reward_painter: + title: Peintre + desc: >- + Le peintre a été débloqué - Extrayez des pigments de couleur (comme vous le faites avec les formes) et combinez les avec une forme dans un peintre pour les colorier!

PS: Si vous êtes daltonien, je travaille déjà sur une solution! + + reward_mixer: + title: Mixeur de couleurs + desc: Le mixeur a été débloqué - Combinez deux couleurs en utilisant le mélange additif avec ce bâtiment! + + reward_stacker: + title: Combineur + desc: Vous pouvez maintenant combiner deux formes avec le combineur! Les deux entrées sont combinée et si elles peuvent êtres mises l'une à cpôté de l'autre, elles sont fusionnées. Sinon, la forme de droite est placée au dessus de la forme de gauche. + + reward_splitter: + title: Découpeur/Fusionneur + desc: Le balancier multifonctionnel a été débloqué - Il peut être utilisé pour construire de plus grandes usines en découpant et fusionnant les formes sur plusieurs convoyeurs!

+ + reward_tunnel: + title: Tunnel + desc: Le tunnel 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 pivoteur - Elle permet de faire pivoter vers la gauche! Pour le construite, sélectionnez le pivoteur et appuyez sur 'T' pour changer sa variante! + + reward_miner_chainable: + title: Extracteur en série + desc: Vous avez débloqué l'extracteur en série! Il permet de transférer ses resources à d'autres extracteurs pour extraire les ressources plus efficacement! + + reward_underground_belt_tier_2: + title: Tunnel échelon II + desc: Vous avez débloqué une nouvelle variante du tunnel - Elle a une portée plus grande, et vous pouvez également mixer ces tunnels maintenant! + + reward_splitter_compact: + title: Balancier compacte + desc: >- + Vous avez débloqué une variante compacte du balancier - 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 découpeur - Elle permet de de découper les formes en quatres parties à la place de simplement deux! + + reward_painter_double: + title: Double peintre + desc: Vous avez débloqué une variante du peintre - Elle fonctionne comme le peintre de base, mais elle permet de traiter deux formes à la fois en ne consommant qu'une couleur au lieu de deux! + + reward_painter_quad: + title: Quadruple peintre + desc: Vous avez débloqué une variante du peintre - Elle permet de colorier chaque partie d'une forme individuellement! + + reward_storage: + title: Tampon de stockage + desc: Vous avez débloqué une variante de la poubelle - Elle permet de stocker des formes jusqu'à une certaine limite! + + reward_freeplay: + title: Mode libre + desc: Vous l'avez fait! Vous avez débloqué le mode libre! Cela veut dire que dorénavant, les formes sont générées aléatoirement! (Ne vous en faites pas, plus de contenu est prévu pour la version complète!) + + # 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!

PS: Vous ne devriez pas détruires votre usine actuelle - Vous aurez besoin de toutes ces formes plus tard pour débloquer les améliorations! + + 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 + + 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' \ No newline at end of file From e2c3b9dc92e43988d8c0f173d965dcfa0e63eab2 Mon Sep 17 00:00:00 2001 From: tobspr <> Date: Wed, 27 May 2020 08:00:36 +0200 Subject: [PATCH 04/16] Allow changing keybindings in the demo version --- gulp/standalone.js | 7 ++++++- src/js/changelog.js | 3 ++- src/js/core/config.js | 4 ++-- src/js/states/keybindings.js | 8 ++++---- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/gulp/standalone.js b/gulp/standalone.js index 00d2b685..bb02b320 100644 --- a/gulp/standalone.js +++ b/gulp/standalone.js @@ -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" ]) diff --git a/src/js/changelog.js b/src/js/changelog.js index f2744136..44475e63 100644 --- a/src/js/changelog.js +++ b/src/js/changelog.js @@ -1,10 +1,11 @@ export const CHANGELOG = [ { version: "1.0.4", - date: "unreleased", + date: "26.05.2020", entries: [ "Balancing Reduce cost of first painting upgrade, and change 'Shape Processing' to 'Cutting, Rotating & Stacking'", "Tutorial Add dialog after completing level 2 to check out the upgrades tab.", + "Misc Allow changing the keybindings in the demo version", ], }, { diff --git a/src/js/core/config.js b/src/js/core/config.js index 922870d8..99770c4b 100644 --- a/src/js/core/config.js +++ b/src/js/core/config.js @@ -94,7 +94,7 @@ export const globalConfig = { // showChunkBorders: true, // rewardsInstant: true, // allBuildingsUnlocked: true, - upgradesNoCost: true, + // upgradesNoCost: true, // disableUnlockDialog: true, // disableLogicTicks: true, // testClipping: true, @@ -102,7 +102,7 @@ export const globalConfig = { // testTranslations: true, // enableEntityInspector: true, // testAds: true, - disableMapOverview: true, + // disableMapOverview: true, /* dev:end */ }, diff --git a/src/js/states/keybindings.js b/src/js/states/keybindings.js index aa6ec2d6..0f7fcf9e 100644 --- a/src/js/states/keybindings.js +++ b/src/js/states/keybindings.js @@ -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, From 5188c2c1ed6dae89518c2398f798255d2a189b3a Mon Sep 17 00:00:00 2001 From: Modded Gamers Date: Wed, 27 May 2020 08:17:25 -0400 Subject: [PATCH 05/16] add all GH Actions work --- .eslintignore | 11 + .eslintrc.yml | 25 ++ .github/workflows/ci.yml | 41 ++++ package.json | 7 +- yarn.lock | 478 +++++++++++++++++++++++++++++++-------- 5 files changed, 461 insertions(+), 101 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.yml create mode 100644 .github/workflows/ci.yml diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..d3510226 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,11 @@ +artwork/* +build/* +electron/* +gulp/* +node_modules/* +res/* +res_built/* +res_raw/* +tmp_standalone_files/* +tools/* +translations/* diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 00000000..8fd0b51b --- /dev/null +++ b/.eslintrc.yml @@ -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 + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..9b852bf0 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,41 @@ +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 diff --git a/package.json b/package.json index 2e90c019..10584493 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/yarn.lock b/yarn.lock index 7fbd075b..90c6e840 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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== From ac37acc1f87e45cb7e57fe7230b8bdf1798777ba Mon Sep 17 00:00:00 2001 From: Modded Gamers Date: Wed, 27 May 2020 08:18:48 -0400 Subject: [PATCH 06/16] workflow can't be created on cli --- .github/workflows/ci.yml | 41 ---------------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 9b852bf0..00000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,41 +0,0 @@ -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 From a44ff977f418a418cf860c95deffc8d280b94200 Mon Sep 17 00:00:00 2001 From: Modded Gamers <35778371+ModdedGamers@users.noreply.github.com> Date: Wed, 27 May 2020 08:25:25 -0400 Subject: [PATCH 07/16] Create workflow --- .github/workflows/ci.yml | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..3b8e4a08 --- /dev/null +++ b/.github/workflows/ci.yml @@ -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 From d25b7305235f63426ff5d4ee9afef08d2a025383 Mon Sep 17 00:00:00 2001 From: Dimava Date: Wed, 27 May 2020 15:25:30 +0300 Subject: [PATCH 08/16] Make ctrl/shift/alt keubindings changeable --- src/js/game/hud/parts/building_placer.js | 11 +++++++---- src/js/game/hud/parts/mass_selector.js | 4 ++-- src/js/game/key_action_mapper.js | 10 +++++----- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/js/game/hud/parts/building_placer.js b/src/js/game/hud/parts/building_placer.js index fa477dbd..b7330130 100644 --- a/src/js/game/hud/parts/building_placer.js +++ b/src/js/game/hud/parts/building_placer.js @@ -159,14 +159,14 @@ 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; } } @@ -464,13 +464,16 @@ 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 diff --git a/src/js/game/hud/parts/mass_selector.js b/src/js/game/hud/parts/mass_selector.js index ddcf9117..79c119b2 100644 --- a/src/js/game/hud/parts/mass_selector.js +++ b/src/js/game/hud/parts/mass_selector.js @@ -89,7 +89,7 @@ export class HUDMassSelector extends BaseHUDPart { * @param {enumMouseButton} mouseButton */ onMouseDown(pos, mouseButton) { - if (!this.root.app.inputMgr.ctrlIsDown) { + if (!this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectStart).currentlyDown) { return; } @@ -97,7 +97,7 @@ 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(); } diff --git a/src/js/game/key_action_mapper.js b/src/js/game/key_action_mapper.js index 9ab089c3..2423cdb4 100644 --- a/src/js/game/key_action_mapper.js +++ b/src/js/game/key_action_mapper.js @@ -58,15 +58,15 @@ export const KEYMAPPINGS = { }, massSelect: { - massSelectStart: { keyCode: 17, builtin: true }, // CTRL - massSelectSelectMultiple: { keyCode: 16, builtin: true }, // SHIFT + massSelectStart: { keyCode: 17 }, // CTRL + massSelectSelectMultiple: { keyCode: 16 }, // SHIFT 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 }, }; From 96030c9b76f3295d9f197c2a151bc6f9ec0b121a Mon Sep 17 00:00:00 2001 From: tobspr <> Date: Wed, 27 May 2020 14:30:59 +0200 Subject: [PATCH 09/16] Initial support for blueprints (Buggy) --- shapez.code-workspace | 1 + src/css/ingame_hud/buildings_toolbar.scss | 6 +- src/html/index.html | 2 +- src/js/changelog.js | 8 + src/js/core/config.js | 4 +- src/js/core/vector.js | 11 ++ src/js/game/buildings/hub.js | 4 + src/js/game/component.js | 8 + src/js/game/components/belt.js | 4 + src/js/game/components/item_acceptor.js | 26 +++ src/js/game/components/item_ejector.js | 16 ++ src/js/game/components/item_processor.js | 7 + src/js/game/components/miner.js | 6 + .../game/components/replaceable_map_entity.js | 4 + src/js/game/components/static_map_entity.js | 37 +++- src/js/game/components/storage.js | 4 + src/js/game/components/underground_belt.js | 7 + src/js/game/components/unremovable.js | 4 + src/js/game/entity.js | 11 +- src/js/game/hub_goals.js | 4 +- src/js/game/hud/hud.js | 5 +- src/js/game/hud/parts/blueprint.js | 176 ++++++++++++++++++ src/js/game/hud/parts/blueprint_placer.js | 103 ++++++++++ src/js/game/hud/parts/building_placer.js | 3 + src/js/game/hud/parts/mass_selector.js | 94 +++++++--- src/js/game/hud/parts/tutorial_hints.js | 3 +- src/js/game/key_action_mapper.js | 1 + src/js/game/logic.js | 2 + src/js/game/map.js | 11 ++ src/js/game/meta_building.js | 4 + src/js/game/themes/dark.json | 2 +- src/js/game/themes/light.json | 4 + src/js/savegame/savegame.js | 26 ++- .../savegame/savegame_interface_registry.js | 2 + src/js/savegame/savegame_typedefs.js | 11 +- src/js/savegame/schemas/1001.js | 52 ++++++ src/js/savegame/schemas/1001.json | 5 + src/js/savegame/serializer_internal.js | 2 +- src/js/states/main_menu.js | 12 +- src/js/states/preload.js | 5 + translations/base-en.yaml | 13 +- 41 files changed, 633 insertions(+), 77 deletions(-) create mode 100644 src/js/game/hud/parts/blueprint.js create mode 100644 src/js/game/hud/parts/blueprint_placer.js create mode 100644 src/js/savegame/schemas/1001.js create mode 100644 src/js/savegame/schemas/1001.json diff --git a/shapez.code-workspace b/shapez.code-workspace index e0766264..29dae2a2 100644 --- a/shapez.code-workspace +++ b/shapez.code-workspace @@ -8,6 +8,7 @@ "files.exclude": { "**/build": true, "**/node_modules": true, + "**/tmp_standalone_files": true, "**/typedefs_gen": true }, "vetur.format.defaultFormatter.js": "vscode-typescript", diff --git a/src/css/ingame_hud/buildings_toolbar.scss b/src/css/ingame_hud/buildings_toolbar.scss index d9f91fcc..a16acfb3 100644 --- a/src/css/ingame_hud/buildings_toolbar.scss +++ b/src/css/ingame_hud/buildings_toolbar.scss @@ -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; diff --git a/src/html/index.html b/src/html/index.html index ffcab1d7..b1d89377 100644 --- a/src/html/index.html +++ b/src/html/index.html @@ -1,7 +1,7 @@ - shapez.io - Build your own shape factory! + shapez.io - Build automated factories to build, combine and color shapes! diff --git a/src/js/changelog.js b/src/js/changelog.js index 44475e63..10c78d3a 100644 --- a/src/js/changelog.js +++ b/src/js/changelog.js @@ -1,4 +1,12 @@ export const CHANGELOG = [ + { + version: "1.1.0", + date: "unreleased", + entries: [ + "UX Added background to toolbar to increase contrast", + "UX Added confirmation when deleting more than 500 buildings at a time", + ], + }, { version: "1.0.4", date: "26.05.2020", diff --git a/src/js/core/config.js b/src/js/core/config.js index 99770c4b..f5bdbf76 100644 --- a/src/js/core/config.js +++ b/src/js/core/config.js @@ -93,7 +93,7 @@ export const globalConfig = { // disableZoomLimits: true, // showChunkBorders: true, // rewardsInstant: true, - // allBuildingsUnlocked: true, + allBuildingsUnlocked: true, // upgradesNoCost: true, // disableUnlockDialog: true, // disableLogicTicks: true, @@ -103,6 +103,8 @@ export const globalConfig = { // enableEntityInspector: true, // testAds: true, // disableMapOverview: true, + disableTutorialHints: true, + disableUpgradeNotification: true, /* dev:end */ }, diff --git a/src/js/core/vector.js b/src/js/core/vector.js index 2bd6cfe9..2a02f75d 100644 --- a/src/js/core/vector.js +++ b/src/js/core/vector.js @@ -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 diff --git a/src/js/game/buildings/hub.js b/src/js/game/buildings/hub.js index b7b960de..49d95005 100644 --- a/src/js/game/buildings/hub.js +++ b/src/js/game/buildings/hub.js @@ -24,6 +24,10 @@ export class MetaHubBuilding extends MetaBuilding { return false; } + getBlueprintSprite() { + return null; + } + /** * Creates the entity at the given location * @param {Entity} entity diff --git a/src/js/game/component.js b/src/js/game/component.js index 8c492351..1d44d60f 100644 --- a/src/js/game/component.js +++ b/src/js/game/component.js @@ -17,6 +17,14 @@ export class Component extends BasicSerializableObject { return {}; } + /** + * Should duplicate the component but without its contents + * @returns {object} + */ + duplicateWithoutContents() { + abstract; + } + /* dev:start */ /** diff --git a/src/js/game/components/belt.js b/src/js/game/components/belt.js index 9d64187c..dcac6ecb 100644 --- a/src/js/game/components/belt.js +++ b/src/js/game/components/belt.js @@ -18,6 +18,10 @@ export class BeltComponent extends Component { }; } + duplicateWithoutContents() { + return new BeltComponent({ direction: this.direction }); + } + /** * * @param {object} param0 diff --git a/src/js/game/components/item_acceptor.js b/src/js/game/components/item_acceptor.js index d5546d4b..d9505d18 100644 --- a/src/js/game/components/item_acceptor.js +++ b/src/js/game/components/item_acceptor.js @@ -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 diff --git a/src/js/game/components/item_ejector.js b/src/js/game/components/item_ejector.js index 5cf96754..d5881a7d 100644 --- a/src/js/game/components/item_ejector.js +++ b/src/js/game/components/item_ejector.js @@ -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 diff --git a/src/js/game/components/item_processor.js b/src/js/game/components/item_processor.js index 0c4e90c6..eab51ae2 100644 --- a/src/js/game/components/item_processor.js +++ b/src/js/game/components/item_processor.js @@ -48,6 +48,13 @@ export class ItemProcessorComponent extends Component { }; } + duplicateWithoutContents() { + return new ItemProcessorComponent({ + processorType: this.type, + inputsPerCharge: this.inputsPerCharge, + }); + } + /** * * @param {object} param0 diff --git a/src/js/game/components/miner.js b/src/js/game/components/miner.js index e08d2906..57de7e2f 100644 --- a/src/js/game/components/miner.js +++ b/src/js/game/components/miner.js @@ -19,6 +19,12 @@ export class MinerComponent extends Component { }; } + duplicateWithoutContents() { + return new MinerComponent({ + chainable: this.chainable, + }); + } + /** */ constructor({ chainable = false }) { diff --git a/src/js/game/components/replaceable_map_entity.js b/src/js/game/components/replaceable_map_entity.js index e6fd95d5..78861caf 100644 --- a/src/js/game/components/replaceable_map_entity.js +++ b/src/js/game/components/replaceable_map_entity.js @@ -8,4 +8,8 @@ export class ReplaceableMapEntityComponent extends Component { static getId() { return "ReplaceableMapEntity"; } + + duplicateWithoutContents() { + return new ReplaceableMapEntityComponent(); + } } diff --git a/src/js/game/components/static_map_entity.js b/src/js/game/components/static_map_entity.js index 6f9abb87..ed616213 100644 --- a/src/js/game/components/static_map_entity.js +++ b/src/js/game/components/static_map_entity.js @@ -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 diff --git a/src/js/game/components/storage.js b/src/js/game/components/storage.js index e024d522..69f4e367 100644 --- a/src/js/game/components/storage.js +++ b/src/js/game/components/storage.js @@ -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 diff --git a/src/js/game/components/underground_belt.js b/src/js/game/components/underground_belt.js index e581ebe9..4fcbbb48 100644 --- a/src/js/game/components/underground_belt.js +++ b/src/js/game/components/underground_belt.js @@ -23,6 +23,13 @@ export class UndergroundBeltComponent extends Component { }; } + duplicateWithoutContents() { + return new UndergroundBeltComponent({ + mode: this.mode, + tier: this.tier, + }); + } + /** * * @param {object} param0 diff --git a/src/js/game/components/unremovable.js b/src/js/game/components/unremovable.js index 17e9f36b..f3864cf8 100644 --- a/src/js/game/components/unremovable.js +++ b/src/js/game/components/unremovable.js @@ -8,4 +8,8 @@ export class UnremovableComponent extends Component { static getSchema() { return {}; } + + duplicateWithoutContents() { + return new UnremovableComponent(); + } } diff --git a/src/js/game/entity.js b/src/js/game/entity.js index 50f4cae5..dc849851 100644 --- a/src/js/game/entity.js +++ b/src/js/game/entity.js @@ -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; } /** diff --git a/src/js/game/hub_goals.js b/src/js/game/hub_goals.js index f1fc15c9..a6f24284 100644 --- a/src/js/game/hub_goals.js +++ b/src/js/game/hub_goals.js @@ -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(); } }); diff --git a/src/js/game/hud/hud.js b/src/js/game/hud/hud.js index 2d317b7f..2294b4f1 100644 --- a/src/js/game/hud/hud.js +++ b/src/js/game/hud/hud.js @@ -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]>} */ (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]]) { diff --git a/src/js/game/hud/parts/blueprint.js b/src/js/game/hud/parts/blueprint.js new file mode 100644 index 00000000..f6dccc4c --- /dev/null +++ b/src/js/game/hud/parts/blueprint.js @@ -0,0 +1,176 @@ +import { GameRoot } from "../../root"; +import { Vector } from "../../../core/vector"; +import { Entity } from "../../entity"; +import { DrawParameters } from "../../../core/draw_parameters"; +import { StaticMapEntityComponent } from "../../components/static_map_entity"; +import { createLogger } from "../../../core/logging"; +import { Loader } from "../../../core/loader"; + +const logger = createLogger("blueprint"); + +export class Blueprint { + /** + * @param {Array} entities + */ + constructor(entities) { + this.entities = entities; + } + + /** + * @param {GameRoot} root + * @param {Array} 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); + } + + /** + * + * @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; + } + + /** + * @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; + } + + /** + * @param {GameRoot} root + * @param {Vector} tile + */ + tryPlace(root, tile) { + 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; + } +} diff --git a/src/js/game/hud/parts/blueprint_placer.js b/src/js/game/hud/parts/blueprint_placer.js new file mode 100644 index 00000000..32993ffc --- /dev/null +++ b/src/js/game/hud/parts/blueprint_placer.js @@ -0,0 +1,103 @@ +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} */ + 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); + + 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; + } + + console.log("down"); + const worldPos = this.root.camera.screenToWorld(pos); + const tile = worldPos.toTileSpace(); + if (blueprint.tryPlace(this.root, tile)) { + if (!this.root.app.inputMgr.shiftIsDown) { + this.currentBlueprint.set(null); + } + } + } + + onMouseMove() { + // Prevent movement while blueprint is selected + if (this.currentBlueprint.get()) { + return STOP_PROPAGATION; + } + } + + /** + * @param {Array} uids + */ + onBuildingsSelected(uids) { + if (uids.length === 0) { + return; + } + this.currentBlueprint.set(Blueprint.fromUids(this.root, uids)); + } + + /** + * + * @param {DrawParameters} parameters + */ + draw(parameters) { + const blueprint = this.currentBlueprint.get(); + if (!blueprint) { + return; + } + const mousePosition = this.root.app.mousePosition; + if (!mousePosition) { + // Not on screen + return; + } + + const worldPos = this.root.camera.screenToWorld(mousePosition); + const tile = worldPos.toTileSpace(); + blueprint.draw(parameters, tile); + } +} diff --git a/src/js/game/hud/parts/building_placer.js b/src/js/game/hud/parts/building_placer.js index fa477dbd..39fae8c9 100644 --- a/src/js/game/hud/parts/building_placer.js +++ b/src/js/game/hud/parts/building_placer.js @@ -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); @@ -255,6 +257,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()); diff --git a/src/js/game/hud/parts/mass_selector.js b/src/js/game/hud/parts/mass_selector.js index ddcf9117..3c251d66 100644 --- a/src/js/game/hud/parts/mass_selector.js +++ b/src/js/game/hud/parts/mass_selector.js @@ -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("", removalKeybinding) + .replace("", copyKeybinding) .replace("", 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,24 +71,50 @@ 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( + "", + "" + 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 @@ -99,7 +131,7 @@ export class HUDMassSelector extends BaseHUDPart { if (!this.root.app.inputMgr.shiftIsDown) { // 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(); }); } } diff --git a/src/js/game/hud/parts/tutorial_hints.js b/src/js/game/hud/parts/tutorial_hints.js index 853d054f..27fd5530 100644 --- a/src/js/game/hud/parts/tutorial_hints.js +++ b/src/js/game/hud/parts/tutorial_hints.js @@ -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 diff --git a/src/js/game/key_action_mapper.js b/src/js/game/key_action_mapper.js index 9ab089c3..34df29c8 100644 --- a/src/js/game/key_action_mapper.js +++ b/src/js/game/key_action_mapper.js @@ -60,6 +60,7 @@ export const KEYMAPPINGS = { massSelect: { massSelectStart: { keyCode: 17, builtin: true }, // CTRL massSelectSelectMultiple: { keyCode: 16, builtin: true }, // SHIFT + massSelectCopy: { keyCode: key("C") }, confirmMassDelete: { keyCode: key("X") }, }, diff --git a/src/js/game/logic.js b/src/js/game/logic.js index c96364da..dc89f8c2 100644 --- a/src/js/game/logic.js +++ b/src/js/game/logic.js @@ -60,6 +60,7 @@ export class GameLogic { origin, tileSize: building.getDimensions(variant), rotation, + blueprintSpriteKey: "", }); const rect = checker.getTileSpaceBounds(); @@ -168,6 +169,7 @@ export class GameLogic { origin, tileSize: building.getDimensions(variant), rotation, + blueprintSpriteKey: "", }); const rect = checker.getTileSpaceBounds(); diff --git a/src/js/game/map.js b/src/js/game/map.js index 3fd82844..ef745c6d 100644 --- a/src/js/game/map.js +++ b/src/js/game/map.js @@ -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 diff --git a/src/js/game/meta_building.js b/src/js/game/meta_building.js index ad360ac0..8753aac5 100644 --- a/src/js/game/meta_building.js +++ b/src/js/game/meta_building.js @@ -154,6 +154,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 +169,7 @@ export class MetaBuilding { originalRotation, tileSize: this.getDimensions(variant).copy(), silhouetteColor: this.getSilhouetteColor(), + blueprintSpriteKey: blueprintSprite ? blueprintSprite.spriteName : "", }) ); diff --git a/src/js/game/themes/dark.json b/src/js/game/themes/dark.json index caf28bfb..fa4c22a8 100644 --- a/src/js/game/themes/dark.json +++ b/src/js/game/themes/dark.json @@ -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", diff --git a/src/js/game/themes/light.json b/src/js/game/themes/light.json index 4837574c..59e9e58f 100644 --- a/src/js/game/themes/light.json +++ b/src/js/game/themes/light.json @@ -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", diff --git a/src/js/savegame/savegame.js b/src/js/savegame/savegame.js index 8b9d2b3b..8027c188 100644 --- a/src/js/savegame/savegame.js +++ b/src/js/savegame/savegame.js @@ -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; diff --git a/src/js/savegame/savegame_interface_registry.js b/src/js/savegame/savegame_interface_registry.js index 6ad22a42..2560b23e 100644 --- a/src/js/savegame/savegame_interface_registry.js +++ b/src/js/savegame/savegame_interface_registry.js @@ -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.} */ const interfaces = { 1000: SavegameInterface_V1000, + 1001: SavegameInterface_V1001, }; const logger = createLogger("savegame_interface_registry"); diff --git a/src/js/savegame/savegame_typedefs.js b/src/js/savegame/savegame_typedefs.js index ca72d856..821306a4 100644 --- a/src/js/savegame/savegame_typedefs.js +++ b/src/js/savegame/savegame_typedefs.js @@ -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 + * entities: Array * }} SerializedGame */ diff --git a/src/js/savegame/schemas/1001.js b/src/js/savegame/schemas/1001.js new file mode 100644 index 00000000..7604dec4 --- /dev/null +++ b/src/js/savegame/schemas/1001.js @@ -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"); + } + } + } + } + } +} diff --git a/src/js/savegame/schemas/1001.json b/src/js/savegame/schemas/1001.json new file mode 100644 index 00000000..6682f615 --- /dev/null +++ b/src/js/savegame/schemas/1001.json @@ -0,0 +1,5 @@ +{ + "type": "object", + "required": [], + "additionalProperties": true +} diff --git a/src/js/savegame/serializer_internal.js b/src/js/savegame/serializer_internal.js index 3eb0f72b..ec761beb 100644 --- a/src/js/savegame/serializer_internal.js +++ b/src/js/savegame/serializer_internal.js @@ -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); diff --git a/src/js/states/main_menu.js b/src/js/states/main_menu.js index 9dd18909..d95f520e 100644 --- a/src/js/states/main_menu.js +++ b/src/js/states/main_menu.js @@ -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 diff --git a/src/js/states/preload.js b/src/js/states/preload.js index 43c84eb0..29d5bdd4 100644 --- a/src/js/states/preload.js +++ b/src/js/states/preload.js @@ -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 => { diff --git a/translations/base-en.yaml b/translations/base-en.yaml index 2318c342..889e6583 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -172,6 +172,11 @@ dialogs: All shapes you produce can be used to unlock upgrades - Don't destroy your old factories! The upgrades tab can be found on the top right corner of the screen. + massDeleteConfirm: + title: Confirm delete + desc: >- + You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? + 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 to remove selected buildings and to cancel. + # Mass select information, this is when you hold CTRL and then drag with your mouse + # to select multiple buildings + massSelect: + infoText: Press to copy, to remove and to cancel. # The "Upgrades" window shop: From f0895335c552b4d99249bcf8b7dafa9f7647c412 Mon Sep 17 00:00:00 2001 From: Dimava Date: Wed, 27 May 2020 15:56:41 +0300 Subject: [PATCH 10/16] Make CycleBuildings work properly --- src/js/game/hud/parts/buildings_toolbar.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/js/game/hud/parts/buildings_toolbar.js b/src/js/game/hud/parts/buildings_toolbar.js index 86c99a01..a03f0f6f 100644 --- a/src/js/game/hud/parts/buildings_toolbar.js +++ b/src/js/game/hud/parts/buildings_toolbar.js @@ -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 + 1) % 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); From 27e9e78bafe800d8227ca924b432afffcc0e7b20 Mon Sep 17 00:00:00 2001 From: Dimava Date: Wed, 27 May 2020 15:58:33 +0300 Subject: [PATCH 11/16] Make CycleBuildings select last used item when empty --- src/js/game/hud/parts/buildings_toolbar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/game/hud/parts/buildings_toolbar.js b/src/js/game/hud/parts/buildings_toolbar.js index a03f0f6f..691185c9 100644 --- a/src/js/game/hud/parts/buildings_toolbar.js +++ b/src/js/game/hud/parts/buildings_toolbar.js @@ -110,8 +110,8 @@ export class HUDBuildingsToolbar extends BaseHUDPart { cycleBuildings() { let newIndex = this.lastSelectedIndex; - for (let i = 0; i < toolbarBuildings.length; ++i) { - newIndex = (newIndex + 1) % toolbarBuildings.length; + 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) { From 8b36c7bcc0ddd5999834e508ce3f4b290b4ef7ab Mon Sep 17 00:00:00 2001 From: tobspr <> Date: Wed, 27 May 2020 15:03:36 +0200 Subject: [PATCH 12/16] Further blueprint improvements --- src/css/states/changelog.scss | 3 +- src/js/changelog.js | 15 +-- src/js/core/config.js | 2 +- src/js/core/input_distributor.js | 31 ------ src/js/core/input_receiver.js | 3 - src/js/game/buildings/miner.js | 17 --- src/js/game/game_system_with_filter.js | 3 +- src/js/game/hud/parts/blueprint.js | 114 ++++++++++++-------- src/js/game/hud/parts/blueprint_placer.js | 19 +++- src/js/game/hud/parts/building_placer.js | 22 +++- src/js/game/hud/parts/keybinding_overlay.js | 20 ++-- src/js/game/key_action_mapper.js | 1 + src/js/game/logic.js | 32 +++--- src/js/game/meta_building.js | 13 --- src/js/game/root.js | 7 ++ src/js/game/systems/miner.js | 7 ++ translations/base-en.yaml | 2 + 17 files changed, 159 insertions(+), 152 deletions(-) diff --git a/src/css/states/changelog.scss b/src/css/states/changelog.scss index 69b7864c..8302da2c 100644 --- a/src/css/states/changelog.scss +++ b/src/css/states/changelog.scss @@ -20,8 +20,7 @@ @include SuperSmallText; @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); diff --git a/src/js/changelog.js b/src/js/changelog.js index 10c78d3a..fe398aae 100644 --- a/src/js/changelog.js +++ b/src/js/changelog.js @@ -3,24 +3,27 @@ export const CHANGELOG = [ version: "1.1.0", date: "unreleased", entries: [ - "UX Added background to toolbar to increase contrast", - "UX Added confirmation when deleting more than 500 buildings at a time", + "Allow changing all keybindings, including CTRL, ALT and SHIFT", + "Allow holding SHIFT to rotate counter clockwise", + "Added confirmation when deleting more than 500 buildings at a time", + "Added background to toolbar to increase contrast", + "Allow placing extractors anywhere again, but they don't work at all if not placed on a resource", ], }, { version: "1.0.4", date: "26.05.2020", entries: [ - "Balancing Reduce cost of first painting upgrade, and change 'Shape Processing' to 'Cutting, Rotating & Stacking'", - "Tutorial Add dialog after completing level 2 to check out the upgrades tab.", - "Misc Allow changing the keybindings in the demo version", + "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: [ - "Balancing 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.", ], }, { diff --git a/src/js/core/config.js b/src/js/core/config.js index f5bdbf76..953af4e7 100644 --- a/src/js/core/config.js +++ b/src/js/core/config.js @@ -40,7 +40,7 @@ export const globalConfig = { // Map mapChunkSize: 16, - mapChunkPrerenderMinZoom: 1.3, + mapChunkPrerenderMinZoom: 1.15, mapChunkOverviewMinZoom: 0.7, // Belt speeds diff --git a/src/js/core/input_distributor.js b/src/js/core/input_distributor.js index e0152774..4ed1429c 100644 --- a/src/js/core/input_distributor.js +++ b/src/js/core/input_distributor.js @@ -23,10 +23,6 @@ export class InputDistributor { /** @type {Array} */ 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, diff --git a/src/js/core/input_receiver.js b/src/js/core/input_receiver.js index 1a373905..ae54f24d 100644 --- a/src/js/core/input_receiver.js +++ b/src/js/core/input_receiver.js @@ -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(); diff --git a/src/js/game/buildings/miner.js b/src/js/game/buildings/miner.js index 25788917..ed87bc85 100644 --- a/src/js/game/buildings/miner.js +++ b/src/js/game/buildings/miner.js @@ -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 diff --git a/src/js/game/game_system_with_filter.js b/src/js/game/game_system_with_filter.js index 52f8ddfe..24a719fb 100644 --- a/src/js/game/game_system_with_filter.js +++ b/src/js/game/game_system_with_filter.js @@ -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); } /** @@ -175,7 +176,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); } diff --git a/src/js/game/hud/parts/blueprint.js b/src/js/game/hud/parts/blueprint.js index f6dccc4c..59271469 100644 --- a/src/js/game/hud/parts/blueprint.js +++ b/src/js/game/hud/parts/blueprint.js @@ -1,10 +1,9 @@ -import { GameRoot } from "../../root"; +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 { DrawParameters } from "../../../core/draw_parameters"; -import { StaticMapEntityComponent } from "../../components/static_map_entity"; -import { createLogger } from "../../../core/logging"; -import { Loader } from "../../../core/loader"; +import { GameRoot } from "../../root"; const logger = createLogger("blueprint"); @@ -17,6 +16,7 @@ export class Blueprint { } /** + * Creates a new blueprint from the given entity uids * @param {GameRoot} root * @param {Array} uids */ @@ -48,7 +48,7 @@ export class Blueprint { } /** - * + * Draws the blueprint at the given origin * @param {DrawParameters} parameters */ draw(parameters, tile) { @@ -93,6 +93,31 @@ export class Blueprint { } /** + * 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 */ @@ -123,54 +148,57 @@ export class Blueprint { } /** + * Attempts to place the blueprint at the given tile * @param {GameRoot} root * @param {Vector} tile */ tryPlace(root, tile) { - 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) { + 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) { - 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; - } + if (contents && !contents.components.ReplaceableMapEntity) { + placeable = false; + break placementCheck; } } } - const clone = entity.duplicateWithoutContents(); - clone.components.StaticMapEntity.origin.addInplace(tile); + 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; + } + } + } + } - root.map.placeStaticEntity(clone); - root.entityMgr.registerEntity(clone); - anyPlaced = true; + const clone = entity.duplicateWithoutContents(); + clone.components.StaticMapEntity.origin.addInplace(tile); + + root.map.placeStaticEntity(clone); + root.entityMgr.registerEntity(clone); + anyPlaced = true; + } } - } - return anyPlaced; + return anyPlaced; + }); } } diff --git a/src/js/game/hud/parts/blueprint_placer.js b/src/js/game/hud/parts/blueprint_placer.js index 32993ffc..a3ff0f14 100644 --- a/src/js/game/hud/parts/blueprint_placer.js +++ b/src/js/game/hud/parts/blueprint_placer.js @@ -21,6 +21,7 @@ export class HUDBlueprintPlacer extends BaseHUDPart { 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); @@ -54,13 +55,13 @@ export class HUDBlueprintPlacer extends BaseHUDPart { return; } - console.log("down"); const worldPos = this.root.camera.screenToWorld(pos); const tile = worldPos.toTileSpace(); if (blueprint.tryPlace(this.root, tile)) { - if (!this.root.app.inputMgr.shiftIsDown) { - this.currentBlueprint.set(null); - } + // This actually feels weird + // if (!this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeMultiple).currentlyDown) { + // this.currentBlueprint.set(null); + // } } } @@ -81,6 +82,16 @@ export class HUDBlueprintPlacer extends BaseHUDPart { 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 diff --git a/src/js/game/hud/parts/building_placer.js b/src/js/game/hud/parts/building_placer.js index 1e09dbd4..ab3ebae4 100644 --- a/src/js/game/hud/parts/building_placer.js +++ b/src/js/game/hud/parts/building_placer.js @@ -161,14 +161,19 @@ export class HUDBuildingPlacer extends BaseHUDPart { if ( metaBuilding && metaBuilding.getRotateAutomaticallyWhilePlacing(this.currentVariant.get()) && - !this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placementDisableAutoOrientation).currentlyDown + !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.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeInverse).currentlyDown) { + if ( + this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeInverse) + .currentlyDown + ) { this.currentBaseRotation = (180 + this.currentBaseRotation) % 360; } } @@ -389,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; } @@ -468,8 +478,10 @@ export class HUDBuildingPlacer extends BaseHUDPart { // Succesfully placed if ( - metaBuilding.getFlipOrientationAfterPlacement() && - !this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placementDisableAutoOrientation).currentlyDown + metaBuilding.getFlipOrientationAfterPlacement() && + !this.root.keyMapper.getBinding( + KEYMAPPINGS.placementModifiers.placementDisableAutoOrientation + ).currentlyDown ) { this.currentBaseRotation = (180 + this.currentBaseRotation) % 360; } diff --git a/src/js/game/hud/parts/keybinding_overlay.js b/src/js/game/hud/parts/keybinding_overlay.js index b143186a..300c0885 100644 --- a/src/js/game/hud/parts/keybinding_overlay.js +++ b/src/js/game/hud/parts/keybinding_overlay.js @@ -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 {
- ⇧ ${T.global.keys.shift} + ⇧ ${getKeycode( + KEYMAPPINGS.placementModifiers.placeMultiple + )}
` @@ -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() {} } diff --git a/src/js/game/key_action_mapper.js b/src/js/game/key_action_mapper.js index acc78024..2c575501 100644 --- a/src/js/game/key_action_mapper.js +++ b/src/js/game/key_action_mapper.js @@ -53,6 +53,7 @@ export const KEYMAPPINGS = { placement: { abortBuildingPlacement: { keyCode: key("Q") }, rotateWhilePlacing: { keyCode: key("R") }, + rotateInverseModifier: { keyCode: 16 }, // SHIFT cycleBuildingVariants: { keyCode: key("T") }, cycleBuildings: { keyCode: 9 }, // TAB }, diff --git a/src/js/game/logic.js b/src/js/game/logic.js index dc89f8c2..90597e52 100644 --- a/src/js/game/logic.js +++ b/src/js/game/logic.js @@ -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"); @@ -132,17 +133,6 @@ export class GameLogic { return false; } - if ( - !building.performAdditionalPlacementChecks(this.root, { - origin, - rotation, - rotationVariant, - variant, - }) - ) { - return false; - } - return this.isAreaFreeToBuild({ origin, rotation, @@ -202,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 diff --git a/src/js/game/meta_building.js b/src/js/game/meta_building.js index 8753aac5..262a33cb 100644 --- a/src/js/game/meta_building.js +++ b/src/js/game/meta_building.js @@ -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 diff --git a/src/js/game/root.js b/src/js/game/root.js index 0c4e6792..91efd137 100644 --- a/src/js/game/root.js +++ b/src/js/game/root.js @@ -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 diff --git a/src/js/game/systems/miner.js b/src/js/game/systems/miner.js index 4ecf1e2d..5420cf36 100644 --- a/src/js/game/systems/miner.js +++ b/src/js/game/systems/miner.js @@ -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])) { diff --git a/translations/base-en.yaml b/translations/base-en.yaml index 889e6583..c12e81e9 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -557,6 +557,8 @@ keybindings: abortBuildingPlacement: Abort Placement rotateWhilePlacing: Rotate + rotateInverseModifier: >- + Modifier: Rotate CCW instead cycleBuildingVariants: Cycle Variants confirmMassDelete: Confirm Mass Delete cycleBuildings: Cycle Buildings From 9ba260eabbe22bb59f5f48a713ada6115bdaee47 Mon Sep 17 00:00:00 2001 From: tobspr <> Date: Wed, 27 May 2020 15:25:17 +0200 Subject: [PATCH 13/16] Further performance improvements --- src/js/changelog.js | 1 + src/js/game/game_system_with_filter.js | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/js/changelog.js b/src/js/changelog.js index fe398aae..e915e831 100644 --- a/src/js/changelog.js +++ b/src/js/changelog.js @@ -8,6 +8,7 @@ export const CHANGELOG = [ "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", ], }, { diff --git a/src/js/game/game_system_with_filter.js b/src/js/game/game_system_with_filter.js index 24a719fb..d1fddc7f 100644 --- a/src/js/game/game_system_with_filter.js +++ b/src/js/game/game_system_with_filter.js @@ -160,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); + } + } } /** @@ -187,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); From a9e592b77f155799777d171c658a2d62cbdc6299 Mon Sep 17 00:00:00 2001 From: tobspr <> Date: Wed, 27 May 2020 15:45:43 +0200 Subject: [PATCH 14/16] Minor improvements --- src/js/application.js | 44 ++++++++++++++++----------------- src/js/changelog.js | 5 ++-- src/js/core/read_write_proxy.js | 28 ++++++++++----------- src/js/game/camera.js | 3 +-- src/js/states/ingame.js | 18 +++++++------- translations/base-en.yaml | 3 ++- 6 files changed, 50 insertions(+), 51 deletions(-) diff --git a/src/js/application.js b/src/js/application.js index 27be4b1c..d337f94a 100644 --- a/src/js/application.js +++ b/src/js/application.js @@ -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"); diff --git a/src/js/changelog.js b/src/js/changelog.js index e915e831..9eced091 100644 --- a/src/js/changelog.js +++ b/src/js/changelog.js @@ -3,12 +3,13 @@ export const CHANGELOG = [ version: "1.1.0", date: "unreleased", entries: [ - "Allow changing all keybindings, including CTRL, ALT and SHIFT", "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", + "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)", ], }, { diff --git a/src/js/core/read_write_proxy.js b/src/js/core/read_write_proxy.js index 4a10f140..ee568dc6 100644 --- a/src/js/core/read_write_proxy.js +++ b/src/js/core/read_write_proxy.js @@ -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) diff --git a/src/js/game/camera.js b/src/js/game/camera.js index 7fb25b32..f0efaba1 100644 --- a/src/js/game/camera.js +++ b/src/js/game/camera.js @@ -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"); diff --git a/src/js/states/ingame.js b/src/js/states/ingame.js index 6307a22c..e6ed0791 100644 --- a/src/js/states/ingame.js +++ b/src/js/states/ingame.js @@ -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() { diff --git a/translations/base-en.yaml b/translations/base-en.yaml index c12e81e9..dfc73801 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -522,7 +522,7 @@ keybindings: general: Application ingame: Game placement: Placement - massSelect: Mass Delete + massSelect: Mass Select buildings: Building Shortcuts placementModifiers: Placement Modifiers @@ -565,6 +565,7 @@ keybindings: massSelectStart: Hold and drag to start massSelectSelectMultiple: Select multiple areas + massSelectCopy: Copy area placementDisableAutoOrientation: Disable automatic orientation placeMultiple: Stay in placement mode From 3c37d406f2bd3c5459c2fe909eb1b62badfd029c Mon Sep 17 00:00:00 2001 From: tobspr <> Date: Wed, 27 May 2020 15:47:47 +0200 Subject: [PATCH 15/16] Add blueprints to changelog --- src/js/changelog.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/js/changelog.js b/src/js/changelog.js index 9eced091..34daacb3 100644 --- a/src/js/changelog.js +++ b/src/js/changelog.js @@ -3,6 +3,7 @@ export const CHANGELOG = [ version: "1.1.0", date: "unreleased", entries: [ + "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", From bafb7c99dd3786244a41a62538426be026df53bf Mon Sep 17 00:00:00 2001 From: tobspr <> Date: Wed, 27 May 2020 16:06:48 +0200 Subject: [PATCH 16/16] Bump version and fix small font --- src/css/states/changelog.scss | 2 +- src/css/states/preload.scss | 2 +- version | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/css/states/changelog.scss b/src/css/states/changelog.scss index 8302da2c..109f1d36 100644 --- a/src/css/states/changelog.scss +++ b/src/css/states/changelog.scss @@ -17,7 +17,7 @@ } .changes { - @include SuperSmallText; + @include PlainText; @include S(padding-left, 20px); strong { color: #aaa; diff --git a/src/css/states/preload.scss b/src/css/states/preload.scss index 075a363f..68a268e1 100644 --- a/src/css/states/preload.scss +++ b/src/css/states/preload.scss @@ -27,7 +27,7 @@ } .changes { - @include SuperSmallText; + @include PlainText; @include S(padding-left, 15px); strong { background: $colorBlueBright; diff --git a/version b/version index a6a3a43c..1cc5f657 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.0.4 \ No newline at end of file +1.1.0 \ No newline at end of file